See the Pen XJOOzv by Dudley Storey (@dudleystorey) on CodePen.

Cet article est également disponible en français

Recently I’ve been thinking about how pages might start to break out of the “boxes inside boxes” trope that’s built up in web design over the past few years. One way to break through limitations is to merge two different creative possibilities: in this case, CSS clip-path and the Shapes module.

The New Clip

clip-path, inherited from SVG, is used to mask content on web pages. The old clip syntax had several significant limitations - clipped elements had to be absolutely positioned, and could only be clipped into rectangular shapes - and has been superseded by this new specification. clip-path opens the specification to arbitrary shapes (including circles, ellipses, and free curves), and places no restrictions on the size, flexibility, or position of content.

Figure 1: Image masked in CSS clip-path Maker

The easiest way to start playing with clip-path is by using Bennett Feely’s excellent “Clippy” tool. One restriction is that you cannot upload images to the app; instead, you must provide an external URL. I’ve provided a copy of the image used in the example above.

There’s an infinite number of possible clipping areas; for this image, I chose “Triangle” in Bennett’s tool and moved the points around to the positions shown in Figure 1.

The complete code for the effect is shown at the bottom of the app window. Note that it provides a -webkit- vendor prefix; right now, clip-path is only supported in Webkit-derived browsers, and Safari still requires prefixes. We’ll get to making the clip effect work in Firefox and other browsers in a moment.

Adding the image to a page, we can apply an id attribute, together with some filler text:

<img src="vapor-cone.jpg" alt id="penetrator">
<h1>The Need For Speed</h1>
<p>The urge to go faster than the speed of sound is probably as old as Kitty Hawk, as old as mankind’s first realization that there was a barrier to break.

And then some CSS:

img#penetrator {
	width: 50%;
	float: left;
	-webkit-clip-path: polygon(24% 0, 24% 100%, 100% 54%);
	clip-path: polygon(24% 0, 24% 100%, 100% 54%);
}

Note that the points of the clip-path are specified in a counter-clockwise direction from the top point, and are measured in percentages. (Pixels are also a possibility, but using percentages means that this effect will scale with the fluid image).

Figure 2: Image with clip applied, but no shape-outside

Contrary to expectations, clip-path does not alter an element’s relationship to the rest of the page; the clipping area affects only the image, and the filler text wraps around it as if it’s still its original shape. To fix that, we need to use a separate CSS module.

Shaping The Wave

In previous articles I’ve shown how to use CSS Shapes to wrap text around circular elements, as well as curved images. In this case, we’re using a polygon shape: and, in a burst of logic, the shape-outside property takes exactly the same values as clip-path to map a polygonal area:

img#penetrator {
	width: 50%;
	float: left;
	-webkit-clip-path: polygon(24% 0, 24% 100%, 100% 54%);
	clip-path: polygon(24% 0, 24% 100%, 100% 54%);
	shape-outside: polygon(24% 0, 24% 100%, 100% 54%);
}

The result matches the clipping path to the shape wrap, but clings the text very closely to the image; the shape itself also looks a little strange just hanging out on the page. In the example, I’ve fixed this by adding a negative margin-left value to the image. This brings the clip-path out of alignment with the wrapping shape, but the result works in this case.

Making The Effect Work Across Browsers

shape-outside can be polyfilled, as discussed in a previous article. To support the clip-path in other browsers, we turn to the SVG standard it was derived from. On the same page, write a small inline SVG:

<svg id="svgpath">
	<defs>
		<clipPath id="delta" clipPathUnits="objectBoundingBox">
			<polygon points=".24,0 .24,1 1,.54" />
		</clipPath>
	</defs>
</svg>

I’ve talked about clipPath previously; in this case, we want to make the SVG clipping path responsive, so we use clipPathUnits="objectBoundingBox". The SVG thinks of itself as a 1 × 1 box, so the clipping polygon takes the same value as clip-path, divided by 100.

This SVG method is a fallback for clip-path, but it goes first in the CSS declaration for the image:

img#penetrator {
	width: 50%;
	margin-left: -12%;
	float: left;
	clip-path: url(#delta);
	-webkit-clip-path: polygon(24% 0, 24% 100%, 100% 54%);
	clip-path: polygon(24% 0, 24% 100%, 100% 54%);
	shape-outside: polygon(24% 0, 24% 100%, 100% 54%);
}

The result - a combination of two different CSS modules - breaks text out of boxes, making for the possibility of powerful and unique art-directed pages.

Photograph from Wikipedia Commons, used under a Creative Commons Attribution-Share Alike 3.0 Unported license.