Flexbox is a CSS module that efficiently lays out items inside a container. It makes sure that spacing and alignment are always consistent and that unused space inside the container is filled, even if the container size or the child element sizes are changeable or unknown. So, it helps us dealing with flexible boxes... hence the name!
It’s not a new invention—in fact, the first W3C working draft is dated 2009. The specifications have changed a bit over time and flexbox is currently a W3C candidate recommendation—so not quite endorsed by W3C yet but on its best way. And I can’t see why it shouldn’t be endorsed, because it makes a front end developer’s life so much easier!
The clearfix hack
Remember the good old pre-flexbox days when you had to pollute your DOM with empty HTML elements just to prevent a container from collapsing?
Say we have three boxes inside a container. Now we want to float the boxes next to each other. What happens? The parent container collapses.
Luckily the clearfix solution was invented. Just add an empty pseudo:element after the container to contain the floats.
But do we really want to add an additional empty element to the DOM? HTML elements are meant to hold the content of a web page. Layout and styling should be handled by the CSS alone. Using an HTML element to make sure that the layout works as expected seems like a bit of a code smell to me.
Flexbox to the rescue!
To be able to use flexbox effectively we need to understand that there is a relationship between the flex-container and the flex-children. To create this relationship, we simply add display: flex
to the container, which automatically makes the children (i.e. the elements inside the container) flex-items.
The default direction in which the children are aligned is a row. Other options for the flex-direction
property are column, row-reverse and column reverse.
In the gif you can also see that the flex-children automatically adjust their height to fill the height of the container.
CSS can do the math, but...
For my second example, let’s again think back to the pre-flexbox days and imagine that the three boxes in a row need to fill the width of the page. No problem! We can just give them 33.3333333%. Wait, how many 3s after the decimal point? It should really be an infinite number of 3s to make it accurate, shouldn’t it? Well, that’s awkward. To make it even more awkward, let’s imagine that the UX designer has asked you to add a 10 pixel margin on the boxes.
Sure, we can add margin: 10px
. But what happens?
The boxes start wrapping because there isn’t enough space! The margin increases the width of the boxes, and the total width ends up being more than 100%.
We can resolve that with CSS calc, as you’ve seen in the GIF. Those calculations can become quite complex though. For example if we wanted the middle box to take up 60% of the width and the other two boxes 15%, and they all had different margins, you might have to get the calculator out. And if we then had to add more boxes with different sizes… You can imagine.
Flexbox to the rescue!
If we use flexbox, we just need to add flex-grow: 1
to the child elements. That will distribute the boxes nicely. Adding a margin? No problem! Flexbox will know to automatically fill the available space. No more awkward calculations. And you want to increase the width of the middle box? Just give the flex-grow
property a higher number.
Reordering elements in the DOM
Sometimes it might be necessary to reorder elements in the view. For example your sales department might require you to put advertising banners near the top of the page for desktop. But your UX designer insists that for mobile more important information for the user should be near the top.
Achieving this with just using CSS: pretty much impossible. Unless you duplicate the elements in different positions in the DOM and hide and display them using media queries. But as we know, duplication is a big code smell. And using this approach also means that every time you load the page, all elements will load and then some will hide, which will make your page slower. Not a great solution.
Alternatively you could remove and insert elements into the DOM with JavaScript. At least you won’t have duplicate elements at any time. But here we’re violating the separation of concerns principle. Normally the HTML is responsible for the DOM elements and the content, not the JavaScript. If other developers worked on the codebase, it could be confusing for them to handle content in this unexpected way.
Well, guess what...
Flexbox to the rescue!
You can give child elements an order. A negative number means that they’re jumping to the beginning, a positive number means that they’re moving to the end.
Browser support
Unfortunately all that glitters is not gold. Even the shiny and ever so helpful flexbox has a downside, and that is browser support. IE8 and IE9 are not supported at all, and there are a large amount of bugs for IE11. I know, it’s frustrating.
Also, keep in mind that flexbox needs vendor prefixing. This can be automatically done with the autoprefixer plugin for your favourite task runner.
But apart from this, I think flexbox is a great tool that makes the layout of a responsive website a lot easier!