Lesson 7: CSS Flexbox

Flexbox is a way to distribute elements within a container evenly or by percentage so that the child elements make up 100% width or height of the container.

Flexbox had a rough start in the web standards department. It began as an idea to aid in page layout, but every browser implemented it differently. Today the browsers have come to some consensus but there are still some quirks with Internet Explorer.

Use cases for flexbox include: site navigation, photo galleries, image alignment, and general responsive component design.

The most definitive guide to flexbox can be found on CSS Tricks but I will go over a few general rules and give a generic example on usage in this article.

Rules and Caveats

  • Elements should add up to 100% of the container width. If the elements take up more than 100% they will exceed the width of the container. If the desire is to have them wrap, you need to set flex-wrap: wrap;
  • When wrapping, elements do not have to follow the previous row as to width. They can be offset from the previous row.
  • For flexboxes with a flex-direction of row (default), the container’s height will be that of the tallest child element. You cannot use flexbox to display a masonry layout like on Pinterest.
  • For flexboxes with a flex-direction of column, the container’s width will be the width of the widest child element.
  • Be careful with justification. It is easy to set justify-content: space-between; and then be surprised when there are only two items to display and they are at opposite sides of the page.

What I Use Flexbox For

Following is an example of what I am asked to develop on many projects and what is a common use case for me.

HTML:

<div class="tile-list">
<a class="tile" href="https://www.google.com">
<img class="tile__image" src="https://placebear.com/900/500"/>
<div>
<h3 class="tile__title">Yogi Bear</h3>
<p class="tile__text">I'm smarter than the average bear</p>
</div>
</a>
<a class="tile" href="https://www.google.com">
<img class="tile__image" src="https://placebear.com/900/500"/>
<div>
<h3 class="tile__title">Yogi Bear</h3>
<p class="tile__text">I'm smarter than the average bear</p>
</div>
</a>
<a class="tile" href="https://www.google.com">
<img class="tile__image" src="https://placebear.com/900/500"/>
<div>
<h3 class="tile__title">Yogi Bear</h3>
<p class="tile__text">I'm smarter than the average bear</p>
</div>
</a>
<a class="tile" href="https://www.google.com">
<img class="tile__image" src="https://placebear.com/900/500"/>
<div>
<h3 class="tile__title">Yogi Bear</h3>
<p class="tile__text">I'm smarter than the average bear</p>
</div>
</a>
</div>

CSS:

.tile-list {
display: flex;
flex-wrap: wrap;
}
.tile {
flex: 0 0 calc(100% - (1em * 2));
// IE Hack
max-width: calc(100% - (1em * 2));
padding: 1em;
color: #333;
text-decoration: none;
font-family: arial, sans-serif;
}
@media screen and (min-width: 600px) {
.tile {
flex: 0 0 calc(50% - (1em * 2));
// IE Hack
max-width: calc(50% - (1em * 2));
}
}
@media screen and (min-width: 1000px) {
.tile {
flex: 0 0 calc(25% - (1em * 2));
// IE Hack
max-width: calc(25% - (1em * 2));
}
}
.tile__image {
width: 100%;
}
.tile__title {
font-weight: bold;
}
.tile__text {
font-weight: lighter;
}

As you can see, the parent container gets the general styles for flexbox ie: display: flex; and flex-wrap: wrap Each of the child elements have the styles to specify width: flex: 0 0 calc(25% — (1em * 2)) All the other styles are for general styling and not for flexbox.

For the flex style, this is a shorthand method. The first two numbers, in this case 0 and 0 are flex-grow and flex-shrink, or the min and max that the elements’ width should be. The last number is the flex-basis or default size of the element. In my example this is a calculation: calc(25%-(1em*2)) .

An explanation of calc: In this example I wanted to display 4 items in a row (for large screens) so naturally I wanted them to be a width of 25%. On top of the 25%, I needed to subtract the padding for each element (1em * 2). An easier way to do this would have been to set box-sizing: border-box; on the .tile elements. Calc can be useful though, especially if there were only 3 items in the flex box. Instead of doing something like this: flex: 0 0 33.333333333% which still won’t be correct, you can do this: flex: 0 0 calc(100%/3)

Normally it would not be necessary to add a max-width style to the elements as well as a flex style. This is done to support IE versions 11 and before.

As of yet I have not gone over media queries. Media queries are ways to style elements for different media and screen sizes. In this example I wanted the tiles on screen sizes from 0px to 600px to be 100% width, on screen sizes from 600px to 1000px I wanted them to be 50% width and on screen sizes over 1000px I wanted them to be 25% width. I used min-width in the example above, min-width is used when you want your styles to go from mobile up to desktop, but you could use max-width if you wanted to go desktop down to mobile. It is generally easier to override styles when you go from mobile up to desktop.

The best way to learn flexbox is to dive in and try it. There are many uses and many caveats that I have not mentioned, but you will learn them as you use flexbox. If you want more control of element placement, and your client doesn’t mind not supporting IE11 and before, a new method is available called CSS Grid. I will go over it in the next lesson, and hopefully provide you with the knowledge you need to be ahead of others in the field.