Several years ago I wrote an article showing how to wrap text to a curve using a combination of Adobe PhotoShop’s Slice tool and some CSS. While that technique still works today, the work of manually creating image slices means that it takes a significant amount of time to create the effect.
Promoted by the Adobe web platform team, the CSS Shapes Module aims to create the same visual effects that have been available to desktop print designers for decades – including wrapping text around and within shapes on the page – available to the web. This means we can rapidly create magazine-quality layouts on web pages, with little PhotoShop trickiness required.
The Shapes spec is defined across two modules. At the head of each is a property: shape-inside
and shape-outside
. While there are many possible variations, this article will concentrate on what will likely become a very popular application of the latter property: using an alpha mask to wrap text around the shape of an image.
Living In A Box
Up until now every image, no matter what visual information it contains, has been always treated as a box on a web page, forcing text to wrap around it in a rectangle.
Usually an alpha mask serves to make an image transparent against a background, but the CSS shapes spec can read the greyscale information from a mask to appropriately wrap text to the actual image, rather than the box that contains it.
Tracing Masks
At this stage I’m going to assume that you know how to make an alpha masked PNG image. If you’re unfamiliar with the process, I’d recommend reading one of my articles on the subject; you can also download the PSD, PNG and mask image to work along with this tutorial.
The first step is to place the standard image inside HTML text just as you normally would. In this example, I’ve added sematic value by accessorizing the markup with a little microdata:
<div itemscope itemtype="http://schema.org/Person">
<h1 itemprop="name">Rita Hayworth</h1>
<img src="rita-hayworth.png" alt class="wrap" property="image">
<h2>Actress, dancer, comedienne:
<span itemprop=birthDate content="1918-10-17">1918</span> –
<span itemprop=deathDate content="1987-05-14">1987</span>
</h2>
<p>Born <span itemprop="additionalName">Margarita Carmen Cansino</span>.
One of the original transformative actresses of Hollywood: changed her hair
color eight times for eight different films, and her name twice. Appeared in
61 features; one of only six women to dance with both Fred Astaire and
Gene Kelly during their careers.
</div>
The image is floated: note that in the current implementation of the spec, the content to be wrapped must be floated and have its width and height declared for shape-outside
to work.
I’ll add a bit of style to the <div>
and text, using the Gilda and Oxygen typefaces from Google Fonts:
div[itemscope] {
font-family: Gilda Display, serif;
background: #222;
overflow: hidden;
color: #fff;
padding: .5rem;
padding-right: 2rem;
}
div[itemscope] h1 {
margin-bottom: .5rem;
margin-top: 2rem;
}
div[itemscope] p {
font-family: Oxygen, sans-serif;
line-height: 1.5;
font-size: 1.4rem;
}
.wrap {
float: left;
width: 50%;
height: auto;
}
You might think that CSS Shapes would use an alpha mask built into the image for wrapping, but it doesn’t: rather, it references a separate specially-formatted image, and uses that as a guide. In principle, this makes CSS Shapes more adaptive: you can apply a wrapping shape to an image format that doesn’t directly support alpha masks (such as JPEGs), or make a wrapping guide that is completely unrelated to the bitmap content of the presented image.
In this case, I’ll use the mask that’s already part of the PNG image to create the guide. To make that happen, I’ll need to export the guide with a careful series of steps:
- Open the rita-hayworth.psd file in Adobe PhotoShop
- Turn off the visibility of the Rita Hayworth layer. Turn on the visibility of the Black Background layer immediately underneath it.
- Hold down the Option / Alt key and drag the mask from the Rita Hayworth layer to the Black Background layer, duplicating the mask. (If you're asked if you want to replace the existing layer mask, say yes).
The final mask image - The guide image has to be in Indexed color: choose Image / Mode / Indexed Color… from the menu bar. You’ll be asked if you want to merge visible layers and discard hidden layers. Click OK. In the window that appears, choose Exact palette, Forced black and white, transparency on and no Matte.
- Choose File / Save for Web…
- Save the image in PNG-8 format, ensuring that Transparency is on; ensure that the new image is saved in the same location as the original mage.
Now that we have our wrapping guide image, we can reference in our CSS:
.wrap {
float: left;
width: 50%;
height: auto;
shape-outside: url(rita-hayworth-mask.png');
shape-margin: 2em;
}
Depending on the browser you’re using, you may find the result doesn’t do much. The CSS Shapes module is supported in Chrome 37+, Safari 8+ on mobile and desktop (behind a vendor prefix), and the latest version of the Android browser, but not Firefox or IE / Edge. However, all is not lost!
Using The Shapes Polyfill
While the Shapes module is expected to be supported in all mainstream browsers very soon, we want the same effect applied across all of them now. To achieve that, we can use a polyfill: a piece of JavaScript that replicates the functionality of the CSS Shapes code in browsers that don’t yet support it. Getting the code is easy: go to the polyfill’s Github page, copy the code you find into an editor, and save it for yourself; alternatively, use the code I’ve linked here. Then, add it to the bottom of your page:
<script src="shapes-polyfill.min.js"></script>
This script queries the browser to see if it currently supports the CSS Shapes module; if it does not, the script replicates the behavior by applying a series of offset float to the text. Obviously, this will not perform as well as a native implementation; you’ll have to judge for yourself how this solution works on your site. Over time, fewer browsers will need the JavaScript solution as they come to support the Shapes module.
Conclusion
There are many more possibilities in CSS Shapes, which I will explore in future articles; if you’re especially eager, Sara Souedian has an excellent article on the topic.
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/iIuab