Flexbox

Introduction

The CSS Flexible Box Layout, or Flexbox, is a powerful layout system designed to help web developers create complex layouts with ease. Flexbox provides a more efficient way to align and distribute space among items within a container, even when their sizes are unknown or dynamic.

The Flexbox layout model is based on the idea of distributing space along a main axis and a cross axis within a container. It offers a much more dynamic and flexible approach compared to traditional layout techniques like using floats or positioning. Flexbox allows elements to adjust their sizes and positions according to the available space in a container, making it ideal for building complex layouts that adapt to different screen sizes.

To use Flexbox, you need to define a flex container, which is the parent element, and the flex items, which are its child elements. The key to Flexbox's power lies in how the container and its items interact with each other, adjusting according to the container's dimensions and the defined properties.

Flexbox Display

The first step in creating a Flexbox layout is applying the display: flex; declaration to a container. This makes the container a flex container, and all its direct child elements automatically become flex items. Once you have a flex container, you can use various properties to manipulate the layout of the flex items.

.container {
    display: flex;
}

Alternatively, you can use display: inline-flex;, which makes the container behave like an inline element while still having the properties of a flex container. This means that the flex container will behave like an inline element and sit in the document flow next to other inline elements, but its children will be flex items.

.container {
    display: inline-flex;
}

Main Concepts

Flexbox relies on two axes to position elements: the main axis and the cross axis. By default, the main axis is horizontal (left to right), and the cross axis is vertical (top to bottom). However, these axes can be switched using the flex-direction property, though I have not personally encountered a situation in which this is required.

The justify-content property controls the alignment of the flex items along the main axis (left to right by default). It helps distribute the available space between or around the items.

  • flex-start aligns items at the start of the container (default behaviour).
  • flex-end aligns items at the end of the container.
  • center aligns items in the centre of the container.
  • space-around distributes space evenly before and after each item, with equal space on both sides.
  • space-between distributes space between the items, but there is no space before the first item or after the last item.
.container {
    display: flex;
    justify-content: center;
}

The align-items property controls the alignment of the flex items along the cross axis (vertical axis, by default). It determines how items are positioned vertically inside the container.

  • flex-start aligns items to the top of the container.
  • flex-end aligns items to the bottom of the container.
  • center aligns items vertically in the centre of the container.
  • baseline aligns items based on their baseline (the bottom of their content).
  • stretch stretches the flex items to fill the container vertically (default behaviour).
.container {
    display: flex;
    align-items: center;
}

The flex-direction property defines the direction of the main axis, determining whether the flex items are arranged horizontally or vertically. By default, Flexbox arranges items in a row (left to right).

  • row items are arranged horizontally from left to right. This is the default value.
  • row-reverse items are arranged horizontally from right to left.
  • column items are arranged vertically from top to bottom.
  • column-reverse items are arranged vertically from bottom to top.
.container {
    display: flex;
    flex-direction: column;
}

In this case, flex-direction: column; arranges the flex items vertically within the container.

Grow, Shrink, and Basis

Flexbox provides three important properties for controlling how flex items grow or shrink to fit the container; flex-grow, flex-shrink, and flex-basis.

The flex-grow property specifies how much a flex item should grow relative to the other items in the container. The value is a unitless number that acts as a proportion, with a higher number indicating more growth. If all items have a flex-grow of 1, they will share the available space equally.

.item {
    flex-grow: 1;
}

The flex-shrink property specifies how much a flex item should shrink when there is not enough space in the container. Like flex-grow, the value is a unitless number, with a higher number indicating more shrinkage.

.item {
    flex-shrink: 1;
}

The flex-basis property defines the initial size of a flex item before any growing or shrinking occurs. It can be set to a specific length (such as px, %, em, etc.) or auto (which means the item's size is based on its content).

.item {
    flex-basis: 200px;
}

You can combine flex-grow, flex-shrink, and flex-basis into a single shorthand property called flex. The shorthand allows you to specify the three properties in one line.

This means the item will grow at a rate of 1, will not shrink (0), and will start with a width of 200px.

Flex-wrap

The flex-wrap property controls whether flex items should wrap onto multiple lines when they exceed the container's width (or height, depending on the flex direction). By default, flex items will try to fit into one line.

  • wrap items will wrap onto the next line if they don't fit in the container.
  • nowrap items will stay on a single line, even if they overflow. This is the default.
  • wrap-reverse items will wrap onto the next line in reverse order.
.container {
    display: flex;
    flex-wrap: wrap;
}

Align Content

The align-content property is used when there are multiple rows of flex items in the container. It controls how the rows are aligned along the cross axis.

  • flex-start aligns the rows at the top of the container.
  • flex-end aligns the rows at the bottom of the container.
  • center centres the rows within the container.
  • space-between distributes space evenly between rows, but not at the top or bottom.
  • space-around distributes space evenly around rows.
  • stretch stretches the rows to fill the container.
.container {
    display: flex;
    flex-wrap: wrap;
    align-content: center;
}

Flex-flow

The flex-flow property is a shorthand for flex-direction and flex-wrap. It allows you to set both properties in one line, making it easier to control both the direction and wrapping behavior of the flex container.

.container {
    display: flex;
    flex-flow: row wrap;
}

In this example, flex-flow: row wrap; sets the flex direction to row (horizontal) and enables wrapping for the flex items.

Advanced Flexbox Layouts

Flexbox is particularly useful for creating complex layouts that need to be responsive. For example, you can create equal-width columns that adapt to different screen sizes by using flex-grow, flex-shrink, and flex-basis.

Equal Width Columns

To create three equal-width columns, you can apply flex-grow to the items:

.container {
    display: flex;
}
.item {
    flex-grow: 1;
}

Each item will take up an equal amount of space in the container, and they will automatically adjust their size if the container is resized.

Centring Items

You can easily centre items both vertically and horizontally using Flexbox. To centre an item within a container, you can use justify-content: center; (for horizontal centring) and align-items: center; (for vertical centring).

.container {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
}

This will centre the flex items both horizontally and vertically within the container.

Footer

In order to achieve a footer that stays at the bottom of the page:

The body is set to a flex container with a column layout and the min-height: 100vh; ensures the page is at least the full height of the viewport. The main { flex: 1 0 auto; } makes the main content expand and take up any available space and flex: 1 0 auto; means:

  • 1: It grows to fill available space.
  • 0: It doesn't shrink.
  • auto: The default basis (size) is determined by its content.

Because main expands to fill the space, it pushes the footer down when there's not enough content and if there's enough content, the footer naturally moves further down.