Chapter 3. Flex Items

In the previous chapters, we learned how to globally lay out all the flex items within a flex container by adding flexbox property values to that container. The flexible box layout specification provides several additional properties applicable directly to flex items. With these flex item–specific properties, we can more precisely control the layout of individual flex containers’ non-anonymous flex items.

Items with display: flex; become flex containers, and their non-absolutely positioned children become flex items
Figure 3-1. Items with display: flex; become flex containers, and their non-absolutely positioned children become flex items

Now that we have a good understanding of the properties applicable to the flex container, it’s time to focus on properties applicable to the flex items.

What Are Flex Items?

We create flex containers simply by adding a display: flex or display: inline-flex to an element that has child nodes. The children of those flex container are called flex items, be they DOM nodes, nonempty text nodes, or generated content.

When it comes to text-node children of flex containers, if the text node is not empty (containing content other than whitespace) it will be wrapped in an anonymous flex item, behaving like its flex item siblings. While these anonymous flex items do inherit all the flex properties set by the flex container, just like their DOM node siblings, they are not directly targetable with CSS. Therefore, we can’t directly set any of the flex item–specific properties on them.

Generated content can be targeted directly; therefore all the properties discussed in this chapter apply equally to generated content as they do to element nodes.

Whitespace-only text nodes within a flex container are ignored, as if their display property were set to none, as the following code example shows:

nav ul {
  display: flex;
}

<nav>
  <ul>
    <li><a href="#1">Link 1</a></li>
    <li><a href="#2">Link 2</a></li>
    <li><a href="#3">Link 3</a></li>
    <li><a href="#4">Link 4</a></li>
    <li><a href="#5">Link 5</a></li>
  </ul>
</nav>

In the preceding code, with its display property set to flex, the unordered list is the flex container, and its child list items are all flex items. These list items, being flex items, are flex-level boxes, semantically still list items, but not list items in their presentation. They are not block-level boxes either. Rather, they participate in their container’s flex formatting context. The whitespace is ignored. The links, which are descendants of the flex items, are not impacted by in inclusion of flex display on their parent’s parent.

Flex Item Features

The margins of flex items do not collapse. The float and clear properties don’t have an effect on flex items, and do not take a flex item out of flow. Additionally, vertical-align has no effect on a flex item. However, the float property can still affect box generation by influencing the display property’s computed value, as the following code example shows:

aside {
  display: flex;
}
img {
  float: left;
}

<aside>
    <!-- this is a comment -->
    <h1>Header</h1>

    <img src="images/foo.jpg" alt="Foo Master">
    Some text
</aside>

In this example, the aside is the flex container. The comment and whitespace-only text nodes are ignored. The text node containing “some text” is wrapped in an anonymous flex item. The header, image, and text node containing “some text” are all flex items. As the image is a flex item, the float is ignored. Even though images and text nodes are inline-level nodes, being flex items, as long as they are not absolutely positioned, they are blockified:

aside {
  display: flex;
}

<aside>
    <!-- a comment -->
    <h1>Header</h1>

    <img src="images/foo.jpg" alt="foo master">
    Some text <a href="foo.html">with a link</a> and more text
</aside>

In the last example, the markup is similar to the code in the second example, with the addition of a link within the nonempty text node. In this case, we are creating five flex items. The comment and whitespace-only text nodes are ignored. The header, the image, the text node before the link, the link, and the text node after the link are all flex items. The text nodes containing “some text” and “and more text” are wrapped in anonymous flex items. As these two text node children of the <aside> are not contiguous, they are wrapped in separate anonymous flex items. The header, image, and link, being DOM nodes, can be targeted directly with CSS. The anonymous flex containers are not directly targetable.

Absolute positioning

While a value of float: left or float: right on the child of a flex container does not float the item—as the child is a flex item and the float is ignored—setting position: absolute is a different story. The absolutely-positioned children of flex containers, just like any other absolutely-positioned element, are taken out of the flow of the document.

They do not get converted to flex items. They are not in the document flow. They do not participate in flex layout. However, they can be impacted by the properties set on the flex container, just like a child can be impacted by a parent element that isn’t a flex container. In addition to inheriting inheritable properties as they would had the parent not been a flex container, the parent’s properties impact the origin of the positioning.

The absolutely positioned child of a flex container is impacted by both the justify-content value of the parent flex container and its own align-self value, if there is one. For example, if you set align-content: center; on the absolutely positioned child, it will by default be centered on the flex container parent’s cross-axis. The order property may not impact where the absolutely-positioned flex container child is drawn, but it does impact the order of when it is drawn in relation to its siblings.

min-width

In Figure 3-2, you’ll note the line that is set to the nowrap default overflows the flex container. This is because when it comes to flex items, the implied value of min-width is auto, rather than 0. Originally in the specification, if the items didn’t fit onto that single main-axis, they would shrink. However, the specification of min-width was altered. In the CSS 2.1 specification, the default value for min-width is 0. Now, for flex items, the implied minimum size is auto, not 0.

Flex items overflowing their container when min-width defaults to auto, unless wrapping is allowed
Figure 3-2. Flex items overflowing their container when min-width defaults to auto, unless wrapping is allowed

If you set the min-width to a width narrower than the computed value of auto—for example, if we declare min-width: 0;—the flex items in the nowrap example will shrink to be narrower than the flex items in containers that are not allowed to wrap, as shown in Figure 3-3. This is what Safari 9 displays by default, as it has not updated the implied min-width change. We’ll cover flex item width in greater depth in “The flex Property”.

Flex items in non-wrapping containers will shrink if the min-width is explicitly set to 0, which is the default in Safari 9
Figure 3-3. Flex items in non-wrapping containers will shrink if the min-width is explicitly set to 0, which is the default in Safari 9

Flex Item–Specific Properties

While the flex items’ alignment, order, and flexibility are to some extent controllable via properties set on their parent flex container, there are several properties that can be applied to individual flex items for more granular control.

The flex shorthand property, along with its component properties of flex-grow, flex-shrink, and flex-basis, control the flexibility of the flex items. The align-self helps control a flex item’s alignment. The order property provides for more granular control of the visual ordering of individual or groups of flex items. All of these properties are discussed in the following sections.

The defining aspect of flex layout is the ability to make the flex items “flex”: altering their width or height to fill the available space in the main dimension. A flex container distributes free space to its items proportional to their flex grow factor, or shrinks them to prevent overflow proportional to their flex shrink factor.

Defining the flex shorthand property on a flex item, or defining the individual properties that make up the shorthand, enables developers to define the grow and shrink factors. If there is excess space, you can tell the flex items to grow to fill that space. Or not. If there isn’t enough room to fit all the flex items within the flex container at their defined or default sizes, you can tell the flex items to shrink proportionally to fit into the space. Or not. This is all done with the flex property, which is a shorthand property for flex-grow, flex-shrink, and flex-basis. While these three subproperties can be used separately, it is highly recommended to always use the flex shorthand.

We will briefly introduce the flex shorthand property, then dive deeper into the three longhand values that make it up. It is important to fully understand what each component is doing so you can effectively use the flex shorthand property.

The flex Property

The flex shorthand, a flex item property, is made up of the flex-grow, flex-shrink, and flex-basis properties, which define the flex growth factor, the flex shrink factor, and the flex basis, respectively.

The flex property specifies the components of a flexible length: the “length” of the flex item being the length of the flex item along the main-axis (see “Understanding axes”). When a box is a flex item, flex is consulted instead of the main-size (height or width) property of the flex item to determine the size of the box. The “components” of the flex property include the flex growth factor, flex shrink factor, and the flex basis. If the target of a selector is not a flex item, applying the flex property to it will have no effect.

The flex basis determines how the flex growth and shrink factors are implemented. As its name suggests, the flex-basis component of the flex shorthand is the basis on which the flex item determines how much it can grow to fill available space or how much it should shrink to fit all the flex items when there isn’t enough space. It’s the initial size of each flex item, and can be restricted to that specific size by specifying 0 for both the growth and shrink factors:

.flexItem {
    flex: 0 0 200px;
}

In the preceding code snippet, the flex item will have a main-size of exactly 200 px, as the flex basis is 200 px, and it is neither allowed to grow nor shrink.

It is important to understand the three components that make up the flex shorthand property, which is the property you should be employing. The reason it is advised to use flex rather than its three individual subproperties is because the spec (and therefore the browser) resets any missing flex values to sensible defaults, which are not always the individual property defaults.

To ensure you fully grok flex, let’s deep dive into its three components.

The order of flex is important, with the first float number being the growth factor.

The flex-grow Property

The flex-grow property defines whether a flex item is allowed to grow when there is available space, and, if it is allowed to grow and there is available space, how much will it grow proportionally relative to the growth of other flex item siblings.

The value flex-grow and of the flex-grow portion of the flex shorthand is always a number. Negative numbers are not valid. Float values, as long as they are greater than 0, are valid.

The value specifies the growth factor, which determines how much the flex item will grow relative to the rest of the flex item siblings as the flex container’s free space is distributed. If there is any available space within the flex container, the space will be distributed proportionally among the children with a nonzero positive growth factor based on the various values of those growth factors.

For example, with the 750px wide horizontal flex container with three flex items all set to width: 100px, as in the four examples in Figure 3-4, you can dictate none, one, two, or all three of the flex items to grow to fill the extra 450px of available space.

With a growth factor of 0, the flex item will not grow; any positive value will allow the item to grow proportionally to the value
Figure 3-4. With a growth factor of 0, the flex item will not grow; any positive value will allow the item to grow proportionally to the value

As noted in min-width, if no width or flex basis is set, the flex basis defaults to auto, meaning each flex item basis is the width of its nonwrapped content. auto is a special value: it defaults to content unless the item has a width set on it, at which point the flex-basis becomes that width. The auto value is discussed in auto. Had we not set the width, in this example scenario, with our smallish font size, we would have had more than 450 px of distributable space along the main-axis.

Note

The examples in this section describe the basics of the growth factor. The main-size of a flex item is impacted by the available space, the growth factor of all the flex items, as well as the flex basis of the item. We have yet to cover flex-basis. We will revisit both the growth and shrink factors and these examples when we learn about flex basis.

Note that the amount of distributable space depends on the basis. In Figure 3-4, because the width of the flex items was set to 100 px each and no basis was set, we have 450 px of distributable space. When a different width or no width is declared, or if a basis is set, the distributable space is different, as shown in Figure 3-6.

Any positive value greater than 0 for the growth factor means the flex item can grow to fill a portion or all of the available space. You can tell the items not to grow with a growth factor of 0, as demonstrated in the first example of Figure 3-4. You can mix and match: growing some flex items and not others, as demonstrated in the second example.

In the 4 examples in Figure 3-4, because the flex container is 750 px wide and each of the 3 flex items has a width: 100px declared, there are 450 extra pixels to be distributed among the flex items that are allowed to grow:

750px - (3 * 100px) = 450px

We have 450 px of empty space in the main end direction as align-items defaults to flex-start. The first example has no growth factors set, so no flex items grew.

Non-Null Growth Factor

In the second example of Figure 3-4, the first two flex items, with a growth factor set to 0, will not grow. Only the third flex item has a value greater than 0, with flex-grow: 1 set, which means the single element with a positive growth factor value will take up all the extra available space.

The first two flex items with flex growth factor of 0 will remain at 100px wide, even if the content doesn’t fit. Only the third flex item is allowed to grow, and therefore it must grow, taking up the extra 450 pixels to become 550 px wide.

The growth factor needs to be a positive, non-null float value for the flex item to grow. In this example the growth factor was 1, but had it been 0.000001 or 10000000, the layout would be the same.

Growing Proportionally Based on Growth Factor

If all items are allowed to grow, the excess space is distributed proportionally based on the flex growth factors. In the third example, with two flex items having a growth factor of 1, and one flex item having a growth factor of 3, we have a total of five growth factors:

 (2 x 1) + (1 x 3) = 5

With 5 growth factors, and a total of 450 px needing to be distributed, each growth factor is worth 90 px:

450px / 5 = 90px.

Before being allowed to grow based on individual flex item’s growth factor, the flex items were each 100 px wide as set forth by the width property. With each growth factor being 90 px, we have 2 flex items with a width of 190 px each and the last flex item has a width of 370 px:

100px + (1 x 90px) = 190px
100px + (3 x 90px) = 370px

In the last example, we have a total of 2.5 growth factors:

 (2 x 0.5) + (1 x 1.5) = 2.5

With 2.5 growth factors, and a total of 450 px needing to be filled, each growth factor is worth 180 px:

450px / 2.5 = 180px

Again, the default flex item size was 100 px, with the flex basis defaulting to auto, leading us to have the exact same layout as in the second example. This demonstrates how the distribution of extra space is proportional. Again we see 2 flex items with a width of 190 px and the last flex item having a width of 370 px:

100px + (0.5 x 180px) = 190px
100px + (1.5 x 180px) = 370px

Had we declared growth factors of 0.1, 0.1, and 0.3, respectively, or 25, 25, 75, the layout would have been identical.

Growth Factor with Different Widths

As mentioned, the available space is distributed proportionally among the flex items in each flex row based on the flex growth factors, without regards to the original, underlying widths.

In Figure 3-5, in the second example, we have flex items that are 100 px, 250 px, and 100 px wide, with growth factors of 1, 1, and 3, respectively, in a container that is 750 px wide. This means we have 300 px of extra space to distribute among a total of 5 growth factors. Each growth factor is therefore 60 px, meaning the first and second flex items, with a growth factor of 1, will each grow by 60 px, and the last will grow by 180 px as the growth factor is set to 3.

The available space is evenly distributed to each growth factor; any positive value will allow the item to grow proportionally to the value.
Figure 3-5. The available space is evenly distributed to each growth factor; any positive value will allow the item to grow proportionally to the value

The available space, growth factors, and width of each growth factor are:

Available space: 750px - (100px + 250px + 100px) = 300px
Growth factors:  1 + 1 + 3 = 5
Width of each growth factor: 300px / 5 = 60px

When flexed, the width based on their original width and growth factors become:

item1 = 100px + (1 * 60px) = 160px
item2 = 250px + (1 * 60px) = 310px
item3 = 100px + (3 * 60px) = 280px

item1 + item2 + item3 = 160px + 310px + 280px = 750px

Growth Factors and the flex Property

The flex property takes up to three values—the growth factor, shrink factor, and basis. The first positive non-null float value, if there is one, is the growth factor. When the growth factor is omitted in the shorthand, it defaults to 1. Otherwise, if neither flex nor flex-grow is included, it defaults to 0.

In the second example in Figure 3-4, because we declared a value for flex-grow only, the flex basis was set to auto, as if we had declared:

#example2 flex-item {
  flex: 0 1 auto;
}
#example2 flex-item:last-child {
  flex: 1 1 auto;
}

Declaring flex-grow is strongly discouraged. Rather, declare the growth factor as part of the flex shorthand.

Had we declared flex: 0, flex: 0.5;, flex: 1;, flex: 1.5;, and flex: 3; in the examples in Figure 3-4 instead of ill-advisedly declaring flex-grow values, the flex basis would be set to 0%, and the width distribution would have been very different, as shown in Figure 3-6:

#example2  flex-item {
  flex: 0 1 0%;
}
#example2  flex-item:last-child {
  flex: 1 1 0%;
}
Flex grow looks different when the flex basis is 0, and some items are not allowed to grow
Figure 3-6. flex-grow looks different when the flex basis is 0, and some items are not allowed to grow

As the shrink factor defaults to 1 and the basis defaults to 0%, the following CSS is identical to the preceding code:

#example2  flex-item {
  flex: 0;
}
#example2  flex-item:last-child {
  flex: 1;
}

You may notice something odd: the flex basis has been set to zero, and only the last flex item has a positive value for flex grow. Logic would seem that the widths of the 3 flex items should be 0, 0, and 750 px, respectively. But logic would also dictate that it makes no sense to have content overflowing its flex item if the flex container has the room for all the content, even if the basis is set to zero.

The specification authors thought of this quandary. When the flex property declaration explicitly sets or defaults the flex-basis to 0 px and a flex item’s growth factor is 0, the length of the main-axis of the nongrowing flex items will shrink to the smallest width the content allows, or smaller. In our example, the width is the width of the widest word “flex:”.

As long as a flex item has a visible overflow and no min-width (or min-height for vertical main-axes) explicitly set, the minimum width (or minimum height) will be the smallest width (or height) that the flex item needs to be able to fit the content or the declared width (or height), whichever is smaller. In the first and second examples in Figure 3-6, even though the growth factor is 0, the flex items don’t shrink to 0. Rather, they shrink to the width of the widest nonbreakable word, as the word “flex-” is narrower than 100 px. Had width: 10px been set instead of width: 100px, the flex items would have narrowed down to whichever was smaller: the width of the word “flex-” or 10 px.

If all items are allowed to grow, and the flex basis for each flex item is 0%, all of the space—the entire 750 px rather than just excess space—is distributed proportionally based on the growth factors. In the examples the flex container is 750 px wide. In Figure 3-6, as the flex basis is zero, rather than auto, and with no positive shrink factors, the first two flex items are only as wide as their widest content (the word flex:), and all the extra space goes to the third flex item with a positive growth factor. This will make more sense after reading the flex-shrink section (see “The flex-shrink Property”). In the third example, with two flex items having growth factors of one, and one flex item having a growth factor of three, we have a total of five growth factors:

 (2 x 1) + (1 x 3) = 5

With 5 grows factors, and a total of 750 px, each growth factor is worth 150 px:

750px / 5 = 150px.

While the default flex item size was 100 px, the flex basis of 0 overrides that, leaving us with 2 flex items at 150 px each and the last flex item with a width of 450 px:

1 x 150px = 150px
3 x 150px = 450px
150px + 150px + 450px = 750px

Similarly, in the last example of Figure 3-6, with two flex items having growth factors of 0.5, and one flex item having a growth factor of 1.5, we have a total of 2.5 growth factors:

 (2 x 0.5) + (1 x 1.5) = 2.5

With 2.5 grows factors, and a total of 750 px, each growth factor is worth 300 px:

750px / 2.5 = 300px.

While the default flex item size was 100 px, the flex basis of 0% overrides that, leaving us with 2 flex items at 150 px each and the last flex item with a width of 450 px:

0.5 x 300px = 150px
1.5 x 300px = 450px
150px + 150px + 450px = 750px

This is different from declaring only flex-grow, as shown in Figure 3-7. Only declaring flex-grow means flex-basis defaults to auto. When set to auto, only the extra space, not all the space, is distributed proportionally. This lack of simplicity is why it is highly encouraged to always use the flex shorthand instead of flex-grow, flex-shrink, and flex-basis separately or not at all.

When using flex-grow instead of the flex shorthand, the flex basis will be auto instead of 0.
Figure 3-7. When using flex-grow instead of the flex shorthand, the flex basis will be auto instead of 0.

While the available space is distributed proportionally based on the flex items’ growth factor, the amount of available space is defined by the flex basis, which is discussed in a following section. Let’s first cover the shrinking factor.

The flex-shrink Property

The flex-shrink portion of the flex shorthand property specifies the shrink factor. The shrink factor determines how much a flex item will shrink relative to the rest of the flex item siblings when there isn’t enough space for them all to fit as defined by their content, basis, and other CSS properties. Basically, the shrink factor defines how the negative space is distributed, or how flex items should become narrower or shorter, when the flex container parent isn’t allowed to otherwise grow or wrap.

Figure 3-8 is similar to Figure 3-4, with the flex items set to 300 px instead of 100 px. We have a 750 px-wide flex container with three 300 px-wide flex items. The total width of the 3 items is 900 px, meaning the content is 150 px wider than the parent flex container. If the items are not allowed to shrink or wrap (see “The flex-wrap Property”), they will burst out from the fixed-size flex container. This is demonstrated in the first example in Figure 3-8: those items will not shrink as they have a null shrink factor. Instead, the flex items overflow the flex container along the main-end side, as justify-content (described in “The justify-content Property”) defaults to flex-start.

In the second example in Figure 3-8, only the last flex item is set to be able to shrink. We forced the single element with a positive shrink factor to do all the shrinking necessary to enable all the flex items to fit within the container. With 900 px worth of content needing to fit into our 750 px container, we have 150 px of negative space. The 2 flex items with no shrink factor stay at 300 px wide. The third flex item, with the positive value for the shrink factor, shrinks down by 150 pixels, to be 150 px wide, enabling the 3 items to fit within the container. In this example the shrink factor was 1, but had it been 0.001 or 100, the layout would be the same.

A flex shrink factor of 0 will not allow flex items to shrink; any positive value will enable the item to shrink proportionally relative to sibling flex items that are allowed to shrink on the same flex line
Figure 3-8. A flex shrink factor of 0 will not allow flex items to shrink; any positive value will enable the item to shrink proportionally relative to sibling flex items that are allowed to shrink on the same flex line

When omitted in the shorthand flex property value or when both flex and flex-shrink are omitted, the shrink factor defaults to 1. Like the growth factor, the value is always a number. Negative numbers are not valid. Floats, as long as they are greater than 0, are valid.

In the third example, we provided positive shrink factors for all three flex items:

#example3 flex-item {
  flex-shrink: 1;
}
#example3 flex-item:last-child {
  flex-shrink: 3;
}
Note

While we included the preceding code, our flex items will behave as if we had declared the following:

#example3 flex-item {
  flex: 0 1 auto;
}
f#example3 flex-item:last-child {
  flex: 0 3 auto;
}

This is likely not the layout you will be developing for production. So, use the flex shorthand.

If all items are allowed to shrink, as is the case here, the shrinking is distributed proportionally based on the shrink factor of the individual items that have a positive value set for that property.

When all items have the same basis, it’s easy to figure out how they will shrink based on the values of their shrink factors. With a parent 750 px wide, and 3 flex items with a width of 300 px, there are 150 extra pixels that need to be shaved off of the flex items that are allowed to shrink. With two flex items having a shrink factor of 1, and one flex item having a shrink factor of 3, we have a total of five shrink factors:

 (2 x 1) + (1 x 3) = 5

With 5 shrink factors, and a total of 150 px needing to be shaved off all the flex items, each shrink factor is worth 30 px:

150px / 5 = 30px.

The default flex item size was 300 px, leading us to have 2 flex items with a width of 270 px each and the last flex item having a width of 210 px, which total 750 px. In shrinking proportionally based on their shrink factor, we have dictated how they shrink to fit in the space allotted:

300px - (1 x 30px) = 270px
300px - (3 x 30px) = 210px

270px + 270px + 210px = 750px

The flex items will shrink to 270 px, 270 px, and 210 px, respectively, as long as the content (like media objects or nonwrappable text) within each flex item is not wider than 270 px, 270 px, or 210 px, respectively:

flex-item {
  flex: 1 0.25 auto;
}
flex-item:last-child {
  flex: 1 0.75 auto;
}

The preceding code produces the same outcome: while the numeric representation of the shrink factors are different, they are proportionally the same.

A positive shrink value does not mean a flex item will necessarily shrink even if there isn’t room available in the parent flex container for it and its siblings. If the flex item contains content that cannot wrap or otherwise shrink in the main-dimension, the flex item will not shrink.

For example, if the first flex items contain a 300 px–wide image or an URL of characters wider than 300 px, the 150 px of negative space would be distributed among the four available shrink factors:

item1 = 300px - (0 x 37.5px) = 300.0px
item2 = 300px - (1 x 37.5px) = 262.5px
item3 = 300px - (3 x 37.5px) = 187.5px

In this case, the first item would be 300 px, with the 150 px of negative space distributed proportionally based on the shrink factors of the second and third flex items. That first flex item can not shrink, and other flex items can shrink, therefore it will not shrink, as if it had a null shrink factor. We have 4 unimpeded shrink factors for 150 px of negative space, with each shrink factor being worth 37.5 px. The flex items are 300 px, 262.5 px, and 187.5 px respectively, for a total of 750 px.

Had the image or URL in the first flex item been 296 px wide, that first flex item would have been able to shrink by 4 px. We would have then distributed the 146 of negative space among the 4 remaining shrink factors for flex items that were 296 px, 263.5 px, and 190.5 px wide, respectively.

If all 3 flex items contained non-wrappable URLs, or media 300 px or wider, the 3 flex items would not shrink, appearing similar to the first example in Figure 3-8.

All the items had the same width or flex basis, therefore this is easy to calculate. Had they not had the same widths, this equation would be more complex. This only works this way because all the flex items had the same flex bases.

Proportional Based on Width and Shrink Factor

The preceding code example was fairly simple because all the flex items started with the same width. But what if the widths were different? What if the first and last flex items had a width of 250 px and the middle flex item had a width of 500 px?

Flex items shrink proportionally relative to both the shrink factors and the flex item width, with the width often being content, the width of the flex item’s content with no wrapping. In Figure 3-9, we are trying to fit 1,000 pixels into a 750 px-width flex container. We have an excess of 250 px to be removed from five shrink factors. If this were a flex-grow concern, we would simply divide 250 px by 5, allocating 50 px per growth factor. If we shrank that way, we would see 200 px, 550 px, and 100 px wide flex items, respectively. But that’s not what we see.

Flex items shrink proportionally relative to their shrink factor
Figure 3-9. Flex items shrink proportionally relative to their shrink factor

Instead we have 250 px of negative space to proportionally distribute. To get the shrink factor proportions, we divide the negative space by the actual space times their shrink factors:

Using this equation, we learn the shrink factor percent:

= 250px / ((250px * 1) + (500px * 1) + (250px * 3))
= 250px / 1500px
= 0.166666667

When we reduce each flex item by 16.67% times the shrink factor, we end up with flex items that are reduced by:

item1 = 250px * (1 * 16.67%) = 41.67px
item2 = 500px * (1 * 16.67%) = 83.33px
item3 = 250px * (3 * 16.67%) = 125px

We get flex items that are 208.33 px, 416.67 px, and 125 px wide, respectively.

In the Real World

Allowing flex items to shrink proportionally like this allows for responsive objects and layouts that can shrink proportionally without breaking.

For example, you can create a three-column layout that smartly grows and shrinks without media queries, as shown on a wide screen in Figure 3-10 and narrower screen in Figure 3-11):

nav {
  flex: 0 1 200px;
  min-width: 150px;
}
article {
  flex: 1 2 600px;
}
aside {
  flex: 0 1 200px;
  min-width: 150px;
}
By setting different values for growth, shrink, basis, and min-width, you can create responsive layouts, with or without media queries
Figure 3-10. By setting different values for growth, shrink, basis, and min-width, you can create responsive layouts, with or without media queries
With growth, shrink, basis, and min-width set, you can create responsive layouts that look great on narrower screens, without needing a multitude of media queries
Figure 3-11. With growth, shrink, basis, and min-width set, you can create responsive layouts that look great on narrower screens, without needing a multitude of media queries

In this example, if the viewport is greater than 1,000 px, only the middle column grows because only the middle column was provided with a positive growth factor. We also dictated that below the 1,000 px-width mark the right column shrinks twice as fast as the left 2 columns, using min-width to ensure the columns never shrinks below its narrowest word or that minimum width, whichever is greater.

Differing Bases

With a null shrink factor, if no width or basis is set on a flex item, its content will not wrap. When we have more content than could neatly fit on one line, a positive shrink value enables the content to wrap. Shrink factors enable proportional wrapping. Because shrinking is proportional based on shrink factor, if all the flex items have similar shrink factors, the content should wrap over a similar number of lines.

Unlike in the previous examples in this chapter, in the two examples in Figure 3-12, the flex items do not have a declared width. Rather, the width is based on the content—the width defaults to auto, as does the flex basis, as if flex-basis: content were set (see “The flex-basis Property”).

Flex items shrink proportionally relative to their shrink factor and content
Figure 3-12. Flex items shrink proportionally relative to their shrink factor and content

You’ll note in the first example, all content wraps over four lines. In the second example, the first flex item, with a shrink factor half of value of the other flex items, wraps over half the number of lines. This is the power of the shrink factor.

In the third example, with a null shrink factor, the text doesn’t wrap and the flex items overflow the container.

Because the flex property’s shrink factor reduces the width of flex items proportionally, the number of lines of text in the flex items will grow or shrink as the width shrinks or grows, leading to similar height content within sibling flex items when the shrink factors are similar.

In the examples, the content of the flex items on my device are 280 px, 995 px, and 480 px, respectively—which is the width of the nonwrapping flex items in the third example (as measured by the developer tools, then rounded to make this example a little simpler). This means we have to fit 1,755 px of content into a 520 px-wide flex container by shrinking the flex items proportionally based on their shrink factor. This means we have 1,235 px of negative space to proportionally distribute.

Obviously you can’t rely on web inspector tools to figure out shrink factors for production. We’re going through this exercise to understand how shrink factors work. If minutia isn’t your thing, feel free to jump to “The flex-basis Property”.

Because flex items shrink proportionally, based on the width of their content, in our example, the single line of text flex items will end up with the same, or approximately the same, number of lines.

We didn’t declare a width, therefore we can’t simply use 300 px as the basis as we did in the previous examples. Rather, we distribute the 1,235 px of negative space proportionally based on the widths of the content—280 px, 995 px, and 480 px, respectively. We determine 520 is 29.63% of 1,755. To determine the width of each flex item with a shrink factor of 1, we multiply the content width of each flex item by 29.63%:

item1 = 280px * 29.63% =  83px
item2 = 995px * 29.63% = 295px
item3 = 480px * 29.63% = 142px

item1 +  item2 + item3  =  83px + 295px + 142px = 520px

With the default of align-items: stretch; (see “The align-items Property”), your three-column layout would have, by default, created three columns of equal height. By using a uniform shrink factor, you can dictate that the actual content of these three flex items be of approximately equal height: though, by doing this, the width of those columns will not be uniform. The width of the flex items is the purview of flex-basis.

In our second example in Figure 3-12, the flex items don’t all have the same shrink factor. The first flex item will, proportionally, shrink half as much as the others. We start with the same widths: 280 px, 995 px, and 480 px, respectively, but the shrink factors are 0.5, 1.0, and 1.0, respectively. As we know the widths of the content, the shrink factor (X) can be found mathematically:

(0.5X * 280px) + (1X * 995px) + (1X * 480px) = 1235px
1615X = 1235px
X = 1235px / 1615
X = 0.7647

We can find the final widths now that we know the shrink factor. If the shrink factor is 76.47%, it means that item2 and item3 will be 23.53% of their original widths, and item1, because it has a 0.5 shrink factor, will be 61.76% of its original width:

item1 = 280px * 0.6176 = 173px
item2 = 995px * 0.2354 = 234px
item3 = 480px * 0.2354 = 113px

item1 + item2 + item3 =  173px + 234px + 113px = 520px

The total combined widths of these 3 flex items is 520 px.

Adding in varying shrink and growth factors makes it all a little less intuitive. That’s why you likely want to always declare the flex shorthand, preferably with a width or basis set for each flex item.

If this doesn’t make sense yet, don’t worry, we’ll cover a few more examples of shrinking as we discuss flex-basis.

The flex-basis Property

Again, while we are covering the flex-basis property individually here so you fully understand it, the CSS working group encourages declaring the basis as part of the flex shorthand property instead of on its own. flex resets to common usage (rather than defaulting) the grow, shrink, and basis values if any of them are not declared within the shorthand. When flex-basis is set, instead of flex, flex items can shrink but will not grow, as if flex: 0 1 <flex-basis> were set.

Seriously, use flex instead of declaring the three longhand values separately. We’re only covering the shorthand here because 1) this is the definitive guide, so we have to, and 2) so you fully understand what the flex-basis of the flex shorthand property does. By this point, I hope you’ve been convinced.

As we’ve already seen, a flex item’s size is impacted by its content and box-model properties and can be reset via the three components of the flex property. The flex-basis component of the flex property defines the initial or default size of flex items, before extra or negative space is distributed—before the flex items are allowed to grow or shrink according to their growth and shrink factors, which we just described.

The basis determines the size of the content box, impacted by box-sizing. By default, when an element is not a flex item, the size is determined by the size of its parent, content, and box-model properties. When no size properties are explicitly declared or inherited, the size defaults to its individual content, border, and padding, which is 100% of the width of its parent for block-level elements.

The flex-basis property accepts the same length value types as the width and height properties—like 5vw, 12%, and 300px—or the key terms auto, initial, inherit, and content.

None of the flex properties are inherited by default, but you can tell a flex item to inherit the flex-basis from its parent with the inherit value.

The global values of initial resets the flex basis to the initial value of auto, so you might as well declare auto. In turn, auto evaluates to the width (or height) if declared. The main-size keyword used to do this: it was part of an older specification, but was deprecated. If the value of width (or height) is set to auto, then the value is evaluated to content.

content

The content keyword value is not supported in most browsers at the time of this writing, with the exception of Microsoft Edge 12+, but is equal to the width or height of the content. When content is used and supported, the basis is the size of the flex item’s content—the value being the main-size of the longest line of content or widest (or tallest) media object.

Until support is complete, flex-basis: content; can be easily polly-filled as it is the equivalent of declaring flex-basis: auto; width: auto; on that flex item, or flex-basis: auto; height: auto; if the main-dimension is vertical. Unfortunately, using content in the shorthand in nonsupporting browsers invalidates the entire flex declaration. The entire declaration is invalidated when any value is not understood as per the specification.

The value of content is basically what we saw in the third example in Figure 3-12, and is shown in Figure 3-13.

When set to content the basis is the width (or height) of the content
Figure 3-13. When set to content the basis is the width (or height) of the content

In the first and third examples in Figure 3-13, the width of the flex item is the size of the content; and the basis is also that width. In the first example, the flex items width and basis are approximately 132 px. The total width of the 3 flex items side by side is 396 px, fitting neatly into the parent container.

In the third example, we have set a null shrink factor: this means the flex items cannot shrink, so they won’t shrink or wrap to fit into the fixed-width flex container parent. Rather, they are the width of their nonwrapped text. That width is the value of the flex basis. The flex items’ width and basis are approximately 309 px, 1,037 px, and 523 px, respectively. You can’t see the full width of the second flex item or the third flex item at all, but they’re in the chapter files.

The second example contains the same content as the third example, but the flex items are defaulting to flex-shrink: 1: the text in this example wraps because the flex items can shrink. So while the width of the flex item is not the width of the content, the flex basis—the basis by which it will proportionally shrink—is the width of the content: 309 px, 1,037 px, and 523 px, respectively, as measured with developer tools.

When the shrink factors are the same, because flex items shrinking is proportional based on the content-width flex basis, they end up with the same or approximately the same number of lines.

Note

Until the content value is supported everywhere, you can replicate it by setting (or defaulting) the width/height and basis to auto.

It is the same as setting flex-basis: auto; width: auto; or flex-basis: auto; height: auto;.

auto

When set to auto, or omitted, the flex-basis is the main-size of the node had the element not been turned into a flex item. For length values, flex-basis resolves to the width or height value, with the exception that when the value of the width or height is auto, the value resolves to content.

If the basis is explicitly set to auto, or omitted and therefore defaults to auto, and all the flex items can fit within the parent flex container, the flex items will be their pre-flexed size, as seen in Figure 3-14. If the flex items don’t fit into their parent flex container, the flex items within that container will shrink proportionally based on their nonflexed main-sizes, unless the shrink factor is null.

When a flex basis is set, by default the item's main-size will be the value declared
Figure 3-14. When a flex basis is set, by default the item’s main-size will be the value declared

When there are no other properties setting the main-size of the flex items (there’s no width or even min-width set on these flex items), and flex-basis: auto; or flex: 0 1 auto; is set, the flex items will only be as wide as they need to be for the content to fit, as seen in the first example in Figure 3-14. In this case, they are the width of the text “flex-basis: auto”, which in this case, with this font, is approximately 110 px. The flex items are their pre-flexed size, as if set to display: inline-block;. In this example, they’re grouped at main-start because the flex container’s justify-content defaults to flex-start.

In the second example in Figure 3-14, each of the flex items has flex basis of auto and a declared width. The main-size of the nodes had the elements not been turned into a flex items would be 100 px, 150 px, and 200 px. In using flex-basis: auto we are telling it to use these underlying box-model properties to determine the flex basis.

There’s a little bit more to understanding of how auto works with the underlying width. While the examples in this section used percentages and auto, when we discussed the growth and shrink factors earlier, the flex items had underlying widths of 100 px and 300 px respectively. Because the basis was not explicitly set to a length, the width value was the basis in those scenarios.

Default Values

When neither flex-basis nor flex is set, the flex item’s main-size is the pre-flex size of the item, as their default value is auto.

In Figure 3-15 two things are happening: the flex bases are defaulting to auto, and the shrink factor of each item is defaulting to 1. That means the bases are being set to the values of the width properties: 100 px, 200 px, and 300 px in the first example and 200 px, 400 px, and 200 px in the second example, and they are all able to shrink. For each, the flex basis is their individual width value. As the combined widths are 600 px and 800 px, which are both greater than the main-size of the 540 px-wide containers, they are all shrinking proportionally to fit.

In the first example, we are trying to fit 600 px in 540 px, so each flex item will shrink by 10%, resulting in flex items that are 90 px, 180 px, and 270 px. In our second examples, we are trying to fit 800 px into 540 px, making the flex items 135 px, 270 px, and 135 px.

When no flex properties are set, the flex item's main-size will be the pre-flex size of the item
Figure 3-15. When no flex properties are set, the flex item’s main-size will be the pre-flex size of the item

Length Units

In the previous examples, the basis defaulted to the declared widths of the various flex items. We can use the same length units for our flex-basis value as we do for width and height.

When there are both flex-basis and width values, the basis trumps the width. Let’s add bases values to the first example from Figure 3-15. The flex items include the following CSS:

flex-container {
  width: 540px;
}
item1 {
  width: 100px;
  flex-basis: 300px;  /* flex: 0 1 300px; */
}
item2 {
  width: 200px;
  flex-basis: 200px;  /* flex: 0 1 200px; */
}
item3 {
  width: 300px;
  flex-basis: 100px;  /* flex: 0 1 100px; */
}
Note the width of the flex item is proportion to the flex-basis property, not the width property
Figure 3-16. Note the main-size of the flex item is proportion to the flex-basis property, not the width property

The widths are overridden by the bases. The flex items shrunk down to 270 px, 180 px, and 90 px, respectively.

While the declared basis can override the main-size of flex items, the size can be impacted by other properties, such as min-width, min-height, max-width, and max-height. These are not ignored.

Length units: percentages

Percentage values for flex-basis are relative to the size of the main dimension of the flex container.

We’ve already seen the first example in Figure 3-17. I am including it here to recall that the width of the text “flex-basis: auto” in this case, with my OS, browser, and installed fonts, is approximately 110 px wide. In this case only, declaring flex-basis: auto looks the same as writing flex-basis: 110px:

flex-container {
  width: 540px;
}
flex-item:last-child {
  flex: 0 1 100%;
}
The percentage value for flex-basis is relative to the width of the flex container
Figure 3-17. The percentage value for flex-basis is relative to the width of the flex container

In the second example in Figure 3-17, the first two have a flex basis of auto with a default width of auto, which is as if their flex basis were set to content. As we’ve noted previously, the flex-basis of the first 2 items ends up being the equivalent of 110 px as the content is 110 px wide.

The last item has its flex basis set to 100%. The percentage value is relative to the parent, which is 540 px. As the third item, with a basis of 100%, is not the only flex item within the non-wrapping flex container, it will not grow to be 100% of the width of the parent flex container unless its shrink factor is set with a null shrink factor (meaning it can’t shrink) or if it contains nonwrappable content that is as wide or wider than the parent container. This is not the case. Each flex item contains only wrappable content, and all three flex items are able to shrink as all have a default shrink factor of 1.

Note

Remember: when the flex basis is a percent value, the main-size is relative to the parent, which is the flex container.

If the content is indeed 110 px wide, and the container is 540 px wide (ignoring other box-model properties for simplicity’s sake), we have a total of 760 px to fit in a 540 px space in this second example. With three flex items with flex bases equivalent to 110 px, 110 px, and 540 px, respectively, we’re trying to fit 760 px of content into a 540 px-width container. We have 220 px of negative space to distribute proportionally. The shrink factor is:

Shrink factor = 220px / 760px = 28.95%

Each flex item will be shrunk by 28.95%, becoming 71.05% of the width they would have been had they not been allowed to shrink. We can figure the final widths:

item1 =  110px * 71.05% =  78.16px
item2 =  110px * 71.05% =  78.16px
item3 =  540px * 71.05% = 383.68px

item1 + item2 + item3 = 78.16px + 78.16px + 383.68px = 540px

These numbers hold true as long as the flex items can be that small: as long as none of the flex items contain media or nonbreaking text wider than 78.16 px or 383.68 px. This is the widest these flex items will be as long as the content can wrap to be that width or narrower. “Widest” because if one of the other two flex items can’t shrink to be as narrow as this value, they’ll have to absorb some of that negative space.

In our third example, the flex-basis: auto item wraps over three lines. The CSS for this example is the equivalent of:

flex-container {
  width: 540px;
}
item1 {
  flex: 0 1 70%;
}
item2 {
  flex: 0 1 auto;
}
item3 {
  flex: 0 1 80%;
}

We declared the flex-basis of the 3 flex items to be 70%, auto, and 80%, respectively. Remembering that “auto” is the width of the nonwrapping content, which in this case is approximately 110 px and our flex container is 540 px, the bases are the equivalent of:

item1 = 70% * 540px = 378px
item2 = widthOfText("flex-basis: auto") = 110px
item3 = 80% * 540px  =  432px

In this third example we have an item with a basis of 70%. This means the basis is 70% of the parent’s 540 px width, or 378 px. The second item is set to auto, which in this case means 110 px because of the width of the content. Lastly, we have flex item with a basis of 80%, meaning 80% of 540 px, or 432 px. When we add the widths of these 3 flex items, they have total combined width of 920 px, which needs to fit into a flex container 540 px wide. We have 380 px of negative space to remove proportionally among the 3 flex items. To figure out the ratio, we divide the available width of our flex container by the sum of widths of the flex items that they would have if they couldn’t shrink:

Proportional Width = 540px / 920px = 0.587

Because the shrink factors are all the same, this is fairly simple. Each item will be 58.7% of the width it would be if it had no flex item siblings:

item1 = 378px * 58.7% = 221.8px
item2 = 110px * 58.7% =  64.6px
item3 = 432px * 58.7% = 253.6px

What happens when the container is a different width? Say, 1,000 px? The flex basis would be 700 px (70% x 1,000 px), 110 px, and 800 px (80% x 1,000 px), respectively, for a total of 1,610 px:

Proportional Width = 1000px / 1610px = 0.6211


item1 = 700px * 62.11% = 434.8px
item2 = 110px * 62.11% =  68.3px
item3 = 800px * 62.11% = 496.9px

Because with a basis of 70% and 80%, the combined bases of the flex items will always be wider than 100%, no matter how wide we make the parent, all 3 items will always shrink.

If the first flex item couldn’t shrink, as shown in Figure 3-18, it would be 70% of the width of the parent—378 px in this case. The other 2 flex items will shrink proportionally to fit into the remaining 30%, or 162 px. In this case, you would expect widths to be 378 px, 32.875 px, and 129.125 px. As the text “basis:” is wider than that (at 42 px on my device) we get 378 px, 42 px, and 120 px.

While the percentage value for flex-basis is relative to the width of the flex container, the main-size is impacted by its siblings
Figure 3-18. While the percentage value for flex-basis is relative to the width of the flex container, the main-size is impacted by its siblings

Testing this out on your device will likely have slightly different results, as the width of the text “flex-basis: auto” may not be the same on your screen.

Zero Basis

If neither the flex-basis property nor the flex shorthand is included at all, the basis defaults to auto. When the flex property is included, but the basis component of the shorthand is omitted from the shorthand, the basis defaults to 0%. While on the surface you might think the two values of auto and 0 may seem similar, the 0 value is actually very different, and may not be what you expect. Once you understand it, you’ll realize it’s actually fairly intuitive.

The growth and shrink factors have completely different outcomes depending on whether the basis is set to 0 versus auto, as shown in Figure 3-19.

It is only the extra space that is distributed proportionally based on the flex growth factors. In the case of flex-basis: auto;, the basis is the main size of their content. If the basis of each of the flex items is 0, the “available” space is all the space, or main-size of the parent flex container. This “available” space is distributed proportionally based on the growth factors of each flex item. In the case of a basis of 0%, the size of the container is divided up and distributed proportionally to each flex item based on their growth factors—their default original main-size as defined by height, width, or content, is not taken into account, though min-width, max-width, min-height, and max-height do impact the flexed size.

flex-basis auto versus 0
Figure 3-19. flex-basis auto, versus 0

As shown in this example, when the basis is auto, it is just the extra space that is divided up proportionally and added to each flex item set to grow. Again, assuming the width of the text “flex: X X auto” is 110 px, in the first examples we have 210 px to distribute among 6 growth factors, or 35 px per growth factor. Our flex items are 180 px, 145 px, and 215 px wide, respectively.

In the second example, when the basis is 0, all 540 px of the width is distributable space. With 540 px of distributable space between 6 growth factors, each growth factor is worth 90 px. Our flex items are 180 px, 90 px, and 270 px wide, respectively. While our middle flex item is 90 px wide, the content in this example is narrower than the 110 px from our other examples, so the flex item didn’t wrap.

The flex Shorthand Property

Now that we have a fuller understanding of the properties that make up the flex shorthand, always use the flex shorthand. There are some commonly used shorthand values, including initial, auto, none, and the use of an integer, usually 1, meaning the flex item can grow. Let’s go over all these values.

Common flex Values

The common flex values are four flex values providing the most commonly desired effects:

flex: initial

This value sizes flex items based on the width/height properties, while allowing shrinking.

flex: auto

This flex value also sizes flex items based on the width/height properties, but makes them fully flexible, allowing both shrinking and growing.

flex: none

This value again sizes flex items based on the width/height properties, but makes them completely inflexible: they can’t shrink or grow.

flex: n

This value doesn’t care about the width/height values as the shrink factor is set to 0. In this case, the flex item’s size is be proportional to the flex factor n.

flex: initial

Initial is a global CSS keyword, which means initial can be used on all properties to represent the property’s initial value:

flex: initial;
flex: 0 1 auto;

These lines are the same: flex: initial is the equivalent of flex: 0 1 auto. This means the flex items’ size will be based on its own width and height properties, or based on the contents if the main-size isn’t explicitly set (set or defaulting to auto). If the flex container is not large enough for the flex items, the flex items can be shrunk, but the flex items will not grow even if there extra distributable space available.

Declaring flex: initial sets a null growth factor, a shrink factor of 1, and sets the flex bases to auto. In Figure 3-20, we can see the effect of the auto flex bases. In the first two examples, the basis of each flex item is content—with each flex item having the width of the single line of letters that make up their content. In the last 2 examples, the flex bases of all the items are equal at 50 px, since width: 50px has been applied to all the flex items. The flex: initial declaration sets the flex-basis to auto, which we previously learned means it is the value of the width (or height), if declared, or content if not declared.

With containers of different main sizes, the flex items shrink but won't grow when flex: initial is set on the flex items
Figure 3-20. With containers of different main sizes, the flex items shrink but won’t grow when flex: initial is set on the flex items

In the first and third examples in Figure 3-20, we see how, if the flex container is too small to fit all the flex items at their default main-size, the flex items will shrink, with all the flex items fitting within the parent flex container. In these examples, the combined flex bases of all the flex items is greater than the main-size of the flex container. In the first example, the amount by which each flex item shrinks are all different. They all shrink proportionally based on their shrink factor. In the third example, with each flex item’s flex-basis being equal at 50 px, all the items shrink equally.

In the first example, you’ll note the last flex item, with the single narrow capital letter I, is the narrowest flex item in the group, followed by A (They would have been the same had we used a monospaced font family). B and H are wider than A and I, even with the wrapping caused by the flex items shrinking, because their bases are based on three characters (two letters and a space) rather than one. The shrinking results in these flex items having only one letter per line of text, but they are still wider than the flex items that have a single character as their bases.

The flex items with more characters are wider because flex-basis is based on the width of the content. A and I are one letter wide. The basis for B and H are based on the width of two space-separated letters. Similarly, D and F are wider than C and G. In the first example, with flex: initial, E ends up being the widest as it has the most characters creating the widest content of all the bases.

In the second and fourth examples, the flex items all fit, so there is no shrinkage. When flex: initial is set, the growth factor is null, so the flex items can’t grow, and therefore don’t grow, to fill up their container.

Flex items, by default, are grouped at main start, as flex-start is the default value of for the justify-content property. This is only noticable when the combined main-size of the flex items on a flex line are smaller than the main-size of the flex container.

flex: auto

Setting flex: auto; on a flex item is the same as setting flex: 1 1 auto. The following two statements are equivalent:

flex: auto;
flex: 1 1 auto;

flex: auto is similar to flex: initial, but makes the flex items flexible in both directions: they’ll shrink if there isn’t enough room to fit all the items within the container, and they’ll grow to take up all the extra space within the container if there is distributable space. The flex items absorb any free space along the main-axis.

You’ll note the first and third examples of Figure 3-21 are identical to the examples in Figure 3-20, as the shrinking and bases are the same. However, the second and fourth examples are different, as when flex: auto is set, the growth factor is not null, and the flex items therefore grow incorporating all the extra available space.

With flex: auto set on the flex items, the flex items can grow and shrink
Figure 3-21. With flex: auto set on the flex items, they can grow and shrink

flex: none

Setting flex: none is equivalent to setting flex: 0 0 auto, making the following two lines of CSS equivalent:

flex: none;
flex: 0 0 auto;

The flex: none items are inflexible: the flex items will neither shrink nor grow.

As demonstrated in the first and third examples of Figure 3-22, if there isn’t enough space, the flex items overflow the flex container. This is different from flex: initial and flex: auto, which both set a positive shrink factor.

With flex: none, flex items will neither grow nor shrink
Figure 3-22. With flex: none, flex items will neither grow nor shrink

The basis resolves to auto, meaning each flex item’s main-size is determined by the main-size of the node had the element not been turned into a flex item: the flex-basis resolves to the width or height value. If that value resolved to auto, the basis would be the main-size of the content. In the first two examples, the basis—and the width, since there is no growing or shrinking—is the width of the content. In the third and fourth examples, the width and basis are all 50 px.

flex: n

When the values of the flex property is a single, positive numeric value, that value will be the growth factor, while the shrink factor will default to 0, and the basis will default to 0%:

flex-grow: n;
flex-shrink: 0;
flex-basis: 0%;

The following two CSS declarations are equivalent:

flex: 3;
flex: 3 0 0%;

Declaring flex: 3 is the same as declaring flex: 3 0 0%. This makes the flex item on which it is set flexible: it can grow. The shrink factor is actually moot, as the flex-basis was set to 0% and the flex item, even if a positive shrink factor were declared, cannot be less than 0 px wide or tall.

In the first two examples in Figure 3-23, all the flex items have a flex growth factor of 3. All the flex items in each example grew to be the same width. While in Figures 3-20, 3-21, and 3-22, the flex items shrank to fit the flex container parent, when you set flex: n, where n is any positive float, the basis is 0, so they didn’t “shrink”; they just grew equally from 0px wide until the sum of their main dimension grew to fill the container’s main dimension. With all the flex items having a basis of 0, 100% of the main dimension is distributable space. The main-size of the flex items are wider in this second example as the wider parent has more distributable space.

Any value for n that is greater than 0, even 0.1, means the flex item can grow. The n is the growth factor. When there is available space to grow, if only one flex item has a positive growth factor, that item will take up all the available space. If all the items can grow, the available extra space will be distributed proportionally to each flex item based on to their growth factor. In the case of all the flex items having flex: n declared, where n is a single or variety of positive numbers, the growth will be proportional based only on n, not on the underlying main size, as the basis for each flex item is 0.

In the last three examples of Figure 3-23, there are six flex items with flex: 0, flex: 1, flex: 2, flex: 3, flex: 4, and flex: 5 declared, respectively. These are the growth factors for the flex items, with each having a shrink factor of 0 and a basis of 0. The main-size of each is proportional to the specified flex growth factor.

With flex: n, you're declaring the flex items growth factor while setting the flex basis to zero
Figure 3-23. With flex: n, you’re declaring the flex items growth factor while setting the flex basis to zero

There are 15 total growth factors distributed across 6 flex items. The narrow flex container is 300 px wide, meaning each growth factor is worth 20 px. This means the widths of the flex items will be 0, 20 px, 40 px, 60 px, 80 px, and 100 px, for a total of 300 px. The last example has a width of 600 px, meaning each growth factor is worth 40 px. This leaves us with flex items that are 0, 40 px, 80 px, 120 px, 160 px, and 200 px, for a total of 600 px.

We added a bit of padding, margins, and borders on the example to make the visuals more pleasing. For this reason, the leftmost flex item, with flex: 0 declared, is visible: it has a 1 px border making it visible even though it’s 0 px wide.

If we had declared a width on these flex items, it would have made no difference. Setting flex: 0, flex: 5, or any other values for n in flex: n sets the flex-basis to 0%. You’ll see no difference between Figures 3-23 and 3-24, other than the “width: 50px” in the paragraph below each flex container.

With flex: n, the basis of the flex item is 0, not auto, so setting a width will not alter the appearance
Figure 3-24. With flex: n, the basis of the flex item is 0, not auto, so setting a width will not alter the appearance

Custom flex Values

flex: initial, flex: auto, flex: none, and flex: n are preset values. While these are provided as they are the most commonly used values, they may not meet all of your needs, and they don’t provide as much flexibility as defining your own custom flex values.

When flex-basis is set to auto, as shown in the first example in Figure 3-25, the main-size of each flex item is based on the content. Looking at the growth factor, you may have thought the middle item would be the narrowest as the growth factor is the smallest, but there is no “growing.” In this example there is no available distributable space. Rather, they’re all shrinking equally as they all have the same shrink factor and the basis of auto means the basis is the width of the content. In this case the flex items’ content are all of equal height, as the size of each is based on the flex basis, rather than the growth factor.

In the second example in Figure 3-25, the basis is 0%, so the main-size is determined by the various growth factors. In this case, the first flex item, with flex: 2 1 0% is twice as wide as the second flex item with flex: 1 1 0%. This second item, in turn, has a main-size that is one-third as wide as the last flex item with flex: 3 1 0%;.

flex-basis auto versus 0
Figure 3-25. flex-basis auto versus 0

We included a shrink factor in this example to make it parallel to the the first example, but it was completely not necessary. When using a 0 (or 0%) basis, the shrink factor has no impact on the main-size of the flex items. We could have included any of the three statements in each declaration:

item1 {
  flex: 2 1 0%;
  flex: 2 0 0%;
  flex: 2;
}
item2 {
  flex: 1 1 0%;
  flex: 1 0 0%;
  flex: 1;
}
item3 {
  flex: 3 1 0%;
  flex: 3 0 0%;
  flex: 3;
}

In these two examples, there was no width set on the flex items. By default, flex items won’t shrink below their minimum content size (the length of the longest word or fixed-size element). To change this, set the min-width or min-height property. For the examples in Figure 3-25, had min-width: 200px been set on the second flex item, in both cases, the width would have been 200 px.

How can this help in practice? In theory the similar height columns we get with auto seem like a good idea, but in reality controlling the widths of the columns in a multiple-column layout is likely a greater priority, as demonstrated by the difference in the two layouts in Figures 3-26 and 3-27.

A responsive three-column layout with just a few lines of code
Figure 3-26. A responsive three-column layout with just a few lines of code and flex: auto
Altering the proportion of a responsive layout by altering the flex value of the flex items
Figure 3-27. Altering the proportion of a responsive layout by altering the flex value of the flex items

The first example’s flex basis, Figure 3-26, is based on the content. For the navigation, the longest line, and therefore the basis, is the link with the longest content. If the article or aside contained a line break in the long and longer paragraphs, their widths would change.

The following CSS was used to create the second example:

@media screen and (min-width: 500px) {

    main {
      display: flex;
    }
    nav {
      order: -1;
      flex: 2;
      min-width: 150px;
    }
    article {
      flex: 5;
    }
    aside {
      flex: 2;
      min-width: 150px;
    }

}

In the second example, Figure 3-27, in viewports that are 500 px or wider, the nav and aside will always each be 22% of the width of the main area, unless they contain a component that is wider than 22%. The main article will be 56% of the width. You can include a min-width on any or all of the items, like we did on the navigation and aside, to ensure the layout never gets too narrow. You can use media queries to let the sections of the layout drop on very narrow screens. So many options!

We’ll cover this example again when we discuss the order property “The order property”. Quickly: in the markup the nav is last, and it will come last on a viewport that is less than 500 px wide. On wider screens that have room for the three columns, it will come first in appearance. Screen readers will still read it in source order (except in Firefox at the moment). Tabbing will still make it appear last.

The align-self Property

The align-self property is used to override the align-items property value on a per-flex-item basis.

With the align-items property set on the flex container, you can align all the flex items of that container to the start, end, or center of the cross-axis of their flex line. The align-self property, which is set directly on the flex item, enables you to override the aligns-items property on a per-flex-item basis.

You can override the alignment of any individual flex item with the align-self property, as shown in Figure 3-29. The default value of align-items is stretch, which is why all the flex items in the five examples in Figure 3-29 are all as tall as the parent, with the exception of the second flex item. All the flex items have the align-self’s default value of auto set, meaning they inherit the alignment from the container’s align-items property, except the second flex item in each example. Each “two” has a different align-self value set.

Just as with the values of the align-items property, the flex-start value places the item at the cross-start edge. flex-end places the item at the cross-end edge. center aligns the item in the middle of the cross axis, etc. In this example, auto, inherit, and stretch all stretch the flex items, as the align-items value was allowed to default to stretch.

To learn more about the flex-start, flex-end, center, baseline, and stretch values, see “The align-items Property”.

You can overwrite the alignment of any individual flex item with the align-self property; note the default value of align-items is stretch
Figure 3-29. You can overwrite the alignment of any individual flex item with the align-self property; note the default value of align-items is stretch

The order property

Flex items are, by default, displayed and laid out in the same order as they appear in the source code. The order of flex items and flex lines can be reversed with flex container property reverse values. The order property can be used to change the ordering of individual flex items.

The order property enables you to control the order in which flex items appear within the flex container by assigning them to ordinal groups. By default, all flex items are assigned the order of 0, with the flex items being displayed in the same order as the source order and the direction of that order based on the flex container properties (“Flex Container Properties”).

To change the visual order of a flex item, set the order property value to a nonzero integer. Setting the order property on elements that are not children of a flex container has no effect on that element: the property is basically ignored in that case.

The value of the order property specifies which ordinal group the flex item belongs to. Any flex items with a negative value will appear to come before those defaulting to 0 when drawn to the page, and all the flex items with a positive value will appear to come after those defaulting to 0. While visually altered, the source order remains the same. Screen readers and tabbing order remains as defined by the source order of the HTML.

For example, if you have a group of 12 items, and you want the 7th to come first and the 6th to be last, as shown in Figure 3-30, you would declare:

ul {
  display: inline-flex;
}
li:nth-of-type(6) {
  order: 1;
}
li:nth-of-type(7) {
  order: -1;
}
Setting order to any value other than 0 will reorder that flex item
Figure 3-30. Setting order to any value other than 0 will reorder that flex item

In this scenario, we are explicitly setting the order for the sixth and seventh list items, while the other list items are defaulting to order: 0.

As shown in Figure 3-30, the flex items are laid out from lowest order value to highest. The seventh item is the first in appearance due to the negative value of the order property—order: -1—which is less than the default zero, and the lowest value of any of its sibling flex items. The sixth item, the only item with a value greater than zero, and therefore having the highest order value out of all of its siblings, will visually appear last. All the other items, all having the default order of 0, will be drawn to the page between these first and last items, in the same order as their source order, since they are all members of the same ordinal group—0.

The flex container lays out its content in order-modified document order, starting from the lowest numbered ordinal group and going up. When you have multiple flex items having the same value for the order property, the items are in the same ordinal group. The flex items will appear in order by ordinal group, and the items in each ordinal group will appear in source order:

ul {
  display: inline-flex;
  background-color: rgba(0,0,0,0.1);
}
li:nth-of-type(3n-1) {
  order: 3;
  background-color: rgba(0,0,0,0.2);
}
li:nth-of-type(3n+1) {
  order: -1;
  background-color: rgba(0,0,0,0.4);
}

Setting the same order value to more than one flex item, the items will appear by ordinal group, and by source order within each individual ordinal group. In Figure 3-31, you’ll note that darkest items appear first, which have an order: -1 set. Within that ordinal group, the items appear in the order in which they appear in the source code. The middle group, the equivalent of li:nth-of-type(3n), has no order or background-color value set; therefore they default to order:0 and with a transparent background, the background color of the parent ul shows through. The last four items have all have order: 3 set, which is the highest value of any order set, greater than the default 0. This ordinal group appears last. Within the ordinal group, the elements are laid out in the order they appeared in the source code.

Flex items appear in order of ordinal groups, by source order within their group
Figure 3-31. Flex items appear in order of ordinal groups, by source order within their group

This reordering is purely visual. Screen readers should read the document as it appeared in the source code. As a visual change, ordering flex items impacts the painting order of the page: the painting order of the flex items is the order in which they appear, as if they were reordered in the source document, which they aren’t.

Changing the layout with the order property has no effect on the tab order of the page. If the numbers in Figure 3-31 were links, tabbing through the links would go through the links in the order of the source code, not in the order of the layout. While it might be intuitive that the link order in Figure 3-31 would be 1, 4, 7, 10, 3, 6, 9, 12, 2, 5, 8, and 11, tabbing through the links will actually take you in order from 1 through 12.

Tabbed Navigation Revisited

Adding to our tabbed navigation bar example in Figure 1-7, we can make the currently active tab appear first, as Figure 3-32 shows:

nav {
  display: flex;
  justify-content: flex-end;
  border-bottom: 1px solid #ddd;
}
a {
  margin: 0 5px;
  padding: 5px 15px;
  border-radius: 3px 3px 0 0;
  background-color: #ddd;
  text-decoration: none;
  color: black;
}
a:hover {
  background-color: #bbb;
  text-decoration: underline;
}
a.active {
  order: -1;
  background-color: #999;
}


<nav>
  <a href="/">Home</a>
  <a href="/about">About</a>
  >a class="active">Blog</a>
  <a href="/jobs">Careers</a>
  <a href="/contact">Contact Us</a>
</nav>
Changing the order will change the visual order, but not the tab order
Figure 3-32. Changing the order will change the visual order, but not the tab order

The currently active tab has the .active class added, the href attribute removed, and the order set to -1, which is less than the default 0 of the other sibling flex items, meaning it appears first.

Why did we remove the href attribute? As the tab is the currently active document, there is no reason for the document to link to itself. But, more importantly, if it was an active link instead of a placeholder link, and the user was using the keyboard to tab through the navigation, the order of appearance is Blog, Home, About, Careers, and Contact Us, with the Blog appearing first; but the tab order would have been Home, About, Blog, Careers, and Contact Us, following the source order rather than the visual order, which can be confusing.

The order property can be used to enable marking up the main content area before the side columns for mobile devices and those using screen readers and other assistive technology, while creating the appearance of the common three-column layout: a center main content area, with site navigation on the left and a sidebar on the right, as we demonstrated in our “Custom flex Values”.

While you can put your footer before your header in your markup, and use the order property to reorder the page, this is an inappropriate use of the property. The order should only be used for visual reordering of content. Your underlying markup should always reflect the logical order of your content:

<header></header>                         <header></header>
<main>                                    <main>
   <article></article>                      <nav></nav>
   <aside></aside>                          <article></article>
   <nav></nav>                              <aside></aside>
</main>                                   </main>
<footer></footer>                         <footer></footer>

We’ve been marking up websites in the order we want them to appear, as shown on the right in the preceding code example, which is the same code as in our three-column layout example (Figure 3-10). It really would make more sense if we marked up the page as shown on the left, with the article content, which is the main content, first in the source order: this puts the article first for screen readers, search engines, and even mobile device, but in the middle for our sighted users on larger screens:

main {
  display: flex;
}
main > nav {
  order: -1;
}

By using the order: -1 declaration we are able to make the nav appear first, as it is the lone flex item in the ordinal group of -1. The article and aside, with no order explicitly declared, default to order: 0.

Remember, when more than one flex item is in the same ordinal group, the members of that group are displayed in source order in the direction of main-start to main-end, so the article is displayed before the aside.

Some developers, when changing the order of at least one flex item, like to give all flex items an order value for better markup readability.

main {
  display: flex;
}
main > nav {
  order: 1;
}
main > article {
  order: 2;
}
main > aside {
  order: 3;
}

In previous years, before browsers supported flex, all this could have been done with floats: we would have set float: right on the nav. While doable, flex layout makes it much simpler, especially if we want all three columns—the aside, nav, and article—to be of equal heights.