Mind Diary

Flexbox

The layouts we can create with floats are actually somewhat limited, so the “flexbox” mode was invented to break out of these limitations.

Whereas floats let us position our boxes only horizontally, the “Flexible Box” or “Flexbox” layout mode gives us complete control over the alignment, direction, order, and size of our boxes.

The various layout possibilities offered by the flexbox mode

It is recommended to use flexbox to lay out your web pages as much as possible, reserving floats for when you need text to flow "around" a box (i.e., a magazine–style layout) or when you need to support legacy web browsers. Flexbox versus floats

Flexbox Overview:

Flexbox uses two types of boxes that we have never seen before:

  • Flex containers.
  • Flex items.

The job of a flex container is to group a bunch of flex items together and define how they are positioned.

Flex container and flex items

Every HTML element that is a "direct child" of a flex container is an item.
The main purpose of flex items are to let their container know how many things it needs to position.

As with float–based layouts, defining complex web pages with flexbox is all about nesting boxes. We align a bunch of flex items inside a container, and, in turn, those flex items can serve as flex containers for their own items.

Remember that the fundamental task of laying out is just "moving" a bunch of nested boxes around.

Flex Containers:

The first step in using flexbox is to turn one of our HTML elements into a flex container.
We do this using the display property giving it a value of flex. Thus, we are telling the web browser that everything in the box should be rendered with flexbox instead of the default box model.

We turn an HTML item into a flex container like this:

div {
   display: flex;
}

Aligning a Flex Item:

After we have defined an HTML element as a flex container, our next job is to define the horizontal alignment of its items using the justify–content property, like this:

div {
   display: flex;
   justify–content: center;
}
Justify-content alignment of flex items

Values for the justify–content property:

  • center.
  • flex–start.
  • flex–end.
  • space–around.
  • space–between.

The last two options are only useful when we have multiple flex items in a container.

Distributing Multiple Flex Items:

The justify–content property lets us distribute items equally inside a container.

Justify-content distribution of flex items

While the space–around value makes the flex container automatically distribute the extra horizontal space to either side of each item, the space–between value adds that extra space between items.

Grouping Flex Items:

Flex containers only know how to position elements that are one level deep (i.e., their child elements). They do not care one bit about what is inside their flex items.

This means that "grouping flex items" is another tool for the layout–creation process. Wrapping a bunch of flex items in an extra <div> results in a totally different layout.

Thus, if we have three flex items, and we wanted to group two of them together so that we would have only two, under the existing space–between behavior, they will snap to the "left" and "right" side of the page.

Cross-Axis (Vertical) Alignment:

Flex containers can also define the vertical alignment of their items (something that is simply not possible with floats).

Align-items versus justify-content

When we have a flex container that has an explicit height, then its flex items can be positioned "vertically" inside of it.
The official specification calls this cross–axis alignment (for our purposes it might as well be called “vertical” alignment).

Vertical alignment is defined by adding an align–items property to a flex container, like this:

div {
   align–items: center;
}

The available options for the align–items property:

  • center.
  • flex–start  (top).
  • flex–end  (bottom).
  • stretch.
  • baseline.
Various values for the align-items property

What about the stretch value ?
It displays the background of each element as the box for each item extends the full height of the flex container, regardless of how much content it contains.
Thus, we can create equal–height columns with a variable amount of content in each one — again, something that is very difficult to do with floats.

Wrapping Flex Items:

Flexbox is a more powerful alternative to float-based grids.
Not only can it render items as a grid — it can change their alignment, direction, order, and size, too.

To create a grid, we need the flex–wrap property.

The flex-wrap property

If you would like make use of the flexbox model to create a photo gallery, add the following code to your HTML file:

<div class="gallery_container">

   <div class="gallery_grid">

      <div>
         <img src="images/name.jpg">
      </div>
      <div>
         <img src="images/name.jpg">
      </div>
      <div>
         <img src="images/name.jpg">
      </div>
      <div>
         <img src="images/name.jpg">
      </div>
      <div>
         <img src="images/name.jpg">
      </div>

   </div>

</div>

Then add the following CSS declarations to your CSS stylesheet:

.gallery_container {
   display: flex;
   justify–content: center;
}

.gallery_grid {
   display: flex;
   width: 900px;
   justify–content: center;
   flex–wrap: wrap;
}

.gallery_grid div {
   width: 300px;
}

.gallery_grid div img {
   width: 99%;
   height: auto;
}
Creating a grid for a photo gallery using the flex-wrap property of the flexbox model

Flex Container Direction:

“Direction” refers to whether a container renders its items horizontally or vertically.
By default a flex container renders its flex items horizontally, which means that the flex items are drawn one after another in the same row before popping down to the next column when they run out of space.

The direction of the flex items inside a flex container

The flexbox model has the ability to transform rows into columns using only a single line of CSS:

.gallery_grid {
   flex–direction: column;
}

The above–mentioned CSS rule changes the direction of the container from the default row value. Instead of a grid, our page now has a single "vertical" column.

The key challenge of responsive design is presenting the same HTML markup to both mobile and desktop users. This presents a bit of a problem, as most mobile layouts are a single column, while most desktop layouts stack elements horizontally. That is why the flex–direction property is going to become useful in building responsive layouts.

The flex-direction column

Alignment Considerations:

Notice that the column is hugging the "left side" of its flex container despite our justify–content: center; rule. When we rotate the direction of a container, we also rotate the direction of the justify–content property. It now refers to the container's vertical alignment, not its horizontal alignment.

The axes of the flex direction

Thus, in order to horizontally center our column, we need to define an align–items property:

.gallery_grid {
   flex–direction: column;
   align–items: center;
}

Flex Container Order:

The flex–direction property also offers us control over the order in which items appear via the row–reverse and column–reverse values.

Flex direction reverse .gallery_grid {
   flex–direction: row–reverse;
}
Flex direction row reverse

Both rows are now rendered right–to–left instead of left–to–right.
Notice how this only swaps the order on a per–row basis: the first row does not start at 5, it starts at 3.
This is a useful behaviour for a lot of common design patterns (column–reverse in particular opens up a lot of doors for mobile layouts).

Flex Item Order:

It is not only possible to position flex items through their parent containers, but also to manipulate individual items.

Flex direction of flex containers versus order of flex items

Adding an order property to a flex item defines its order in the container without affecting surrounding items.
Its default value is 0, and increasing or decreasing it from there moves the item to the right or left, respectively.

Flex Item Alignment:

We can also align flex items individually using the align–self property. Adding this to a flex item overrides the value of the align–items that is applied to its container:

.subscribe {
   align–self: flex–end;
}

The values for the align–self property are the same as those of the align–items property.

Flexible Items:

Flex items are flexible: they can “shrink” and “stretch” to match the width of their containers.

The flex property defines the “width” of individual items in a flex container. Or, more accurately, it allows them to have flexible widths.
For example, an item with a flex value of 2 will grow twice as fast as items with the default value of 1.

The flex property which allows flex items to have flexible widths

For example, if we have three flex items, we can make the third item grow twice as fast as the other two with the following CSS rule:

.item_three {
   flex: 2;
}

Static Item Widths:

We can mix–and–match “flexible boxes” with “fixed–width” ones. flex: initial; falls back to the item's explicit width property.
Thus, we can combine static and flexible boxes in complex ways.

Combining flexible and static items

Suppose we have three boxes like shown in the diagram above, all of them have the same flex: 1; CSS rule, but we want to make the box in the centre flexible, while having the ones on either side of always the same size — then, all we need to do is add the following rule to our CSS stylesheet:

.item_one,
.item_three {
   flex: initial;
   width: 300px;
}

Without that flex: initial; line, the flex: 1; rule would be inherited causing the width property (width: 300px;) to be ignored.

Summary:

Compared to floats, the flexbox model provide us with amazing tools that makes it a cleaner option for laying out modern websites:

  • Use display: flex; to create a flex container.
  • Use justify–content to define the horizontal alignment of items.
  • Use align–items to define the vertical alignment of items.
  • Use flex–direction if you need columns instead of rows.
  • Use the row–reverse or column–reverse values to flip item order.
  • Use order to customize the order of individual elements.
  • Use align–self to vertically align individual items.
  • Use flex to create flexible boxes that can stretch and shrink.

These flexbox properties tell web browsers how to arrange a bunch of HTML elements. The hard part is not actually writing the HTML and CSS code, it is figuring out, conceptually (on a piece of paper), the behaviour of all the necessary boxes in order to create a given layout.

When a designer hands you a mockup to implement, your first task is to draw a bunch of boxes and determine how they are supposed to stack, stretch, and shrink to achieve the desired design.
Once you have got that done, it should be pretty easy to code it up using these new flexbox techniques.