With CSS, you can make all kinds of shapes, but if you try to put any text inside even a simple non-rectangular shape, you can run into problems. The text will not wrap to fit inside the container.
However, recently I discovered the
CSS
property shape-outside
. Browser support isn’t great (currently only
Webkit-based browsers), but there is a
polyfill. It
allows you to wrap text around a floated element, as if it had a shape
you specify. Perhaps the most common example is a circle:
Gorgeous. But how does this help with the original problem? This handles
wrapping outside a shape. There’s no shape-inside
(yet).
Until that arrives, we can still manage this. The trick lies in
inverting the shape-outside
. In other words, make the shape a polygon,
with two points at (0,0) and (0, 100%), and the rest following the
contour of the desired shape. It’s not perfect (for circles at least)
but it’s good enough, since text would never be perfect anyway.
One caveat: this only works with floated elements. We can float the
::before
pseudoelement just fine, but if we try to float the
::after
, it doesn’t look right. See the example below — you can hover
over the circle to color the pseudoelements, to make it more obvious
what’s happening.
Unfortunately the only way I’ve found around it so far is
double-wrapping the circle element, so you can use both ::before
elements.
Forgiveable, I suppose, but I would like a single-element solution.
Here’s an SCSS mixin to handle it all:
@mixin circle($radius){
width: $radius*2;
height: $radius*2;
border-radius: $radius;
&::before{
content: '';
height: 100%;
width: 50%;
float: left;
shape-outside: polygon(
0 0, 100% 0, 60% 4%, 40% 10%, 20% 20%, 10% 28.2%, 5% 34.4%, 0 50%,
5% 65.6%, 10% 71.8%, 20% 80%, 40% 90%, 60% 96%, 100% 100%, 0 100%
);
}
> span::before{
content: '';
height: 100%;
width: 50%;
float: right;
shape-outside: polygon(
100% 0, 0 0, 40% 4%, 60% 10%, 80% 20%, 90% 28.2%, 95% 34.4%, 100% 50%,
95% 65.6%, 90% 71.8%, 80% 80%, 60% 90%, 40% 96%, 0 100%, 100% 100%
);
}
}