Scalable SVG Masks (Clipping Paths) for Video Elements in HTML/CSS – Even in Safari

Scalable SVG Masks (Clipping Paths) for Video Elements in HTML/CSS – Even in Safari

Adding a clipping path to a video element in HTML/CSS can be a challenging task, especially when dealing with browser inconsistencies. Safari, for example, doesn’t fully support clip-path applied directly to video elements.

Why does this matter? In modern web design, custom clipping paths allow you to create unique, dynamic visuals that elevate user experience. However, achieving this with video elements often requires creative workarounds due to limited browser support.

After some trial and error, I discovered a robust solution that leverages SVG clipping paths with clipPathUnits="objectBoundingBox". This approach ensures that the clipping path scales properly with the video’s dimensions. The critical piece of this solution is the transform applied to the <path>, which ensures the clipping path works as intended.

Here’s the code example:

function Diamond({
  className,
  style
}: {
  className?: string;
  style?: CSSProperties;
}) {
  return (
    <div
      className={classNames(
        'tw-relative tw-aspect-[220/191] tw-flex tw-justify-center tw-items-center',
        className
      )}
      style={style}
    >
      <svg width="0" height="0" className="tw-absolute tw-pointer-events-none">
        <defs>
          <clipPath id="diamondShape" clipPathUnits="objectBoundingBox">
            <path
              d="M47.373 10.77A21.889 21.889 0 0164.185 2.9h91.63a21.887 21.887 0 0116.812 7.87l39.599 47.493c6.991 8.384 6.727 20.636-.619 28.712l-85.414 93.906c-8.683 9.546-23.703 9.546-32.386 0L8.393 86.975C1.047 78.9.783 66.647 7.774 58.263l39.599-47.494z"
              transform={`scale(${1 / 220}, ${1 / 191})`}
            />
          </clipPath>
        </defs>
      </svg>

      <object
        className="tw-block tw-w-full tw-h-full tw-media-adjust-cover"
        style={{ clipPath: 'url(#diamondShape)' }}
      >
        <video src="videos/2608621.webm" autoPlay loop muted playsInline />
      </object>
    </div>
  );
}

Key Details of the Solution:

SVG with clipPathUnits:

The clipping path is defined in an SVG using the objectBoundingBox units, which are normalized to the bounding box of the element (values from 0 to 1). This allows the path to scale proportionally with the target element's dimensions.

Critical Use of transform:

Without the transform attribute in the <path>, the clipping path will not work correctly. The scale(${1 / width}, ${1 / height}) transformation adjusts the normalized values to match the aspect ratio of the clipping path (220×191 in this example).

Why it’s crucial: The transform bridges the gap between the SVG's native coordinate system and the objectBoundingBox scaling. By default, the coordinate system assumes a square (1×1) bounding box, which would distort the path for non-square elements. The scale operation rescales the clipping path to match the actual aspect ratio of the element, ensuring accurate rendering.

Debugging Tip: If the path doesn’t align with your element, verify the aspect ratio and adjust the scaling values accordingly. For example, if your element’s dimensions are 300×150, the transform should use scale(${1 / 300}, ${1 / 150}) which calculates to scale(0.00333, 0.00667).

Video in an Object Element:

Instead of applying clip-path directly to the <video> (which is poorly supported in some browsers, including Safari), the video is wrapped in an <object>. The clipPath is then applied to the <object>, ensuring consistent rendering.

Dynamic Scaling with Aspect Ratio:

The tw-aspect-[220/191] utility maintains the proper aspect ratio of the clipping mask while allowing the video to scale fluidly within its container.

Why This Solution Works

Cross-browser compatibility: Safari-friendly by wrapping the video in an <object>.

Precision and scalability: Properly scaled clipping paths with the critical transform.

Flexibility: The clipping path adjusts dynamically with the video size while maintaining its proportions.

If you’ve faced issues applying clipping paths to videos in HTML/CSS, this method is worth a try. For a live example and to experiment with the implementation, check out my CodePen playground. It demonstrates the full setup and lets you see the results in action.

  • #HTML
  • #CSS
  • #SVG
  • #frontend