100% found this document useful (1 vote)
123 views

Clipping and Masking in CSS CSS-Tricks

The document discusses the differences between clipping and masking in CSS. Clipping uses vector paths to hide parts of an element, while masking uses images as a stencil. The old clip property is deprecated, and the new clip-path property allows clipping with basic shapes like circles and polygons. Masking defines a mask in SVG that is referenced in CSS. Both clipping and masking can be animated, but browser support for newer techniques is inconsistent.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
123 views

Clipping and Masking in CSS CSS-Tricks

The document discusses the differences between clipping and masking in CSS. Clipping uses vector paths to hide parts of an element, while masking uses images as a stencil. The old clip property is deprecated, and the new clip-path property allows clipping with basic shapes like circles and polygons. Masking defines a mask in SVG that is referenced in CSS. Both clipping and masking can be animated, but browser support for newer techniques is inconsistent.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

css-tricks.

com

Clipping and Masking in CSS | CSS-Tricks

8-10 minutes

Both of these things are used to hide some parts of elements


and show other parts. But there are, of course, differences
between the two. Differences in what they can do, differences
in syntaxes, different technologies involved, the new and the
deprecated, and browser support differences.

And sadly there is quite a bit of outdated information out there.


Let’s see if we can sort it out.

The difference between clipping and masking

Masks are images; Clips are paths.

Imagine a square image that is a left-to-right, black-to-white


gradient. That can be a mask. The element it is applied to will
be transparent (see-through) where there is black in our
gradient mask image, and opaque (normal) where there is
white. So the final result will be an element that fades in from
left to right.

Clips are always vector paths. Outside the path is transparent,


inside the path is opaque.

I personally found this confusing, because often times you’ll


run across a tutorial on masking that uses a masking image
that a white vector-looking shape on black, so it is basically
doing the same thing a clip. That’s fine, it just confuses things
a bit.

The Old/Deprecated clip

The first presence of clipping in CSS (other than overflow:


hidden; trickery) was the clip property. (MDN).

It was like this:

.element {
clip: rect(10px, 20px, 30px, 40px);
}

Those four values are in the same order as margin/padding:

10px from the top of the element


20px from the right of the element
30px from the bottom of the element
40px from the left of the element

The clip property is deprecated in CSS, meaning the use of it


isn’t recommended because there is a newer, standardized
version that browsers will actually focus their efforts.

There are some strengths of clip: because clip shipped in


browsers, it will probably always work. And the browser
support for it is extremely strong: pretty much every browser
ever. Plus I’ve heard animation performance from it trumps
newer methods.

There are two rather significant weaknesses of clip though,


which makes not using it easier to swallow:

clip only works if the element is absolutely positioned


clip can only do rectangles.

Pretty limiting. So let’s move on.

The New clip-path

The new, recommend version of applying clipping to elements


in CSS is clip-path. You’d think it would be as simple as:

.element {

clip-path: rect(10px, 20px, 30px, 40px);


}

That doesn’t work though (even prefixed, anywhere).


Eventually, we’ll get rectangle(), just not yet:

Postponed rectangle() to level 2

The new way to do this is with inset():

.element {
clip-path: inset(10px 20px 30px 40px);

Note that there are no commas, and the syntax is different, but
ultimately does the same kind of things.

What also does work with clip-path though (in some


browsers), is circles, ellipses, and polygons. Here’s some
examples:

.clip-circle {
clip-path: circle(60px at center);

}
.clip-ellipse {
clip-path: ellipse(60px 40px at 75px 30px);

}
.clip-polygon {
clip-path: polygon(5% 5%, 100% 0%, 100% 75%,
75% 75%, 75% 100%, 50% 75%, 0% 75%);

Polygon is pretty powerful. Ryan Scherf posted a tutorial here


on CSS-Tricks on using it programmatically to produce a
sketchy effect.

I highly recommend playing with it through Bennet Feely’s


Clippy:
Theoretically, this is what clip-path will support (known as
“basic shapes“):

.clip-examples {

clip-path: rectangle(x, y, width, height,


rounded-x, rounded-y)

clip-path: inset-rectangle(from top, from


right, from bottom, from left, rounded-x,
rounded-y)

clip-path: polygon(a, bunch, of, points)


clip-path: circle(radius at x, y)
clip-path: ellipse(radius-x, radius-y at x,
y)

I can’t seem to find info if path() will ever be a valid value.


Using clip-path with an SVG-defined <clipPath>

You don’t have to define the clip-path value right in CSS, it can
reference a <clipPath> element defined in SVG. Here’s what
that looks like:

<img class="clip-svg" src="harry.jpg"


alt="Harry Potter">

<svg width="0" height="0">


<defs>
<clipPath id="myClip">
<circle cx="100" cy="100" r="40" />
<circle cx="60" cy="60" r="40" />
</clipPath>
</defs>
</svg>

.clip-svg {
clip-path: url(#myClip);
}

Demo:

Sara Soueidan has a demo of this in action as well.

There is a rather significant issue with using SVG-defined clip


paths though: some browsers pin them to the upper left of the
document. Here’s a demo of that issue:

Left: clip path moves along with image in Google Chrome 54 (good).
Right: clip path is pinned to the upper left and doesn’t move along
with image in Safari 10 (bad).

Animating/Transitioning clip-path

When you declare a basic shape as a clip-path, you can


animate it! Dirk Schulze has a wonderful article covering this
same kind of stuff which features this demo:

Here’s a simple example of code:


div {
transition: 0.4s cubic-bezier(1, -1, 0, 2);
clip-path: polygon(50% 5%, 0% 100%, 100%
100%);
}
div:hover {
clip-path: polygon(50% 19%, 0 76%, 100%
76%);
}

Try it out:

Masking

There was a WebKit-only version of masking where you could


link up a raster image or define a gradient to be a mask. It
looked like this:

img {
width: 150px;
-webkit-mask-image: -webkit-gradient(
linear, left top, right bottom,
color-stop(0.00, rgba(0,0,0,1)),
color-stop(0.35, rgba(0,0,0,1)),
color-stop(0.50, rgba(0,0,0,0)),
color-stop(0.65, rgba(0,0,0,0)),
color-stop(1.00, rgba(0,0,0,0)));
}

As far as I know, that’s deprecated. That’s the definitely


deprecated gradient syntax, and when I changed it to the new
syntax, it didn’t work. So yeah, probably deprecated. It still
works though:

And it gave birth to things like this old tutorial WebKit Image
Wipes, which still works (you know, in Blink/WebKit land).

More modern references I’ve found only mention masks as


being defined in SVG and referenced in CSS by ID or URL.
Here’s an example two ways. The mask is defined in the SVG,
and on the left, the image is within the SVG in an tag. On the
right, that mask applied to an in the HTML (which only seems
to work in Firefox at the moment).

Check out this demo in Firefox too (example code lifted from
Dirk Shulze’s article). This kind of thing is a little dangerous at
the moment, as it doesn’t just not work in WebKit/Blink, it
erases the element it’s applied to entirely.

You can also link up an entire SVG file as the mask, like:

.mask {
mask: url(mask.svg);
}

Mask Types

.mask {
mask-type: luminance;
mask-type: alpha;
}

Border Masks

This is very similar to how border-image works in CSS. You


define an SVG image, and nine-slice scaling is applied (like a
tic-tac-toe board over the image). The corners are used in the
corners, the edges (can be) repeated along the edges, and the
middle (can) stretch in the middle. The basics of that:

.border-mask {

-webkit-mask-box-image: url(stampTiles.svg)
30 repeat;
mask-border: url(stampTiles.svg) 30 repeat;

Here’s a demo of regular masking versus border masking:

Browser Support
It’s so hard so summarize succinctly, since different properties
and even values have different support levels all over the place.
Not to mention how you use them and on what. It’s a
wilderness out there, so I’d recommend using as progressive
enhancement the best you can at the moment. Which might be
a little tough, as there isn’t even Modernizr tests for this stuff
really.

As far as prefixing goes: use the non-prefixed and -webkit-


prefix on pretty much everything.

Yoksel has a great browser support chart she made related to


all of this:

More

clip-path here on the CSS-Tricks Almanac


Clipping and Masking in CSS
clip-path on WPD
clip-path on MDN
Clipping and masking on MDN
The (deprecated) CSS Clip Property (Impressive Webs)
Spec on CSS Masking
CSS Masking by Dirk Schulze
Clipping in CSS and SVG – The clip-path Property and
<clipPath> Element by Sara Soueidan
Pens tagged clip-path on CodePen
Demos and browser support demo Pen by Yoksel
SVG Masks by Jakob Jenkov
Alan Greenblatt’s research on browser support levels for
clipping and masking features
Video of a talk: Razvan Caliman – Cutting-edge CSS
Features for Graphics: CSS Masking, Blending and Shapes

You might also like