CSS Layout Techniques: Part 2

This post is a continuation of last week’s CSS Layout Techniques, an overview of tried and tested layout techniques. Missed part 1? You can catch up here.

Flexbox

As I mentioned last week, each technique we’ve touched on so far is essentially a hack, or uses hacks. None of them were meant for layout. Flexbox is the first thing we have that is actually intended as a layout tool (sorry, position’s a thing but again – not quite all there). It’s actually intended for use in components while CSS Grids are set to take on the main page layout – but they’re not quite ready yet. When they do come out though, each will be able to live inside the other, so go crazy when that happens and bend the rules!

For now, FlexBox is supported pretty much everywhere except IE9 & below. We do have a polyfill, flexie, but it works for an older version. There’s also reflexie for the new spec but it looks to have been abandoned. So, we can kind of use it! That’s why I wanted to write this article – to go through FlexBox in detail before using it in bigger projects. At the highest level, it works by defining the relationship between a container (the “Flex Container”) and, within it, a group of children (the “Flex Items”). In this week’s installment of Front-End Friday, I’ll focus on each individually.

Flex Container

We can set any element to take on this role through its display property. inline-flex tells the browser that this element is a Flex Container and that it should behave like an inline-block. Setting display: flex; also defines it as a Flex Container but it will behave in the same way as display:block;.

.container { 
    display:inline-flex; //like 'block'
    display: flex; //like 'inline-block'
}

That’s the container defined in addition to how it is to fit within its context. The following properties affect how its children, the “Flex Items”, will be treated.

1: flex-direction


Within the Flex Container there are two axes: the main axes and, perpendicular to it, the cross axes. The flex-direction property defines the orientation of both with two pairs of values:

  • row and row-reverse set the main axis to run horizontally. row will run the Flex Children in the text direction, usually left to right unless you’re building a site with a language that runs right to left. So RTL sites will flip both the text direction and the Flex Item flow direction – pretty cool! row-reverse runs the Flex Children against the text direction. In both cases the cross axes runs from the top to the bottom, it doesn’t flip for either row orientation.
  • column and column-reverse both swap the main and cross axes. The main axes will now run from top to bottom (in both cases) and the cross axes will run with text direction (column) or against text direction (column-reverse)..container {
    flex-direction: row;
    flex-direction: row-reverse;
    flex-direction: column;
    flex-direction: column-reverse;
    }

2: justify-content

With the axes now defined we can start setting how the Flex Items will move around on them. justify-content sets their position along the main axes. We can pile the items against the start/end, in the middle, or space them out. Pretty useful – and it seems the CSS working group agree, this property is set to be applied to any element, be it flex boxed or not, though this may not work quite yet.

.container {
    justify-content: flex-start; //pile up to the start of the main axes
    justify-content: flex-end; //pile to the end
    justify-content: center; //pile in the middle!
    justify-content: space-between; //space out from end to end
    justify-content: space-around; //like margins, but they also collapse!
}

3: align-items

Finally, we can define how the items move on the cross axes. Like justify-content this also has flex-start, flex-end, and center, each working in pretty much the same way. But, the last two values differ:

  • baseline This is an unusual one. It looks at the first child with a baseline (eg an <h1>) within each item and uses that baseline to set the alignment of the Flex Item. In the demo below, note how the red box in 2 offsets all three boxes when baseline is set.
  • stretch: Each item will stretch to the extents of the cross axes, but this will not override width, max-width,height, or max-height..container {
    align-items: flex-start;
    align-items: flex-end;
    align-items: center;
    align-items: baseline;
    align-items: stretch;
    }

4: align-content

This property comes into play when the Flex Items wrap – yep, they wrap! But, we do have to define this with flex-wrap: nowrap | wrap | wrap-reverse; In the demo I’ve set it simply to wrap. When the items then start wrapping the align-content property lets us define the behavior of the resulting “lines”. The values we can give are the same as align-items and, if you imagine each “line” of Flex Items as a single item, they work in the same way.

.container {
    align-content: flex-start;
    align-content: flex-end;
    align-content: center;
    align-content: baseline;
    align-content: stretch;
}

A Demo

To test out, and hopefully reinforce, how all these properties actually work, I’ve put together a wee demo below. Try typing in the various values for each attribute (press enter to apply) to see their effects. Again, to reiterate: we’re only changing the css values on the Flex Container – not its children; we’ll get to that next.


Flex Items

To the items themselves! Until Grids come along we can build our layouts with these quite easily. Again, I’ve put together a live demo to experiment with at the end of this section. Hopefully, it too will make things a little clearer.

align-self

This gives us an override for the Flex Container’s align-items property, the one that defines how items are positioned along the cross axes. For the individual item to which we apply it, it works in exactly the same way with the same set of values: flex-start, flex-end, center, baseline, and stretch.

.item {
    align-self: flex-start;
    align-self: flex-end;
    align-self: center;
    align-self: baseline;
    align-self: stretch;
}

order

No more hiding elements or scripting them about to hack varying DOM orders, with this property we can specify the order of the Flex Items in CSS – without touching the DOM! This has been a long time coming. It’s also pretty easy, just set numeric values in the order property and the browser will deal with matching the order.

flex-basis, flex-grow, and flex-shrink

These three properties influence the size of the item. I’ve grouped them such that, in a way, they all work together, although you don’t need to set all three every time. To start: flex-basis “sets the initial size”, at least that’s about all I could find when searching for more details on it – not the most helpful! I had to experiment a little to figure out what’s going on and in doing so, the workings behind flex-grow and flex-shrink began to reveal themselves.

It seems that, true to the statement that comes up everywhere, each item is given its basis size. Then, if there’s extra space left over and any of the items have a flex-grow value other than 0, that space will be divided up according to the flex-grow values. Similarly, if the items expand beyond the Flex Container,flex-wrap has not been set, and any items that have flex-shrink set to anything other that 1 (the default) – the items with a shrink value – will be shrunken according to that value. That feels like a slightly convoluted description, go play with the demo – it’s much easier to see this in action!

The values that go into flex-shrink and flex-grow don’t have, or need, units. The influence, or force, that results for each is determined by its proportion of the sum of the other items grow / shrink values. The most basic example would be two items, one with flex-grow:1 and the other with flex-grow:2. The second will be twice the size of the first. One caveat though, each must have a flex-basis defined that wouldn’t push the smaller item to be larger than one third of the available space. Other wise the proportions are going to be a bit off.


Another Demo

The containing pink box is resizable (horizontally) and the slider is for the basis value. If it’s not working for you try opening up the actual pen and give that a shot. One idea for an experiment would be to set one item’s flex-grow value to 1 and another’s flex-shrink to 10. Then change the basis size for all using the slider (which should appear beside the “Toggle Wrap” button if it’s working for you – otherwise, resizing your browser should work).


That’s FlexBox! At least, that’s a simple overview of how it works. If my style of explanation didn’t quite do it for you, there’s always the CSS Tricks version, or even the Spec itself! Fun story – as I was writing this paragraph Dan posted this FlexBox learning “game” on Slack – good timing! With the basics all wrapped up, have a look at these FlexBox “patterns” to take it a little further. Next week, I’m wrapping up this series with a look to the future: CSS Grids. Stay tuned!

 

Front-End Friday is an ongoing series about our favorite tools, tricks, lessons, and best practices. Want to share your own favorite front-end development lesson? Chat with us on Twitter!

« Prev Article
Next Article »