I am a professional front end web developer based in London, England. The purpose of this blog is to write about issues in the field of web development as well as about open source projects that I am working on.

Blog posts

Ways of making CSS clip-path property work better

authorRichard Hunter date createdFeb 25 2016 12:00 AM
Ways of making the clip path better

The clip-path property

The clip-path css property defines a clipping region for an element hiding parts of the element outside of the border of the region. The region can be defined using a shape function or by refererence to an SVG clip path. It is the latter method that we are concerned with here.

According to the spec, the clippath can be either an inline SVG or an external SVG file; however external SVGs are not currently supported by most browsers.

The basic concept is quite simple: an SVG clip path element defines a path which is referenced by an html element via the clip-path property. The path is used to form the clipping region. In practise however, clipping paths can be quite tricky to work with. Take the following example which was taken from Codepen.

The problem, as you will find if you attempt to move the element in any way, is that neither the position of the clipping region or its size are related in any way to the element that we are trying to clip. This means that the effect will only work if our element is correctly sized according to the path and positioned. Worse still, the path is anchored to the top of the page! (this is why we have included the example within an iframe). For anything other than experimental examples this is obviously not much use!

The problem lies in the value of the clipPathUnits attribute of the clipPath element. If we do not explicitly specify it, it's default value is "UserSpaceOnUse". The SVG spec says this about it:

If clipPathUnits="userSpaceOnUse", the contents of the 'clipPath' represent values in the current user coordinate system in place at the time when the 'clipPath' element is referenced (i.e., the user coordinate system for the element referencing the 'clipPath' element via the 'clip-path' property).

The term 'user coordinate system' is a little ambiguous to me but it turns out that this is normally the coordinate space of the document itself. If the referencing element is contained by one with fixed positioning, the clip path coords will be relative to the positioned element. If that element is positioned absolutely however, Firefox and Chrome behave differently. In Firefox the clip path will be relative to the positioned element, but in Chrome the clip path will be relative to the document. In spite of these inconsistencies, I don't think the concept of 'userSpaceOnUse' is a useful one. Even Sarah Souiedan in her article on clip path resorted to using images for it rather than live examples!

What we actually probably want is a clipping region which adjusts to the size and position of the referencing element and happily it is possible to do this using the other possible value for clipPathUnits, 'objectBoundingBox'. The spec says this about it:

If clipPathUnits="objectBoundingBox", then the user coordinate system for the contents of the 'clipPath' element is established using the bounding box of the element to which the clipping path is applied (see Object bounding box units). If attribute 'clipPathUnits' is not specified, then the effect is as if a value of 'userSpaceOnUse' were specified.

This seems much more useful. If we move or resize the element, the clipping region will adjust accordingly. But there is one caveat: the value of the coords must be fractional and within the range 0 and 1. I have created a JFiddle which demonstrates this.

Malebranche

we will often find that the coords in the clipping path that we want to use are not fractional. We can edit them ourselves but if it's a complicated path involving bezier curves this quickly becomes unworkable. This is where Malebranche comes in. It's a node package which takes an svg file containing clip paths with absolute coordinates and converts them into fractional ones. See below for a link to its npm webpage.

The basic workflow is that you take an svg file which contains clip path elements and feed the path to this as an argument to malebranche along with a reference length and malebranche will generate a new version of the file with all clip path units transformed into fractional ones. Of course, as for most browsers it is still necessary to use inline svg some copy and pasting is still required. Malebranche is still also very new and I am still working on and it doesn't support just yet some of the more complicated possible clip paths but it is a work in progress and of course as an open source project we welcome pull requests!

Here are some examples of clipped images using a clip path transformed by Malebranche. Note how when we resize the element, the clip path adjusts accordingly. Even when we alter the proportions of the element, the clip path changes with them. I think it's fairly obvious why fractional coords are preferable to absolute ones.

Rain Drops
Rain Drops
Rain Drops
Rain Drops

References