Home/Blog/Web Development/Understanding CSS Flexbox
Home/Blog/Web Development/Understanding CSS Flexbox

Understanding CSS Flexbox

Marketing @ Educative
Sep 10, 2024
10 min read

CSS has helped developers create many different kinds of web page layouts. One challenge web developers often face is positioning different content parts on a web page. Flexbox makes this task easy and predictable across different screen sizes.

Cover
Understanding Flexbox: Everything you need to know

This course will cover all the fundamental and advanced concepts you need to get good with the CSS Flexbox model. You will learn to layout a Responsive Music App in the process. It is a detailed course, and I hope you’re ready for it.

4hrs
Beginner
54 Playgrounds
18 Illustrations

Today we'll introduce some basics of Flexbox to help you get started with it.

Switching from default to Flexbox#

Imagine creating a web page with three distinct sections in it. You might have the following code:

  • HTML
  • CSS
html
css
A starter template for our page layout

We define a top-level div element and nest three div elements inside it.

Why do each of the three div elements appear on separate "lines"? This is because they're block elements, and the default CSS layout mode is in effect: namely, flow mode.

Flow mode is useful for documents, which is what the world wide web was originally for. Words are displayed next to each other in a line, from left to right (for the English language), then begin to wrap around on the next line when there’s no more space on the current line. Block-level elements (like p and div) on the other hand, are put on separate lines. The three children div elements, being block elements, occupy the width of their parent div element and are stacked on top of each other in separate rows.

Switching to the Flexbox layout mode provides lots of flexibility in element layouts. Central to a Flexbox-based layout is an HTML element that serves as the Flexbox container. This element contains one (usually two) or more other elements that are termed children. The idea is to control the positioning of the children within the container. We declare an HTML element as a Flexbox container by specifying display: flex; in its style. We then set some Flexbox properties to help us achieve the desired layout.

In the above coding playground, uncomment line 26 in the CSS file and see what happens. We configure the top-level div element as a Flexbox container (line 26 in CSS) and nest three div elements inside it. This change enables the Flexbox layout mode, which, by default, lays out the children one after the other at the start of a row.

The following illustration shows how the parent-child DOM element relationship (CSS not shown for simplicity) translates to the Flex container layout.

The container-child relationship
The container-child relationship

Changing children orientation#

CSS Flexbox layout mode has a main axis and a cross axis. The children are distributed within the container element along the main axis. By default, the main axis is horizontal, which is why children are laid out horizontally from left to right. To change the children’s orientation within the container, we need to switch the main and cross axes. We do this with the flex-direction property on the container element. The default value is row, but we can change it to row-reverse, column, or column-reverse. To see the effect, try changing that property using the “Row”, “Row Reverse”, “Column” and “Column Reverse” buttons in the following playground. Clicking these buttons sets the flex-direction property on the container element to the appropriate value. You can use the checkbox at the bottom of the playground to indicate the main axis.

Switching the main and cross axes

For the rest of the blog, we use only Row and Column as the available options, in the interest of simplicity and brevity.

Q

We have the following markup:

<nav class="navigation">
    <ul class="menu">
        <li>Home</li>
        <li>About</li>
        <li>Contact</li>
    </ul>
</nav>

The class named container is a Flex container. We want the list items to be arranged from left to right. Which CSS selector achieves this?

A)

.navigation { flex-direction: column; }

B)

.navigation { flex-direction: row; }

C)

.navigation { flex-direction: row-reverse; }

D)

.navigation { flex-direction: column-reverse; }

Distribution along the main axis#

To control the distribution of children along the main axis, use the justify-content property on the container element. The following coding playground shows all the possible values for this property. See what each value for this property achieves.

The justify-content property
1

We are designing a navigation bar where we want the menu items to be evenly distributed across the container. Which value do we set for the justify-content property?

A)

flex-start

B)

flex-end

C)

center

D)

space-between

Question 1 of 30 attempted

Alignment along the cross axis#

If different children have different dimensions, for example, div elements with different amounts of text, shouldn’t there be options to control where the children are positioned along the cross axis? That’s where the align-items property comes in. It is applied to the container element, but applies the alignment to all the direct children. Try playing with this property’s values in the following playground where each child element has a different dimension.

The align-items property

There are other possible values for the align-items property. Please see the Mozilla documentation for details.

There’s also the align-self property that has the same set of available values as the align-items property. It can be applied to a child element to override the setting of the align-items property set on the container element. Use this when you want to align one (or a few) children differently from the other children. In the following playground, the “Home” and “About” children are positioned through the align-items property on the flex container, whereas the “Products” element is positioned using align-self.

The align-self property
1

Suppose you’re working on a layout with a sidebar containing multiple sections. You want the “news” section to be aligned at the bottom of the sidebar while the others remain aligned at the top. Which property would you apply to the “news” section?

A)

justify-contents

B)

align-items

C)

align-self

D)

justify-self

Question 1 of 20 attempted

Items vs. content#

The properties that we’ve just seen aren’t arbitrarily named. Think of content as the term used for whatever group of elements we have along the main axis. On the other hand, think of items as the term for whatever element(s) we have along the cross axis. Furthermore, the term justify deals with the placement along the main axis, whereas align deals with the placement along the cross axis. All of the Flexbox children are cut across by the main axis, but each child has its own separate cross axis. That’s why the justify-content property value gets applied to the group of children together, while the align-items property applies individually to each child. For instance, if align-items is set to center, each child is centered on the cross axis according to its own dimensions.

Wrapping#

Flex flow mode tries to fit all child elements into a single row inside the flex container. It will shrink the children if needed and if possible. However, sometimes we want the remaining child elements to wrap over to the next row. In such cases, we can set the flex-wrap property to wrap on the container element. The default value for this property is nowrap. Another possible value is wrap-reverse. Let's see this property in action.

In the following playground, we have a flex container of 400 pixels by 400 pixels. The “Home” and “Products” elements are 150 pixels by 150 pixels. With the flex-wrap property set to nowrap and flex-direction set to column, the Flex layout mode fits the three elements in the same column. It turns out the absolute height (or width) specified for children are suggestions and not hard constraints for the Flex layout mode. When you set the flex-wrap property to wrap, you see wrapping in action. With flex-wrap set to wrap-reverse, the placement and wrapping is done in a direction opposite to the usual direction of the main axis.

The flex-wrap property

Gap property#

We usually control the space between elements using the margin-* properties. Imagine the links in a horizontal navigation bar. We might want the first and the last links to be left-aligned and right-aligned, respectively, with an equal space between elements everywhere else. For something like this without Flexbox, we have to resort to some fancy selectors. Flexbox provides an easy way to achieve this spacing using the gap, row-gap, and column-gap properties on the container element.

In the following playground, we gave the flex container element and the children fixed dimensions. Choose the property you want to modify and change its value using the slider to see the effect.

The gap properties

Children sizing#

Let's say we are creating a horizontal navigation bar. We might start with the following.

A horizontal navigation bar using Flexbox

With just the short CSS above, we apply a few flex properties to each of the children and get their default values, resulting in a reasonable display. Let's discuss these properties.

Note that these properties can be assigned individually to each child.

flex-basis#

We can size HTML elements using the width and height properties (among others). But what if you wanted to set the dimension of a child element along the main axis? Do you set the width or the height? The answer depends on the value of the flex-direction property, right? Flexbox provides a property named flex-basis which refers to the dimension of a particular child along the main axis.

Let's say we have a three-column layout of a page: a vertical navigation bar on the left, main content in the center, and some useful links to the right. We set the flex-basis property on the left and right columns to 10% each. You can vary the flex-basis property for the main content column using the slider. Notice how flex-basis is also a suggested starting size of the child elements and not a hard constraint. Flexbox distributes the available space among the children reasonably.

A demonstration of the flex-basis property

flex-grow#

Flexbox distributes space available in the container element among the children, the space between them, and the space around them. The flex-grow property, set on the child elements, represents whether the child should grow to accept space distributed by Flex layout or not. The default value for this property is 0, i.e., do not grow. This isn't a 0/1-valued property. You can set it to any non-negative number. Flexbox distributes the total space available in the container among the children in the proportion of values of their flex-grow properties. Let’s look at an example to explain that.

If we want to size some children equally and some other(s) proportionately bigger, we can set flex-grow to 1 on the former set of elements, and set it to 2, or 3, or whatever fraction we desire on the latter set of elements. In the following playground, we have a website with a horizontal navigation bar on top and a two-column layout in the main section. The main content is to the left, and there’s a “What’s new!” section on the right. We set the flex-grow property to 1 on both the main content and the “What’s new!” section. That’s why they are sized almost equally. But you can use the slider to change the value of the flex-grow property on the main content to see the effect.

Demonstration of the flex-grow property

flex-shrink#

Another thing that Flexbox does is that it causes children to shrink compared to their assigned width or height property. This is the effect of the flex-shrink property, set on the child elements, with the default value being 1, i.e., do shrink.

In the following playground, we've given each button a width of 1000 pixels, which can clearly not be accommodated in the flex container. Yet, we don't see a horizontal scroll bar. The reason is the default value of the flex-shrink property. This is because Flexbox shrinks all the children until they have equal width. That’s why, despite the justify-content property set to space-between, the “Contact Us” button is not flush with the right edge, unlike the previous playground.

A demonstration of the flex-shrink property
1

We are developing a dashboard with resizable widgets. We want each widget to shrink when the available space decreases, but we want to prevent one specific widget from shrinking beyond a certain point. Which value should we assign to the flex-shrink property for that specific widget?

A)

0

B)

1

C)

2

D)

auto

Question 1 of 50 attempted

flex#

This is a shorthand property to set flex-grow, flex-shrink, and flex-basis all in one line. This property is also set on a child element. We may skip the last two values when configuring this property. In this case, flex-basis is implicitly set to 0. We may skip the value for the flex-shrink property by setting this property to two values, with the second value being a length value such as 10px rather than just a number. Skipping the value for flex-basis is straightforward.

Doing more with Flexbox#

We hope that this blog helped you learn a thing or two about CSS Flexbox!

To refresh your memory, here's a table summarizing the properties that we discussed today.

Property

Set on

Purpose

display: flex;

Container

Indicates that the children of this element should be placed according to the Flex layout mode.

flex-direction

Container

The orientation of the main axis. The default value is row, i.e., the children are laid out horizontally in a row. Can be set to column to lay out the children vertically in a column.

justify-content

Container

Configures the distribution of children along the main axis.

align-items

Container

Configures the distribution of children along the cross axis.

align-self

Child

Configures the placement of a particular child element on the cross axis.

flex-wrap

Container

Configures whether items should wrap over to the next row (or column) if they can’t all fit in the current one.

row-gap

Container

Configures the gap between two consecutive rows. This property can have any length unit.

column-gap

Container

Configures the gap between two consecutive columns. This property can have any length unit.

gap

Container

Configures the gap between two consecutive rows and consecutive columns. This property can have any length unit.

flex-basis

Child

Configures the starting minimum size of a child element along the main axis before the Flex layout distributes container space among the children.

flex-grow

Child

Configures the behavior of a child element in case Flex layout has to grow the children to occupy the available container space. Space is distributed among the children in proportion of the value of this property.

flex-shrink

Child

Configures the behavior of a child element in case Flex layout has to shrink the children to fit within the available container space. The children shrink in proportion of the value of this property.

You can continue getting hands-on with Flexbox in some of our courses below:


  

Free Resources