The frustrations of using CSS Shapes and CSS Exclusions
I don’t like to write ‘moany’ and negative articles. That’s not what you need.
But indulge me as I explain my current feelings of woe with CSS Shapes and CSS Exclusions.
The promise of CSS Shapes
Around 2014, articles surfaced extolling the virtues of the forthcoming CSS Shapes implementations.
Namely, the ability to have non-rectangular shapes for content via the power of CSS. Think about the gazzilion magazine articles you have seen where text flows around images; basically that for the web.
Fantastic. We have wanted this in CSS since forever.
Back then I got enthusiastic about the possibilities but as support was scant, I mentally parked CSS Shapes up until they were something that could be used in anger and I had a suitable use-case.
Current state of browser support
Fast-forward to 2018 and support is much better. Take a looky-see at https://caniuse.com/#feat=css-shapes
They have been in Safari and Chrome for a while and we finally (from v62) have them in Firefox.
IE and Edge have no support. However, as they are edge browsers (pun intended) with very low market share I could work around that.
By the way, if you are an Edge user, you can cast a vote to get supported added at the Windows Developer Feeback site.
It’s been in the backlog with a priority of ‘medium’ since 2015 so don’t hold your breath. Not quite the 18+ years we have been waiting for custom scrollbars in Firefox but you know, hardly a break-neck pace either.
Anyway, don’t start hating on IE and Edge until you have read the rest. No-one really comes out of this smelling of roses.
How to use CSS Shapes
The first paragraph of the CSS Shapes Module Level 1 specification provides this description:
CSS Shapes describe geometric shapes for use in CSS. For Level 1, CSS Shapes can be applied to floats. A circle shape on a float will cause inline content to wrap around the circle shape instead of the float’s bounding box.
Suppose you have a bunch of flowing text and you want to let it flow around a 200px circle. The markup might look like this:
<div>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Repudiandae vel possimus voluptatibus culpa eius ea totam animi fugiat, laboriosam repellat, nisi obcaecati ab natus! Nisi quasi sapiente nulla libero non?
<div class="shape"></div>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Laborum, voluptatem nobis. Ex alias, perspiciatis accusantium ab ad magni quaerat minus vel accusamus soluta adipisci expedita numquam reprehenderit sequi veniam eveniet!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ad at tempora aut earum. Quasi quaerat vel perspiciatis totam deleniti ullam eius dolore magni aliquam harum necessitatibus sunt accusamus, delectus animi.
</div>
And your CSS could be:
body {
max-width: 500px;
margin: 0 auto;
font-size: 1.2rem;
line-height: 1.5;
}
.shape {
height: 200px;
width: 200px;
background-color: #e4e4e4;
shape-outside: circle(50%);
float: left;
}
The main ‘lorem’ text will now flow around a 200px circle shape. However, if you have a background-color on your shape element, you would be forgiven for thinking “WTF” when the shape itself is still square:
See the Pen CSS Shapes 1 by Ben Frain (@benfrain) on CodePen.
Turns out you will need to add a clip-path
to the shape div which is the same as your shape-outside
. So, here goes:
.shape {
height: 200px;
width: 200px;
background-color: #e4e4e4;
shape-outside: circle(50%);
clip-path: circle(50%);
float: left;
}
That gives us this result
See the Pen CSS Shapes 2 by Ben Frain (@benfrain) on CodePen.
Then you can play with shape-margin
to add a little space around the shape itself if you need it.
With CSS Shapes, you can have basic shapes like circle()
or ellipse()
or pass in values to create a polygon. When it comes to polygons, the best advice I have is to use Bennett Feely’s ‘Clippy’ tool, choose the custom shape and go wild.
You don’t have to use coordinates with CSS Shapes. You can also flow text around an image based on the Alpha channel. Pretty cool, right?
I thought so, so jumped to the first practical example I thought of.
What about a pull quote?
With CSS Shapes we can flow text in irregular shapes. Great. I’m thinking I’ll make a great pull-quote for the blockquotes
on a blog site.
I’ll take a polygon shape, add some content for the pull-quote that will sit inside and I’ll liberate my content from the rectangular world it has grown accustomed to. Easy right? Not so fast Bat-man.
See the Pen CSS Shapes 3 by Ben Frain (@benfrain) on CodePen.
There is no shape-inside
See the text inside the shape getting clipped? I must have set something wrong surely? No. I’m afraid not.
Turns out, what is needed here is shape-inside
. That would allow us to define a shape inside the element which internal text can flow within.
Turns out shape-inside
isn’t implemented anywhere yet; it’s a CSS Shapes Level 2 property.
Arse.
I’m pretty sore about that.
I suppose we can kind of work around that by setting some internal padding on the shape that will safeguard the content from the ‘shape’ of the shape. Not ideal, but arguably workable depending upon the use-case.
Moving on, the next thing I wanted to do was pull the quote out of the left-hand visual flow a little.
Let’s make the shape relatively positioned and apply some negative positioning to achieve that.
left: -100px;
position: relative;
Here is the effect:
See the Pen CSS Shapes 4 by Ben Frain (@benfrain) on CodePen.
The pull-quote does indeed come left by –100px but the shape of the text just kind of stays there. Hmmm. Not exactly what we were after.
At first I thought this was a browser quirk but Firefox does the same. So, this is intentional. I’m sure there is a sensible reason for this.
A read of the specification tells me that this will happen but doesn’t offer an explanation as to why it makes sense to do so. Bummer.
Regardless, I don’t like to give in easily. Let’s use calc()
to amend the coordinates in that prior polygon:
shape-outside: polygon(calc(75% - 100px) 0%, calc(100% - 100px) 50%, calc(75% - 100px) 100%, 0% 100%, 0 50%, 0% 0%);
That way, we are taking off the 100px from the horizontal percentages. OK, here we go:
See the Pen CSS Shapes 5 by Ben Frain (@benfrain) on CodePen.
Right, the essence of the technique seems to work. I should probably do that left-pull thing with CSS Grid but that’s another matter.
I’m not sure if it’s my own ineptitude and lack of practice with CSS Shapes but I don’t find working with CSS Shapes particularly predictable or fruitful. I’ve worked around one issue to get the result I needed but I’m left with the less than ideal situation of the text inside a shape not adhering to the shape it sits within.
Another shortcoming is that with CSS Shapes, as they make use of floats, you are limited to the shape having text flowing to the left or right but not both.
CSS Exclusions
While IE/Edge have failed to implement CSS Shapes, they are the only platform to ship CSS Exclusions. The specification for CSS Exclusions is here: https://www.w3.org/TR/css3-exclusions/
Here’s a line from the abstraction:
CSS Exclusions define arbitrary areas around which inline content ([CSS21]) can flow.
Wow, doesn’t sound that different to CSS Shapes really. One thing flows around another.
From a cursory read through the specification, it also allows text to flow around non-floated elements. You have some granularity about how things flow with the wrap-flow
property too. Plus using z-index
to set the exclusions order. Very cool. But…
Oh, wait. These exclusions are just for rectangular boxes. No shapes. Just boxes.
And just Microsoft Edge support.
So. About as much use as a chocolate fire-guard. Why read any further. Sad trombone time.
Summary
I don’t know what’s going on here. As an outsider, coming to these features fresh in 2018 this situation seems like a bit of a car crash.
Safari, Chrome and Firefox has CSS Shapes and no Exclusions, Microsoft has CSS Exclusions and no Shapes – what a great situation for a developer!
Right now I’d take CSS Shapes with shape-inside
. I could make things happen with that. I’d also find Exclusions useful but they look about as likely to drop across the board as custom scrollbars making their way into Firefox.
I guess we all just need to hold on until CSS Shapes Level 2?
OK, enough grumbling. I promise the next post will be more positive.
On the relatively positioned issue, note that you’re not so much relatively positioning the *shape* as relatively positioning the *float*. Take a look at how relative positioning works on the float without the shape (the text wrapping around the float stays there in that case, too).
You can use a negative margin-left for this case without fiddling with the shape definition. Try taking off the position:relative; and adding margin-left:-10%; (after the margin shorthand declaration).