Hostingheaderbarlogoj
Join InMotion Hosting for $3.49/mo & get a year on Tuts+ FREE (worth $180). Start today.
Advertisement

Tricks with Flexbox for Better CSS Patterns

by

If you started writing CSS a few years ago, the chances are you've become accustomed to a few quirks of CSS layouts that you've taken to be unavoidable. For instance, using absolutely positioned elements inside of relatively positioned elements, or using clearfix in conjunction with floats to achieve column grids.

Intuitively, we've all thought there should be a better way. After all, it is a bit strange that the best solution for vertical centering has involved using display:table; and associated styles. Why should we be using hacks to make fundamental things work?

The flexible box module, or flexbox for short, is the emerging solution to many of our past woes, and fits a host of design patterns that have become prevalent. The basic idea behind flexbox is to allow the containing box of elements to resize and reorder those elements to best fit the container in an appropriate way.

Current Support

Flexbox isn't intended for site-wide usage necessarily. The CSS grid spec is in the works to address that problem, but unfortunately is still in a much less supported state than flexbox, which has at least partial support in all browsers except Opera Mini. In contrast, the CSS grid spec is only fully supported by IE, with unknown or no support in all other browsers.

Flexbox is intended to be used for discrete portions of a layout. In this article, we will cover a few common tasks which can be carried out more effectively with flexbox, and explain the syntax for how we achieve particular results. To get a full-fledged overview of all of the property options, take a look at the CSS Tricks post on flex box A Guide to Flexbox.

Better Centering

Before flexbox, vertical centering of dynamic content was a non-trivial task. (See this Smashing Mag post as well as this CSS-Tricks article for the full tale.) With flexbox, everything just got easier. We'll set up a basic container with child elements.

<div class="container">
  <div class="center-all">Testing vertical center</div>
  <div class="center-all">A secondary test</div>
  <div class="center-all">Tertiary is for three</div>
</div>

Our goal is to center these elements vertically and horizontally. With flexbox, it's as simple as the following:

.container {
  width: 500px;
  height: 500px;
  margin: 0 auto;
  background-color: #dedede;
  /* Flex rules */
  display: flex;
  flex-flow: column nowrap;
  justify-content: center;
  align-items: center;
}

Note: that we are not using the vendor prefixed versions, but you should! Alternatively, take a look at Autoprefixer.

What We've Just Done

You'll have noticed some unfamiliar new rules applied here; Flexbox is a module which comprises a number of properties. To start off, the display:flex creates our flexbox container and its child elements are automatically treated as flex items.

Unless we state otherwise, our flex items will flow inline along the main axis. However, flex-flow (which is shorthand for the flex-direction and flex-wrap properties) can alter both the main and cross axes.  flex-flow: column nowrap tells flexbox that we want our content displayed in a vertical column, and that we don't want our items to wrap (forcing them to jump to the next row). 

We set justify-content to center, which aligns our items to the center of the main axis, which is based on the direction defined by the flex-flow, in this case the vertical axis. 

align-items: center aligns our items in relation to the secondary ("cross") axis.

Visual Order vs. Cognitive Order

There's an inherent problem with a traditional approach to layout, especially when dealing with responsive content. When using floats, for instance, it's easy to see the content of a page in a totally different order than is natural or cognitive. What's more, it's very difficult to manipulate the order of elements on a page. With flexbox, we're going to tackle one of the more difficult-to-achieve layouts for traditional CSS; a top aligned, reverse-ordered stacking of elements. So, in other words, the element that appears first in the markup will appear last on the screen, and adding new elements to the bottom of the markup will have them appear  the top of the screen.

We'll use this markup:

<main>
  <div class="item">Here is the first item</div>
  <div class="item">Here is the next item</div>
  <div class="item">The third item</div>
  <div class="item">The fourth item</div>
</main>

With the following CSS, we can achieve what we're trying to do easily.

main {
  position: relative;
  height: 100%;
  display: flex;
  flex-flow: column-reverse nowrap;
  justify-content: flex-end;
  align-items: center;
}

This will give us exactly what we are aiming for. View the results (with a few extra styles for easier viewing) here.

What We've Just Done

By creating a column-reverse on the flex-flow, we are asking flexbox to reverse the order of the items. We want to align the content to the end of the flexbox cross line, which in the case of the reversed column is a vertical line running from the bottom of the box to the top. 

We also set align-items:center to center the items in the column horizontally. This is useful for any kind of stacking of elements, where the cognitive order (first to last) doesn't match the visual order (top to bottom).

Further Ordering Manipulation

There are plenty of situations where you need to reorder elements based on your screen size. The common solutions to this problem are usually convoluted, or they repeat markup. Look at this example, where we've move a featured image from being in the flow of an article to the start of the article using the simple order property. We use the following HTML:

<main>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ipsam eum repudiandae ullam ipsum repellendus officiis eaque unde aut ea porro accusamus placeat earum qui quia quidem totam harum odit voluptates?</p>
  <img src="http://lorempixel.com/200/200" alt="" />
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Autem provident voluptas commodi atque. Consequatur non natus earum nobis exercitationem sapiente dolorem explicabo asperiores soluta unde est voluptatibus fugit officia quo.</p>
</main>

And the accompanying CSS:

main {
  display: flex;
  flex-flow: row wrap;
}
img {
  flex-grow: 1;
  width: 200px;
  order: 3;
}
p {
  flex: 1 auto;
  order: 1;
  padding: 10px;
  background-color: #dedede;
  margin: 0;
}
p:nth-child(3){
  order: 2;
  flex: 3 0 50px;
}

@media only screen and (max-width: 600px){
  img {
    order: 1;
  }
  p {
    flex: 1 auto;
    order: 2;
    padding: 10px;
    background-color: #dedede;
    margin: 0;
  }
  p:nth-child(3){
    order: 3;
    flex: 3 0 50px;
  }
}

This is just the tip of the iceberg when it comes to the power provided by flexbox to do in a very few lines of code what is commonly much more difficult to achieve.

Three Columns? No Problem

How many times have you been frustrated that 100/3 was impossible to do, and subsequently resort to creating 99.9% width columns, just to realize how poor of a solution that is? Flexbox fixes this problem once and for all. Take the markup:

<div class="container">
  <div class="column">Testing</div>
  <div class="column">Testing</div>
  <div class="column">Testing</div>
</div>

And add the CSS to make all three columns appear, perfectly calculated.

.container {
  display: flex;
  justify-content: center;
  align-content: space-between;
  background-color: #dadada;
}
.column {
  width: 100%;
  padding: 50px;
  text-align: center;
  box-shadow: 0 0 10px #c0c0c0;
}

Want a little gutter? No problem. Simply add margin to your .column class. The calculations for proper spacing are done for you.

Want More?

Take a look at the awesome GitHub repo "Solved By Flexbox" for more examples. Flexbox is a massively powerful module, as we hope has been proven through this article. What are some other powerful and exciting use cases you see for flexbox? Let us know in the comments!

Advertisement