Understanding the CSS Clip Property

Learn about the underused and often misunderstood CSS clip property and understand how to apply it for some nifty effects.

Understanding the CSS Clip Property

Hi guys! First of all let me wish a belated happy new year to all of you. Today we are going to do something different: dig deep into one single CSS property. And that property is going to be the “clip” property.

I’m pretty sure some of you don’t even know there is a CSS property called clip since it’s probably the less used property in the world. It’s no big deal guys, we will cover pretty much everything you have to know about it.

The clip property aims at defining what portion of an element you want to show. You may have heard of this stuff as “crop”. There are a bunch of JavaScript plugins out there to crop an element, but actually you can do pretty much the same thing with the CSS clip property. Probably, with some limitations of course. We’ll take a look at them later.

Syntax

Let’s get started straight away with the syntax of the clip property which is not only a little bit weird but also probably difficult to understand at first glance. Please consider the following example:

.my-element {
	position: absolute;
	clip: rect(110px, 160px, 170px, 60px);
}

First thing you should note: the clip property only works on elements with position: absolute or position: fixed. It won’t work with relative or static positioning.

To be honest, I don’t really know why it is like that. At least, I didn’t find anything on the web on the topic so if you want to share some knowledge, please do.

As I said on Twitter a few days ago — and as you might think — this is a huge downside to the clip property.

However, it still might be interesting to experiment with the clip property and to find some cool use cases. Still with me? Great, let’s dig into the syntax.

The clip property accepts only three different values:

  • auto: this is the default behavior. Setting clip to auto is the same thing as not using clip at all.
  • inherit: well, it inherits the clip value from its parent.
  • a shape function. Currently only rect() exists.
clip: { shape | auto | inherit } ;

In most cases, you’ll want to use the shape function. I hope that someday we’ll have access to more shapes than just rect() (like circle() for example) but as of today, this is the only thing we can do. But don’t worry, we can still do pretty cool stuff with it. ;)

The rect() function

Now, let’s finally dig into the rect() syntax. It requires four length values, separated by commas: top, right, bottom and left. As for padding or margin shorthands, it’s clockwise.

clip: rect(<top>, <right>, <bottom>, <left>);

Now pay attention because it can be tricky. Both the top and the bottom values define the offset from the top border and the left and right values define the offset from the left border.

schema-clip

Let’s make a little example to make things clear. Please consider the following CSS:

clip: rect(40px, 260px, 150px, 80px);

This means we want to keep the portion of the element between 40 and 150px vertically and between 80 and 260px horizontally. If it’s still not clear, please have a look at the following picture.

schema

Once you’ve understood how the rect() function works, it’s pretty easy to use the clip property, but I understand that it can be quite confusing in the beginning.

Now a quick question to see if you’ve wrapped your head around the clip property. Let’s say I have a 400px (width) by 200px (height) element. Now I want to remove 50px from the right of the element, 10px from the top, and 30px from the bottom. Which one of the following lines is the one I should use?

  1. clip: rect(50px, 30px, 350px, 70px);
  2. clip: rect(0, 10px, 30px, 50px);
  3. clip: rect(10px, 50px, 30px, 0);
  4. clip: rect(50px, 30px, 10px, 10px);
  5. clip: rect(10px, 350px, 170px, 0);

Click here to get the answer!

The correct answer is the fifth one: clip: rect(10px, 350px, 170px, 0);. Be sure to check this JSFiddle to have a visual explanation. Congratulations if you were correct. ;)

Miscellaneous

Okay, now we have covered the basic usages of the clip property. I think there are a few more things you’d like to know about it.

First, the rect() function accepts auto as a value for each one of the four parameters. Basically it means “100%”. Let’s say you clip something to rect(0, 50px, 50px, 0) and want to display it in full size (100×100 let’s say). You could either do rect(0, 100px, 100px, 0) or rect(0, auto, auto, 0).

Secondly, since the rect() function requires length values for each parameter, it means it’s animatable either with CSS transitions or CSS animations. This is excellent news to make sweet effects. Of course you can’t animate to auto since it’s not an integer.

Third, percentage values for the rect() function are not supported. It’s too bad because it would make responsive clip stuff easier.

Browser support

And there you say “yes Hugo, this is nice but what about the browser support?”. You’re right to ask this question but you’ll probably be surprised to know that the browser support for the clip property is freaking good (according to MDN)!

Feature Chrome Firefox Internet Explorer Opera Safari
Support 1.0 1.0 4.0 7.0 1.0
8.0
Correct comma syntax supported in this version.

Yeah, you read right: Internet Explorer 4! But, until Internet Explorer 8, you have to use the old syntax which requires the four rect() values to be separated by spaces instead of commas. Okay no big deal, what about this?

.my-element {
	position: absolute;
	clip: rect(10px  350px  170px  0); /* IE4 to IE7 */
	clip: rect(10px, 350px, 170px, 0); /* IE8+ & other browsers */
}

Demos

In order to make things a little clearer, I made two demos. The first one is just a little example of the clip property. In this demo, I used a few things:

  • The clip property (oh, really?)
  • CSS transitions; as we saw earlier, values are animatable
  • A sibling selector (~ or +)

So what happens? At first, the image is cropped to be invisible. Then, when you hover the little “button”, the next image is being clipped to appear in about 0.5s from its center.

Pretty neat, right? Now let me show you what you can do as a real live thing with the clip property, some advanced CSS selectors, and CSS transitions.

Explaining the whole code would probably not only be a bit heavy but also certainly not that interesting since what was the most difficult to do was finding the accurate advanced CSS selectors to target only the pictures I wanted. Things like li:nth-of-type(n+7):nth-of-type(-n+9):hover img { ... }.

However there was a little overlapping bug caused by both CSS transitions and z-index when hovering pictures, which has been fixed by Ana Tudor so big thanks to her.

Anyway, if there is anything you’d like to know about this demo, be sure to ask a question in a comment. I’ll try to get back to you as soon as I can. ;)

You may still wonder what else you can do with this strange property. Here are some ideas of use cases; if you have any, please be sure to share them.

  • An image gallery as above
  • A way for cropping variously sized pictures
  • CSS sprites (source)
  • An accessible method to hide content (source)

The next tutorial on Codrops will also show you how to use the clip property practically to create an expanding overlay effect: Putting CSS Clip to Work: Expanding Overlay Effect

Final words

In the end, what can we say about the clip property? First, that it’s a weird one. It has an odd syntax calling a function requiring counter-intuitive values. The fact that both, top and bottom values are offsets from the top border and not respectively from top and bottom borders, can be pretty hard to get. However, the W3C may fix this in the future by editing the syntax.

Note. In CSS 2.1, all clipping regions are rectangular. We anticipate future extensions to permit non-rectangular clipping. Future updates may also reintroduce a syntax for offsetting shapes from each edge instead of offsetting from a point.

Source W3C

Secondly, we can surely say it’s not a common CSS property. It has a fairly limited usage, but I can assure you it gives really a bunch of possibilities and I think its low usage is probably due to a lack of understanding. Be sure to use it when you feel like it’s a good place for it, especially since it has a really great browser support.

Well guys, I think we have covered pretty much everything you need to know about the CSS clip property in order to be able to use it in real live projects. If you have any question or want to show any related work, please be sure to do so. Thanks for reading!

Previous:
Next:

Tagged with:

I am a front-end developer from Grenoble (France) with a passion for HTML5 and CSS3. Plus, I'm a geek and a gamer. I am the author of Browserhacks and Wild Web Watch.

View all contributions by

Website: http://hugogiraudel.com

Related Articles

Feedback 44

Comments are closed.
  1. 1

    Hi! Definitely a great article but, as could make the image is displayed in full size or preferably fill the page?

  2. 3

    Cool! Pretty much exactly what I thought it was. I’ve come across clip before but never knew what the syntax was to actually use it.

  3. 5

    Just a quick css question. I see that you nicely used li:nth-of-type(3n+1) { clear: both; }, presumably to make the 4th, 7th, and 10th list items clear their rows and begin a new one. Is that part correct? If so, I notice that I can remove the rule in Dev Tools yet the behavior remains the same. Am I missing something?

    • 6

      Your understanding is correct but as the container is 300px and each of the items is 100px wide then every 4th element will drop onto a new row anyway as that’s the natural behaviour of floats when they don’t fit in its parent. However, it may have been added as a safety net incase people are dealing with different height elements as that would cause some weird layout issues with the floats if the clears weren’t in place.

  4. 8

    A great article. I’m just wondering whether it could be used with media enquiries to show a better image on mobile devices. Has anyone tried it?

  5. 10

    Hi there, if anyone is interested doing this animation with jquery, you cant do this directly through a CSS property but you need to “borrow” a different property which isnt used like backgroundPositionX. Here is an example:

    $(“.foo”).stop().animate({
    backgroundPositionX: 130
    },
    {
    step: function(now, fx) {
    now = 130 – now;
    $(this).css(“clip”, “rect(0px, 182px, 30px, ” + now + “px)”);
    },
    complete: function() {
    $(this).css({ backgroundPositionX: 0 });
    }
    }, 1000
    )

  6. 12

    can someone explain why its

    span:hover ~ img {
    clip: rect(0, 400px, 200px, 0);
    }

    and not

    span:hover ~ img {
    clip: rect(0, 0, 0, 0);
    }

    in the first demo.

    • 13

      Because the point it to show the image when the button is hovered, not to hide it (especially since it’s hidden from the start).

Comments are closed.