Vertically Align Content With CSS Using This One Weird Trick
Front-end devs will hate me for revealing the secret.
Phil Karlton famously said “there are only two hard things in computer science: cache invalidation and naming things”. I would add a third: vertically aligning content with CSS.
The scenario
We want to vertically align variable height content within a wrapper div.
vertically centered
Just use vertical-align:middle?
Most people (myself included) expect that adding vertical-align:middle
to the wrapper will
do this trick. But vertical-align
doesn’t set the alignment of content within a wrapper, it sets the
alignment of inline elements relative to each other.
Let’s try some variations of vertical-align
and see how it works.
Making vertical-align:middle work for you
Going back to the original scenario, instead of applying vertical-align:middle
to the wrapper,
let’s apply vertical-align:middle
to the content. Seems counter-intuitive, but bear with me.
vertically centered
We’re getting closer. Let’s add a third element with 100% height
vertically centered
This is starting to look promising!
Make CSS do the work for us
Manually adding a third element to vertically align things is a burden. So let’s
have css do that for us with a :before
pseudo element.
vertically centered
It’s working! Now remove the red border from the pseudo element and… Voila
vertically centered
Edge cases
Well this is awesome. But you knew there would be edge cases right? Consider this scenario:
Your customer views the page on a small device, or resizes their browser and…
What happened?? The text wraped, but the content dropped below the wrapper. Let’s make our before pseudo element visible again.
Now we can see what happened. The :before
pseudo element is an inline-block element. So
it’s getting wrapped as well. We can fix that with another trick. Add a negative right
margin to the :before
pseudo element so the pseudo element doesn’t take up any horizontal
space.
Now the text is wrapping like it should.
All together now
Conclusion
I’ve used many tricks over the years to vertically align content. They all have tradeoffs. Some
add a lot of noise to the CSS. Others (like using display:table-cell
) have side effects. I’ve just
recently discovered this trick, but I think it’s going to be my new go-to solution. In terms of
compatibility, it works on all modern browsers + IE8.
Thanks to Chris Coyler for the idea and Gary Turner for the original work.