mattholland
Published in

mattholland

Twerking It With Flexbox

Article summary: Learn how to flex your muscles with CSS FlexBox! Codepen also provided.

This is the first wall ever built using Flexbox, now a UNESCO world heritage site.

When I first learned about Flexbox, I was worried. That’s because I had already flexed enough muscle to move traditional grids around. I didn’t want to have to throw away all those years of growing my delicate fibers, one by one, cell by cell, millimeter by millimeter. But sometimes as devs, we have to sit down for a moment, stop writing code, and place our precious seconds onto a scale to see which side is dragging us down the most. In the end, those few introspective seconds could save us weeks of work. Flexbox has a menagerie of features, but we are going to go over the major ones that you will use most often. Let’s do this…

Equal distribution

.container {
display: flex;
}
.box {
flex: 1;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>

There are two major cornerstones of Flexbox: distribution and alignment. Here we demonstrate its ability to create equally distributed content blocks with ease. Traditionally, each box would have had a percentage width, with margins mixed into the calculation to ensure that our content doesn’t go over 100% of our container width.

A common problem that I’ve encountered too many times is forcing all containers in a row to be the same height regardless of their inner content (given an unspecified, auto height). This is usually a debacle for cards. No more, my friend; with flex: 1;, all containers will grow to the height of the tallest container, and their widths will stretch to 100% of the available space.

Unequal column distribution with ease

.container {
display: flex;
}
.box-large {
flex: 3;
}
.box-small {
flex: 1;
}
<div class="container">
<div class="box-large"></div>
<div class="box-small"></div>
<div class="box-small"></div>
<div class="box-small"></div>
</div>

If you’ve had experience with the traditional float grid, you know you would have had to specify something similar to <div class="large-6 columns"> for the large block, and <div class="large-2 columns"> for the small blocks. No longer, my friend. Flexbox doesn’t require any specific float, clear, or calc instructions like our old grid. It just works. Isn’t it simply beautimous?

Simple content alignment

.container {
display: flex;
}
.box {
display: flex;
flex: 1;
align-items: center;
justify-content: center;
}

That’s right; we just precisely centered our box content without using any internal margin or padding. We could have given our box a text-align: center; instruction for the horizontal alignment, but that wouldn’t ensure alignment for all possible elements that our box could have in it. text-align only aligns the inner content of block elements, not the block elements themselves (like a <p>). We take care of this by using justify-content: center; , and then we vertically align the content with align-items: center;. What if you wanted one of the specific items to be aligned differently than the parent specification? You could use the align-self property on the individual item.

You need to also remember that we can only use these two properties on an element with display: flex; applied, because they are sub-properties if it. Let’s dive into these two properties a bit more before we move on so that you truly understand them.

align-items demo

align-items: start;
align-items: center;
align-items: end;

If you aren’t a doofus, you can probably see thatalign-items deals with the vertical alignment of elements.

justify-content demo

justify-content: flex-start;
justify-content: center;
justify-content: flex-end;
justify-content: space-between;
justify-content: space-around;
justify-content: space-evenly;

If you aren’t a dodo bird, you should know by now that justify-content deals with the horizontal alignment of elements, as well as the space distribution of elements (this includes both row and column orientations as well). space-between is a good use case for things like navbars or footers that need specific left and right content, with voids in between. It distributes all of the inner space around the elements, and doesn’t care about the space before or after the initial and last elements, respectively. space-around ensures that each element has the same space before and after it (which will result in double the space between two elements, similar to margin that is specified for all elements in a row). space-evenly ensures that all elements have the same amount of space before and after them (this one won’t double-up the in between space like space-around does). I hope that this doesn’t make you feel too spacey.

Vertical stacking & responsiveness

flex-direction: column;

Flexbox allows you to stack columns with ease:

.container {
display: flex;
flex-direction: column;
}

The default stacking order is flex-direction: row;. This gets applied if we don’t specify a specific direction. We could use the column instruction for mobile-specific responsiveness, like so:

.container {
display: flex;
}
// 640px
@media only screen and (max-width: 40em) {
.container {
flex-direction: column;
}
}

Source ordering

.box--1 {
order: 4;
}

.box--2 {
order: 1;
}

.box--3 {
order: 3;
}

.box--4 {
order: 2;
}

<div class="container container--order">
<div class="box box--1"><p>1</p></div>
<div class="box box--2"><p>2</p></div>
<div class="box box--3"><p>3</p></div>
<div class="box box--4"><p>4</p></div>
</div>

Flexbox will naturally order your containers in the order that they are written. However, you can also change that on the fly without having to alter your source code! What if you wanted to completely reverse the order, you ask? In that case, you could use flex-direction: row-reverse; for a row, or flex-direction: column-reverse; for a column.

Ordering demo

Take the following scenario: you have a nice little display card with content that is horizontally drawn ( row ) that includes an icon, a stacked title and description, and a dollar amount. On mobile, you want the vertical order from top to bottom to be the icon, dollar amount, and then the stacked title & description. Git’er done:

Default order
Altered order
// Summarized styles for vertical card
.card--vertical {
flex-direction: column;
justify-content: space-around;
}
.card__info-wrapper {
order: 3;
}
<div class="container card">
<div class="card__icon"></div>
<div class="card__info-wrapper">
<div class="card__title">Our New iPhone !</div>
<div class="card__description">It is the best...</div>
</div>
<div class="card__value">$6,450</div>
</div>

That is just beautimous. We could have also given the card__info--wrapper an order value of 1 and it would have done the same thing. But for clarity and readability, I gave it a 3. Items that do not have a specified order are automatically drawn in the order that they have been coded before any elements with an order specification. You most likely noticed (if you are smart) that we also used thejustify-content: space-around; instruction. This applies an equal amount of space around each element. That’s right; once again, we didn’t have to specify any padding or margin!

Wrapping like Snoop

.container {
display: flex;
flex-wrap: wrap; // Could also say flex-flow: row wrap;
overflow: hidden;
}
.box {
display: flex;
align-items: center;
justify-content: center;
height: 80px;
width: 85px;
}
<div class="container">
<div class="box"><p>1</p></div>
<div class="box"><p>2</p></div>
<div class="box"><p>3</p></div>
<div class="box"><p>4</p></div>
<div class="box"><p>5</p></div>
<div class="box"><p>6</p></div>
<div class="box"><p>7</p></div>
<div class="box"><p>8</p></div>
<div class="box"><p>9</p></div>
</div>

Flexbox allows us to wrap like Snoop Dogg. See how quickly we threw those down? Are you picking up what I’m putting down? If we specify the box’s width, whether in px or %, then it will automatically wrap to the next row once the content exceeds the parent container’s width. This can be convenient in cases where you have a fixed-width container (like pictures or album covers), and you’re not sure how many will be on the page. Ice Cube once said “Today’s gonna be a good day.” Well, just rap it and call it a day.

Flexbox practical demo: a simple page layout

What good is all of this, you might have asked yourself (I hope you didn’t, because that probably means that you should be writing more code instead of being a poser)? The simple answer is: it is REAL GOOD. That’s because you can use it to efficiently created layouts like this:

// Styles summarized; see codepen for all styles
.container {
display: flex;
flex-direction: column; // whole page flows from top to bottom
}
.navbar {
display: flex;
align-items: center;
justify-content: space-between; // left-side & right-side content
}
.main-wrapper {
display: flex; // flex-direction: row; is the default
}
.content {
display: flex;
flex: 3; // shorthand, signifies flex-grow
flex-flow: row wrap; // shorthand for flex-direction & wrap
}
.menu {
display: flex;
flex: 1; // takes up 1/4th of container width
flex-direction: column;
}
.footer {
display: flex;
align-items: center;
justify-content: space-between;
}
<div class="container">
<nav class="navbar">
<p>Pics 'r Us</p>
<p>log in</p>
</nav>

<div class="main-wrapper">
<section class="content">
<div class="box"><p>flex</p></div>
<div class="box"><p>flex</p></div>
<div class="box"><p>flex</p></div>
</section>
<aside class="menu">
<p>categories</p>
<hr>
</aside>
</div>

<footer class="footer">
<p class="footer__brand">DUTcH inc.</p>
<div class="footer__icons">
<svg></svg>
<svg></svg>
<svg></svg>
</div>
</footer>
</div>

The entire page uses flexbox. The navbar, body and footer containers all have the display: flex; property applied. For the navbar and body, we use align-items: center; and justify-content: space-between; to get the spacing perfect. For the body, we use the flex-grow property to define the column widths. Our inner box content is also flexed, and uses the flex-wrap: wrap; instruction so that the boxes always flow over to the next row. To get the main body content sections to behave and sit on top of each other on mobile, we use a media query with the flex-direction: column; instruction applied, and we use the order property to put the <aside> section on top of the main content section.

Loose trimmings

There are a few items we should cover before wrapping it up. Did you notice that we used flex: 1; and flex: 3 for the content and menu containers in the example page? This property is shorthand for flex-grow, flex-shrink, and flex-basis. If you specify only one number, the browser will automatically set the flex-shrink and flex-basis values (which is the preferred method most of the time). However, there may be some cases when you need to specify these, which you can do either this way: flex: 1 0 80px;, or flex-grow: 1; flex-shrink: 0; flex-basis: 80px.

flex-grow, as we explained before, tells the container how much of the available space to take. flex-shrink specifies how much the targeted element will shrink as compared to the rest of the items next to it. So if you have an element with flex-shrink: 3;, then it will shrink 3x the amount of the flex elements next to it as the container size is reduced. flex-basis specifies the initial size of a flex item, before any available space is distributed (horizontally if the item is in a flex row, or vertically if the item is in a flex column). Explicit width declarations will take precedence over flex-basis.

We used another shorthand property as well: flex-flow. This declares both theflex-direction and wrap properties in one swoop. If not specified, the default flex-direction will be row. The default wrap setting is no-wrap.

Moving forward

Flexbox is great for all of the previous reasons that we just demonstrated. But there is one thing that we haven’t discussed yet: Flexbox is designed with a one-dimensional flow in mind. Despite this, front-end frameworks like Foundation now have a Flexbox grid available to replace the existing float grid. This is great, and is definitely what I recommend using since there is now browser-wide support for Flexbox.

What if we needed to specify both the vertical and horizontal properties of containers at the same time, though? Well, there is a new kid in town that’s really good at that: CSS Grid. CSS Grid creates two-dimensional structures, with both rows and columns in mind. Our simple page layout, for example, really is a two-dimensional flow. Our header and footer flow in one direction (from left to right), and are rows instead of columns. Our main content area really consists of columns, with rows inside of them. The entire page itself is a column, that flows from top to bottom. The ideal mix for this situation would be to use CSS Grid to create the page layout itself, and then to use Flexbox to align and organize the inner content of the page sections. I definitely recommend reading up on CSS Grid and practicing it, as it will eventually have browser-wide support as well.

wRap-up

I hope you enjoyed this article and that it inspires you to hit up the gym and flex your muscles. We all could use more flexing in our lives, for greater health, confidence and happiness. I also recommend that you listen to this song (and that you check out my codepen below it):

(Ice Cube thinks that every day is a good day to flex…)

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Matt Holland

Matt Holland

Software engineer based in Austin, TX, fueled by an endless stream of digital curiosity.