Flex: What, How and Why?

29 Mar 2017

Flex is a new layout mode which provides simple and powerful tools for aligning content and creating complex layouts. Despite it not being an accepted standard from the World Wide Web Consortium (W3C), its popularity in the web design community is growing and browser support is pretty good in everything apart from Internet Explorer < 10 (who expected anything else?). Apparently, the draft of the standard was up for review at the start of September but we haven’t heard any news yet.

In this article, I hope to explain the main ideas behind the introduction of Flex and highlight some reasons that Flex > Float.

Because Flex is so different to other layout modes, the W3C had to think of some new terminology to describe it. This terminology has evolved over time, as has the module itself. There are currently 3 naming conventions for Flex, as you can see when generating vendor prefixes. I hope the current one is the last, I don’t know how many more names for the same thing I can remember.

To properly understand what is going on inside your flex box it is a good idea to come to terms with the terminology laid out in the latest draft. The image below shows the terms used when describing an area of a flexible box.

using flex box instead of float

There are a lot of terms here that aren't necessarily useful unless you're talking to another designer.

The horizontal axis, usually referred to as the inline axis, is called the Main Axis. The vertical axis, usually referred to as the block axis, is called the Cross Axis. The Main Axis is called the Main Axis because it is the main axis used when adding items to your flexbox. It is used when adding flex children alongside each other. Believe it or not, the Cross Axis is called the Cross Axis because it crosses the Main Axis, it is used when the first row of flex children has to wrap. As far as I’m aware, this Main-axis/Cross-axis terminology won’t be used anywhere in your code, but it’s still good to understand how the module works. Note that the Main Axis is only horizontal when you have your flex children laid out in a row ( flex-direction: row;), if you want a column layout ( flex-direction: column;) your Main Axis will be vertical instead.

There are quite a few properties included in the flexbox module, making it a little confusing to learn. Here are some good resources for learning more about flex and here’s something to play with.

display: <flex | inline-flex>
flex-direction: <row | row-reverse | column | column-reverse>
flex-wrap: <nowrap | wrap | wrap-reverse>
justify-content: <flex-start | center | flex-end | space-around | space-between | space-evenly>
align-items: <flex-start | center | flex-end | baseline | stretch>
align-content: <flex-start | center | flex-end | space-around | space-between | stretch>
flex-flow: <prop flex-direction | prop flex-wrap>

align-self: <auto | flex-start | center | flex-end | baseline | stretch>
flex-basis: <auto | ’width’ | content | max-content | min-content | fit-content | >
flex-grow: <‘number’>
flex-shrink: <’number’>
order: <’number’>
flex: <flex-grow | flex-shrink | flex-basis>

Layout Modes

To understand flex and why this new layout mode is so good you have to first understand what a layout mode is in CSS. There are currently four ways of laying out a page in CSS, each of which has a different set of rules dictating how they interact:

Inline – this defines the flow of text in a document
Block – this defines the position of stylistic elements in a document
Table – this defines the layout of tables
Positioned – this allows the exact positioning of elements, outside of the flow of other layouts
Flex is a new addition to this list and its primary function is to easily lay out block-level elements. A decent grid layout is also on its way into CSS, but that’s not as finished as flex and is only sort of working in Chrome at the time of writing.

Inline Layout

Inline flow is when text (or blocks with display: inline-block) are laid out in a format that’s easy to read i.e. one letter comes after another in an order that the brain expects. In English, we use a left-to-right flow for text with the next line going underneath, whereas in Chinese or Japanese, their text flows from top-to-bottom and the next line goes on the left. Inline elements, can be described as “in the flow of the text”. Inline elements have a few rules:

  • Follow the flow of text
  • Follows padding and margin but ignores margin-top and margin-bottom
  • Ignores width  and height  definitions
  • If given a float of left or right the inline element will become a block element.
  • Follows the vertical-align property.

A few examples of elements that are inline by default are <a>, <span>, <b>, <em> , <i> , <cite> , <mark>  and <code>.

Block Layout

Block level elements, on the other hand, are much more free thinking and can be manipulated in a lot of different ways. They function more like an object in a 2D space. They can be made independent of document flow with position: absolute. Block elements have a few rules too:

  • If width is not set they fill the full width of their container.
  • If height is not set they will be as tall as their child elements unless the children are floating, then the height is 0.
  • Can have margins and/or padding.
  • They always clear each other by default.
  • They don’t listen to the vertical-align property.

Some examples of block level elements are: <p> , <div> , <form> , <section> , <header> , <footer> .

One is not better than the other, that’s not the point of this comparison, they just have different applications.
Tables are old news that everyone should understand by now so I don’t need to go into that here. There is another new layout called Grid under consideration, but browser support is minimal at the moment. It will provide a lot more flexibility when designing page layouts than Flex.
Because of the nesting nature of HTML, layout modes sometimes need to be mix-and-matched to achieve a good looking result. This has resulted in partial layouts such as ‘inline-block’, ‘inline-flex’ and ‘inline-table’ which will fit into the flow of the elements around them as text, but the contents will be displayed as a block, flex or table. Images are inline-block by default because they are often included with page content and as such the text needs to wrap around it.

Fixing Common Problems

Flex was designed to be simple and to fix some common layout issues that designers were having. Here are a couple of examples. Bear in mind that we write SCSS here at SCL, not plain CSS. If you’re not using Sass yet, you should be.

Order

Sometimes you need to adjust the order of the items you’re styling and don’t have access to/don’t want to change the HTML, for example, if you want to alternate the layout of articles in an archive page depending on whether their position in the list is odd or even. Flex has a handy property called order that you can use on flex children to change the order that they appear in when rendered. Want things to move around on a hover? Just change the order. The main drawback of this method is that the order remains unchanged when your page is being viewed with a screen-reader or some other thing that doesn’t use CSS.

Centring

Centring items on both axes has proven difficult up to this point. In the old days you would probably have to set position: relative on the container and then position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%) on the child, or something like that. Even transforms are a relatively recent addition to the CSS standards. As I said before, there are a few methods, most of which don’t allow for variation in the height of child elements. With flex, you set display: flex; justify-content: center; align-items: center; on the container, and you will have a perfectly centred, responsive child. Have a play with this to get to grips with justify-content and align-items:

See the Pen Flex Positioning Demonstration by Govi Tusler (@govinski) on CodePen.

Triple Column Layout

Since the move from table layouts to divs and floats and with the beginnings of responsive design, triple column layouts have proven tricky to get right. There’s always margins that have to be removed and switching from a 3 column to a 2 and a 1 on tablets requires redoing your maths (if you want to keep margins consistent, which you definitely should). It’s just a pain. With Flex you can set a minimum width for the child using flex-basis and set flex-wrap: wrap on the container and Flex will wrap the children for you and keep all your margins as consistent as possible without any effort on your part. Have a look at the example below, give it a click to change the layout mode that it is using (the title changes too). Neither the parent or any of the children have a height set, it’s all based on the length of the text; something that’s been impossible for years! All you need is align-items: stretch;.

Check out this CodePen example to see this difference.

See the Pen Flex vs Float Triple Column by Govi Tusler (@govinski) on CodePen.

Dealing with a second row

If you have multiple rows of content, you can have control over how your boxes fill any excess vertical space with align-content, like you can with justify-content. As mentioned before, this wasn’t possible with floats as they weren’t aware of the content around them. Have a play with this:

See the Pen Align Content Demonstration by Govi Tusler (@govinski) on CodePen.

Making Flex Responsive

Flex, by its very nature, is responsive. Flex is really good for responsive design because it encourages you to use percentage widths in combination with flex-basis for min and max widths and will wrap content when it doesn’t fit its container (only if you tell it to). Where you would find yourself writing 5 different media queries to, say keep the logo centered on all devices, there is probably a flex solution that looks just as good and takes less than half of the code. You can always adjust flex properties at breakpoints if you really need to.

Building a triple column

I just want to run through creating a triple column layout using both floats and flex. You could just have a look at my code in the flex/float triple column example above, but I had to structure it a little weirdly to get JavaScript to be able to switch between them.

First, we have to define the markup, a bit of filler content is always a good place to start.

I will keep all stylistic CSS separate from the layouts so that it’s easier to follow. These styles are common to both layouts.

Flex Triple Column

In this case, it is the justify-content property that makes Flex so much better than floats. You can configure your column margins to be close together with justify-content: center;, equal margins with justify-content: space-around; or as far apart as possible with justify-content: space-between; while flex does all the heavy lifting for you.

Float Triple Column

This one works because when an element is given a float, it is converted to a block level element, regardless of its original type. When given a float of left, other inline or floated content is allowed to flow along the right-hand edge.

We want the leftmost box to be aligned with the left-hand edge of its container, so we have to disable the margin on that one with the :first-child selector. The other boxes require a 5% margin because 100% total-width – 30% box-width * 3 boxes leaves you with 10% to spread between 2 boxes.

Of course, neither of these layouts are responsive. With flex it is easy enough, you could set your container to wrap and add something like this: flex-basis: 30%; width: 100%; min-width: 200px; to your .flex-child and it would suddenly be responsive(ish). With float, it’s a much more painful process and would require 3 breakpoints

Flex is a godsend to designers, making life so much simpler with a relatively small learning curve. If you can Flex somewhere, you can Flex anywhere. Browser support is increasing all the time, it looks pretty solid across the board at the time of writing with older versions of IE being the main culprit for jeopardising your use of Flex.

Can I Use flexbox? Data on support for the flexbox feature across the major browsers from caniuse.com.

Not everything is possible with Flex, though, you can’t really create complex responsive layouts for your entire page and you can’t really align single flex items. I would like to see a few pseudo-selectors added to Flex. Namely :flex-item-wrapped, to adjust the width of flex children which have been wrapped, :first-of-row to remove margins from the first item in every row, :last-of-row to remove margins from the last item in every row. Responsive layouts will soon be doable with the new grid system, but that’s another post for another time.

Why aren’t you using Flex yet? Let us know in the comments!