CSS Shapes, text around images with CSS

0
346

The Shapes Level 1 CSS module, promoted by Adobe since 2012, defines a series of new CSS properties through which it is possible to scroll the text around a profile that does not follow the standard rectangular shape. As you can guess, this is another decisive step forward for the creation of creative layouts that bring the Web closer to the potential of printed paper.

An example of CSS Shape
An example of CSS Shape

In this article we will give a general overview of these properties and basic techniques, starting from the state of the art with respect to browser support for a specification that, at the time of writing, has reached the status of Candidate Recommendation. Here is the table obtained from Can I Use.

Support on CSS Shapes browsers
Support on CSS Shapes browsers

Internet Explorer and Firefox are missing. Safari requires the use of the prefix -webkit-, while on older versions of Chrome (35 and 36) it is necessary to first activate the experimental features of the browser. As we will see later, a Javascript polyfill is available that provides basic support to the specification even to browsers that do not present it natively.

CSS Shapes: preliminary notions

Before starting with the analysis of properties and functions, it is necessary to dwell on some preliminary basic concepts.

The specification allows you to define only shapes around which to externally scroll the text. This is set through the property shape-outside. The property was also initially planned shape-inside. With the latter, it was possible to adapt the text contained within a box to an arbitrary form. The implementation of shape-inside has been postponed to a subsequent development of the specification.

The shape around which to scroll the text can be of four types:

  • a circle (function circle);
  • an ellipsis (function ellipse);
  • a regular or irregular polygon (function polygon);
  • a rectangle, possibly with rounded corners (function inset).

The form is associated with an element (a div, an image, etc.) that must necessarily be floated to the left or right. It will be drawn on the side opposite to that set with the property float.

The element that serves as the basis for creating the shape must always have the basic dimensions (height and width) explicitly defined with one of the units of measurement available in CSS. The only exception is represented by the images: in this case the dimensions, if not defined, become those of the images themselves.

In addition to using the four functions mentioned above, a shape can be defined starting from an image that has a transparent alpha channel around the profile of the main object.

The circle function

Spelled out the preliminary notions, we can move on to the practice by analyzing the first and simplest of functions circle. It is used to create a circular shape. Let’s see how we used it in the first demos.

In the HTML we have a container element and within it a div class .shape with a series of paragraphs with the text.

<pre class=”brush: php; html-script: true”>
<div class = “shape”> </div>
<p> Lorem ipsum dolor sit amet […] </ p>
</pre>

The div with class .shapewill be the basis for the creation of our circular form.

As we mentioned, we will first proceed to float (in this case on the left) the element and assign it explicit dimensions:

<pre class=”brush: php; html-script: true”>
.shape{
width: 200px;
height: 200px;
float: left;
}
</pre>

To define the shape we use the property shape-outsidewith the function circle:

<pre class=”brush: php; html-script: true”>
.shape{
width: 200px;
height: 200px;
float: left;
shape-outside: circle (40%);
-webkit-shape-outside: circle (40%);
}
</pre>

circleit can take as its main value the size of the radius of the circle. We can use any unit of measure. In our case, the 40% value means that the radius of the circular shape will be equal to 40% of the size of the reference box. For us they are 200px. The radius will therefore be 80px.

With this observation, we have introduced a new concept on which it is opportune to dwell: that of ‘reference box’.

To try to explain it at best it is best to start from an image:

A circular shape with its reference box
A circular shape with its reference box

It is a screenshot captured by inspecting the item with the Google Chrome developer tools. When inspecting an element that contains a CSS shape, it returns a graphical representation that shows the shape (the circle in purple) in the context of its reference box (in light blue). The latter is none other than the rectangular box on the left, with dimensions 200x200px from which we left. A shape is always created in the context of a box of this type. It provides the limits to the form and its positioning context. The image is also useful for understanding something else: an element to which we apply a form does not take that form! It is always a rectangular box. The shape only affects the so-called float area around which the text flows.

Remaining on the image, one can also notice a sort of border around the circle. This is a margin set around the circular shape with the property shape-margin:

<pre class=”brush: php; html-script: true”>
.shape{
width: 200px;
height: 200px;
float: left;
shape-outside: circle (40%);
-webkit-shape-outside: circle (40%);
shape-margin: 10px;
-webkit-shape-margin: 10px;
}
</pre>

This is the easiest way to create a breathing distance between the shape and the surrounding text. Nothing prevents us, however, and in some cases may be more appropriate, to use the classic margin CSS property for this purpose. In fact, keep in mind that the margin set with shape-margin is valid only in the context of the reference box. It means, that is, the margin between the edge of the form and that of the box. If the form then occupies the entire area of the reference box, there is no room for the application of shape-margin.

Well, having analyzed our first demo and the CSS code, we can draw a first conclusion: the way in which the text flows around a form is given by the relationship between a series of parameters. For the circular form, the main ones are the dimensions of the reference box, the width of the radius and the value of the margin. Changing one of these parameters affects the form and the way in which the text flows around it. Let’s see some examples.

Here’s what happens if we increase the box dimensions to 300x300px:

Circular shape with a box of 300x300px
Circular shape with a box of 300x300px

And here’s what happens if instead, we set the circle radius to 60%:

Circular shape with 60% radius
Circular shape with 60% radius

As we can see, we have lost the circular shape. Because? Because with that beam size the circle exceeds the limits of the reference box. The conclusion is that a form, to take effect, must always be contained in the context of this box.

Finally, let’s see how it is possible to position the shape with respect to the reference box. The latter, in fact, also defines a sort of coordinate system, a context for positioning. In this system, the upper left corner of the box represents the 0 0 coordinates on the horizontal and vertical axis. By default, the center of the circle coincides with the center of the box. But we can act on these parameters, like this:

<pre class=”brush: php; html-script: true”>
shape-outside: circle (40% at 0 0);
</pre>

Just add the at two-point references, two coordinates, on the horizontal and vertical axis after the definition of the radius and the keyword. These coordinates can be expressed with any unit of measure.

Using the values 0 0 as in the code seen above we obtain this result:

Positioning of a circular shape
Positioning of a circular shape

The center of the circle now coincides with the 0 0 point of the reference box. The possibility of positioning the shape undoubtedly allows us to refine the work to obtain precisely the shape we want.

The ellipse function

What has been said so far allows us to proceed more quickly with the analysis of the other functions, starting from ellipse, with which we can set up an elliptical form.

The only difference from circlethis is that this function requires the declaration of two values for the radius, the first for the horizontal axis, the second for the vertical axis.

In the second demo we get this result.

Elliptical shape
Elliptical shape

starting from this CSS code:

<pre class=”brush: php; html-script: true”>
.shape{
shape-outside: ellipse (50px 140px);
-webkit-shape-outside: ellipse (50px 140px);
shape-margin: 10px;
-webkit-shape-margin: 10px;
width: 150px;
height: 300px;
float: left;
}
</pre>

As for circle, it is possible to precisely define the positioning of the shape with respect to the reference box.

The polygon function

With the function polygon we can create extremely complex shapes, from regular polygons with n sides to polygons with an irregular profile. The minimum number of sides provided for these polygons is equal to three (one triangle).

To draw a polygon you must define as many pairs of coordinate values as the vertices of the polygon itself. Here, for example, how an equilateral triangle is defined:

<pre class=”brush: php; html-script: true”>
shape-outside: polygon (50% 0%, 0% 100%, 100% 100%);
</pre>

As you can see, we have three pairs of coordinates separated by commas. The values expressed for the coordinates are intended, in order, for the horizontal and vertical axis. The reference system for coordinates is given by the box already seen for the previous functions. For the values, we can use all the units of measure provided for CSS. In the image below you can see highlighted the vertices of the triangle that is obtained with the code just seen:

A triangle used as a CSS Shape
A triangle used as a CSS Shape

It should be clearer now, how the coordinate system works. Considering that the upper left corner of the box coincides with the 0 0 point, the first vertex is halfway (50%) on the horizontal axis and 0 on the vertical axis. And so on for the other two vertices.

It is evident that drawing complex polygons can be quite complex without some visual guidance. Fortunately, we have a tool available that can be very useful. It is Clippy, an instrument created by Bennett Feely to create shapes to be adapted to the CSS property clip-path. Since the notation is identical to that of CSS shapes, we can exploit it for our purposes also in this context. The tool provides many freely configurable predefined shapes by moving the vertices of the polygon. You can also size the reference box as desired and load an image to be used as a base and guide from an external URL. When we have created the form that interests us, it will be enough to copy the function polygon with its values and paste it in the context of our property shape-outside instead of with clip-path.

In the third demo we did all these operations creating a hexagonal shape:

Hexagonal shape in its reference box
Hexagonal shape in its reference box

Here is the CSS code:

<pre class=”brush: php; html-script: true”>
.shape{
shape-outside: polygon (50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
-webkit-shape-outside: polygon (50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
width: 300px;
height: 300px;
float: left;
}
</pre>

We then ‘played’ a little with Clippy, creating an irregular shape from the hexagon:

Irregular polygon
Irregular polygon

Copy and paste the code from Clippy and get the fourth demo:

An irregular polygon in its reference box
An irregular polygon in its reference box

This is the CSS code:

<pre class=”brush: php; html-script: true”>
.shape{
shape-outside: polygon (50% 0, 100% 0, 70% 45%, 100% 100%, 0% 75%, 0% 25%);
-webkit-shape-outside: polygon (50% 0, 100% 0, 70% 45%, 100% 100%, 0% 75%, 0% 25%);
width: 300px;
height: 300px;
float: left;
}
</pre>

The inset function

The last function, insetallows you to create rectangular shapes, possibly with rounded corners.

We used inset in the fifth demo getting this result:

Rectangular shape in its reference box
Rectangular shape in its reference box

Taking a look at the CSS code, we find that the function is defined by setting four values (top, right, bottom and left in the order) with which the rectangle is moved relative to the sides of the reference box. The keyword roundand the next value are used to create rounded corners for the rectangle:

<pre class=”brush: php; html-script: true”>
.shape{
shape-outside: inset (30px 25px 30px 40px round 40px);
-webkit-shape-outside: inset (30px 25px 30px 40px round 40px);
shape-margin: 10px;
-webkit-shape-margin: 10px;
width: 300px;
height: 150px;
float: left;
}
</pre>

In the second part of the article we see how to use the shapes to scroll the text around the images.

Use images

In all the examples we have seen so far we have worked, for didactic purposes, with “empty” forms. In the most common practice, however, the text will flow around forms created from images. What we have to do is choose the function that best fits the image and proceed in the ways we have seen.

In the sixth demo, for the image of pizza, the choice is obvious: we start from a circle and then work with circle.

<pre class=”brush: php; html-script: true”>
<img src = “pizza.jpg” class = “shape”>
<p> Lorem ipsum dolor sit amet [..] </ p>
</pre>

In place of an empty div we have here an element to imgwhich we assign the class .shape. In CSS we proceed like this, finding in 50% the ideal dimension of the ray that fits our image:

<pre class=”brush: php; html-script: true”>
.shape{
shape-outside: circle (50%);
-webkit-shape-outside: circle (50%);
float: left;
}
</pre>

When using images as a reference for the shapes, particular attention must be paid not only to the basic profile of the object that guides the shape itself, but also to the background. The image of the pizza is perfect and is particularly suitable not only for the round shape, but also because the pizza is isolated on a white background that coincides with the background color of our page. But what if we start from an image that does not have these characteristics? In Example 7 we used a photo of the Statue of Liberty by setting a circular shape:

<pre class=”brush: php; html-script: true”>
.shape{
shape-outside: circle (40%);
-webkit-shape-outside: circle (40%);
float: left;
}
</pre>

Here is the result:

A shape without clips
A shape without clips

Yes, we have a circular shape around the float area, but the box represented by the image remains squared. What we would like is to be able to ‘cut out’ the profile of the image because it takes on a circular shape. In this scenario the CSS property helps us clip-path, with which it is possible, precisely, to cut out any shape from a classic box square.

In the next example we have combined shape-outsideand clip-pathin this way:

<pre class=”brush: php; html-script: true”>
.shape{
shape-outside: circle (40%);
-webkit-shape-outside: circle (40%);
clip-path: circle (40%);
-webkit-clip-path: circle (40%);
float: left;
}
</pre>

With these results:

A shape with a circular clip
A shape with a circular clip

Use images with alpha channel

The ability to define very complex polygons allows us to create profiles suitable for very irregular images and objects. In this demo we took another picture of the Statue of Liberty. We loaded it in Clippy and created this polygon, not too detailed:

A polygon around the Statue of Liberty
A polygon around the Statue of Liberty

It was enough to get the coordinates and set up the CSS rule:

<pre class=”brush: php; html-script: true”>
.shape{
shape-outside: polygon (30% 22%, 69% 27%, 69% 69%, 96% 72%, 100% 84%, 91% 100%, 0 100%, 0% 70%, 0% 35%, 23% 0);
-webkit-shape-outside: polygon (30% 22%, 69% 27%, 69% 69%, 96% 72%, 100% 84%, 91% 100%, 0 100%, 0% 70%, 0% 35%, 23% 0);
float: left;
}
</pre>

Profile of the Statue of Liberty in its reference box
Profile of the Statue of Liberty in its reference box

With the image we have just seen, however, we could have proceeded in another way. It is in fact a PNG file 24 with a transparent alpha channel. In this scenario, the CSS Shapes specification provides the possibility to obtain the form directly from the image, without resorting to any function. The drawn profile will coincide with the opaque, non-transparent part of the image. In this case, the level of adaptation of the text to the profile is very precise. Let’s see how to proceed in the CSS.

The latest demo of this article once again presents an image with class .shapeas the origin of the form. In the style sheet we used these rules:

<pre class=”brush: php; html-script: true”>
.shape{
shape-outside: url(statua-2.png);
shape-image-threshold: 0.5;
-webkit-shape-outside: url(statua-2.png);
-webkit-shape-image-threshold: 0.5;
shape-margin: 15px;
-webkit-shape-margin: 15px;
float: left;
}
</pre>

For the property shape-outside, the image URL is given as value and the property is set shape-image-thresholdwith a value between 0.0and 1.0. This property is used to define the transparency threshold of the pixels that help to create the shape. A value of 0.5 is almost always perfect to achieve the desired result.

Working with CSS Shapes

To conclude, a series of links to useful resources and tools.

LEAVE A REPLY

Please enter your comment!
Please enter your name here