How CSS Flexbox works: a clear introduction to the layout of elements on a web page

CSS Flexbox is a technology for creating complex, flexible layouts by placing elements correctly on the page. About the technology itself is written here. We decided to explain the features of CSS Flexbox using gifs.

Note You are reading an improved version of an article we once published.

It has 4 divs of different sizes, which are inside a gray div. Each div has the property display: block. Therefore, each block occupies the entire width of the line. To get started with CSS Flexbox, you need to make the container a flex-container. 

So, the blocks now have a property flex-context, which in the future will allow you to manage them much more easily than using standard CSS.

CSS Flexbox: flex-container axes

By default, all items are placed along the main axis – from left to right. This is why the blocks in the previous example are lined up when we applied display: flex. But the flex-direction allows you to rotate the main axis.

Note that flex-direction: column does not align the blocks on an axis perpendicular to the main axis. The main axis itself changes its position, and now points downward.

There are a couple more properties for flex-direction: row-reverse and column-reverse.

Justify-content can take 5 values:

  • flex-start
  • flex-end
  • center
  • space-between
  • space-around
  • justify-content

Space-between sets the same distance between blocks, but not between container and blocks. Space-around also sets the same distance between blocks, but now the distance between container and blocks is half the distance between blocks.

While justify-content works with the main axis, align-items works with the axis perpendicular to the main axis. Let’s go back to flex-direction: row and walk through the align-items commands:

  • flex-start
  • flex-end
  • center
  • stretch
  • baseline
  • CSS Flexbox: align-items

Note that for align-items: stretch the height of blocks must be equal to auto. For align-items: baseline you don’t need to remove paragraph tags, otherwise it will look like this:

To get a better understanding of how the axes work, let’s combine justify-content with align-items and see how center alignment works for the two flex-direction properties:

This is responsible for the original size of the elements before they are resized by other CSS Flexbox:flex-basis properties

flex-basis affects the size of elements along the main axis. Let’s see what happens if we change the direction of the major axis:

CSS Flexbox

Notice that we had to change the height of the elements as well: flex-basis can determine both the height of the elements and their width depending on the direction of the axis.

The default value of flex-grow is 0. This means that the blocks are not allowed to grow in size.

Now the blocks have occupied the rest of the space in the container. But what does flex-grow: 1 mean? Let’s try to make the flex-grow equal to 999.

And… nothing happened. This is because flex-grow takes relative values, not absolute values. This means that it doesn’t matter what value flex-grow has, it is important what value it is relative to the other blocks.

At the beginning, the flex-grow of each block is 1, which makes the total value 6. This means that our container is divided into 6 parts. Each block will occupy 1/6 of the available space in the container. When the flex-grow of the third block becomes 2, the container is divided into 7 parts: 1 + 1 + 2 + 1 + 1 + 1. The third block now takes up 2/7 of the space, the others take up 1/7 each. And so on.\

The flex-grow only works for the main axis until we change its direction

The exact opposite of flex-grow. Determines how much the block can shrink in size. flex-shrink is used when elements don’t fit in the container. You determine which elements should shrink in size and which should not. The default value of flex-shrink for each block is 1. This means that blocks will be shrinked when the container is shrunk.

Now let’s change the value of flex-shrink for the third block to 0. It is forbidden to shrink, so its width will remain 120px:

  • The flex-shrink is based on proportions. That is, if the first block has a flex-shrink of 6 and the others have a flex-shrink of 2, this means that the first block will shrink three times faster than the others.
  • Replaces flex-grow, flex-shrink, and flex-basis. Default values: 0 (grow) 1 (shrink) auto (basis).
  • Both have the same flex-basis. That means both will be 300px wide (container width: 600px plus margin and padding). But when the container starts to increase in size, the first block (with the larger flex-grow) will expand twice as fast, and the second block (with the largest flex-shrink) will shrink twice as fast.
  • You can find even more possibilities of this property in the animated CSS flex tutorial.

How does CSS Flexbox change size?

When the first box is increased, it does not become twice the size of the second box, and when the second box is decreased, it does not become half the size of the first box either. This is because flex-grow and flex-shrink are responsible for the growth and contraction rate.

A bit of math

The initial size of the container: 640px. Subtract 20px on each side for padding, and we’re left with 600px for the two blocks. When the width of the container becomes 430px (210px loss), the first block (flex-shrink: 1) loses 70px. The second block (flex-shrink: 2) loses 140px. When the container shrinks to 340px, we lose 300px. The first block loses 100px, the second block loses 200px. The same thing happens with flex-grow.

If you’re also interested in CSS Grid, you can check out our article where we look at Flexbox and Grid.