Photo by Immo Wegmann on Unsplash
If there is a thing that used to be unintuitive in CSS (or even ridiculously hard for beginners) is aligning stuff to both horizontal and vertical center. This visual little detail so easy to design usually meant a good amount of frustration for old-timey web developers.
Thankfully Flexbox came around and changed that but, despite it being my go to way of centering stuff, I believe that we have a lot to learn from alternative ways of doing so. So we are going to cover that and some other ways to solve this common UI problem.
Oh, and we're not talking CSS Grid here because that is a complex, very well resourced property with endless alignment possibilities that would need a full article to present.
Anyways, here we go:
The good, reliable way
One good thing about Flexbox is that it feels like a very well thought standard. It can get a bit complex, yes, but if you give yourself a chance to actually understand how it works it empowers you to make very elegant and, well, very flexible layouts.
That being said, here's how you center stuff with Flexbox.
No drawbacks, no bells and whistles, just a very good CSS property used the way it was intended to. It is so good that you don't even need to add properties to the child element, but if you really wanted to you could do something like .child { align-self: center; }
instead of .parent { align-items: center; }
.
The classic align
If there is anything classic on web development is the good old <table>
element.
Other than it's main use of creating tables, <table>
used to be repurposed on sliced websites made with Photoshop and it still shines in email templates. However, back in the day, making use of its layout properties was a sure, albeit a bit hacky, way to align elements to the center of a parent.
Here's how you'd do it back in the day -- and how you probably still wanna do it in email templates because, let's be honest, Gmail won't fully support Flexbox anytime soon...
Not too shabby, right? It still is easy to read and understand but there is some bitterness in repurposing display: table
and display:table-cell
for only that but, whatever works, man.
The X/Y align
This one makes use of some absolute positioning magic and transform properties. It is not as pure as the Flexbox approach, but it is useful for cases where you want child elements to overlap each other naturally.
Let's take a look at the example:
The main difference of this technique is that, considering that the children are absolute, any new child that you add will fill the exact same space inside the parent. And by changing the transform
values or playing around with opacity
that might be super useful.
The line-height hack-align way
This one feels the hackyest so far, but it works well if the parent height doesn't vary and the child is an inline element like a <span>
, <a>
or a text node... You know what, you're probably better off with any of the other solutions, but here is how it works anyway:
I mean, it is suboptimal that you'd need to also change the line-height of the child if the parent height changed, but this is better than increasing the child's vertical padding pixel by pixel...
Conclusion
A bit of well-used CSS can go a long way.
These four different solutions for a single problem can address multiple use cases and hopefully help you on your quest for an incredible UI implementation.
Hey, let's connect 👋
Follow me on Twitter and let me know you liked this article!
And if you really liked it, make sure to share it with your friends, that'll help me a lot 😄
Top comments (10)
I think there is a quite simple CSS Grid method
But I can see why you didn't include it. CSS Tricks also has a nice post about this:
css-tricks.com/centering-css-compl...
I now use grid for everything except margins and padding
You could improve the example by using an image or a child element that has
display: inline-block
with a set width and height. This being said you're missing a few things with theline-height
trick:line-height
, not the child's.line-height
to the child.vertical-align: middle
on the child.line-height
has to be slightly smaller than the true height, 197px or 198px (if you want to avoid child being 1 or 2px too low on some browsers).It is very hard to get it just right cross-browser, which is also why most people just use flexbox and be done with it :) In the past I've written solutions for displaying centered images cross-browser all the way from IE6 to whatever was the latest Firefox, Chrome, IE, Opera and Safari with just CSS and it was awful to master, although also both challenging and interesting, which I like. Each of those browsers had their own unique rendering engine back then! And with IE6 and IE7 you had to use
display: inline
and trigger "hasLayout" mechanism to get a behavior that matchedinline-block
... stuff you really don't want to learn unless you like mental torture of complexity :)Hey Vesa, great addition, thanks!
I really love that nowadays we don't have as much cross-browser problems that we had back in the IE6 era. I don't remember ever using the "hasLayout" trick but sure enough I've written a few browser specific stylesheets in the past. I don't miss those times 😄
Just for the sake of completeness, I think this is what one had to write when also avoiding browser specific stylesheets:
The hasLayout stuff was undocumented feature based on old layout engine for Windows applications. When CSS was added into IE they just continued to use the old layout engine despite it being not compatible with CSS. The way they worked around issues was to link some particular HTML elements and CSS properties that would trigger hasLayout internally to mimick CSS behavior as well as they could, but that would ultimately not work that well as can be seen by the amount of issues IE continued to have during the entirety of it's lifespan. I guess this is a good enough summary that doesn't lie too much :)
It was impossible to learn CSS by using IE6, there were simply so many times the browser didn't follow what was written in the standards. I learned CSS when Firefox was released: for the most part it did exactly what was written in the standards, and you would get the results you expect when expirementing. With IE you'd continuously find inconsistencies, because you either didn't trigger hasLayout or you triggered it accidentally by using "wrong" HTML element or CSS property. It was nice to find info on hasLayout some ten years ago somewhere on the web, it was enough so that I could start writing stylesheets where all CSS was in one place instead of having browser specific ones.
Now the only problem is that I still remember how to work with these legacy browsers and nobody needs the knowledge anymore :D
Great article! As someone with little background in CSS, I have a couple of questions: what is the main reason that flexbox is your go-to centering way instead of using the table-like alignment? Also, with the X/Y way, wouldn't it break the responsive layout?
Thanks for the feedback, I appreciate it!
It's hard to reply this question with something other than "because it is the right way" 😅 My main reasoning is that Flexbox itself was developed from the ground up as way to standardise positioning of elements that were previously implemented with floats and properties like top, left, etc.
MDN's article on Flexbox is great resource on the What/Why/How of it developer.mozilla.org/en-US/docs/L....
Not really because in the example we are using percentage for left/top/transform so if the width of the parent component increases/decreases the child stay in the right place. You can try changing some of the property values in the X/Y codepen and see how the example adapts.
don't forget about
margin: calc(50% - 100px)
😂Beware half-pixels in using X/Y align method. Chrome still renders half-pixels (causing blurry content) with percentage-based CSS translations. It drives me insane that Chrome still doesn't see this as an issue.
Thanks for sharing - definitely will be using X/Y and classic in the future, and will check the other two out!