CSS Flexbox

April 14, 2026
#css #web-development #flexbox #layout #responsive

Before Flexbox, centering something on a web page was surprisingly hard. Vertical centering? A nightmare. Equal-height columns? Hacks on top of hacks. Flexbox changed all of that. It’s a one-dimensional layout system that makes it straightforward to distribute space, align items, and build responsive layouts.

If you’ve been through the CSS Box Model tutorial, you understand how individual elements take up space. Flexbox is about how you arrange multiple elements together.

The Basics: Container and Items

Flexbox works on two levels: the flex container (the parent) and the flex items (the children). You activate it by setting display: flex on the parent.

<div class="container">
    <div class="item">A</div>
    <div class="item">B</div>
    <div class="item">C</div>
</div>
.container {
    display: flex;
}

.item {
    padding: 20px;
    background: #3388cc;
    color: white;
    margin: 4px;
}

Without flexbox, those divs would stack vertically (they’re block elements). With display: flex, they sit side by side in a row. That’s the default behavior — items flow along the main axis, which is horizontal by default.

flex-direction

flex-direction controls which way items flow:

.container { flex-direction: row; }            /* default — left to right */
.container { flex-direction: row-reverse; }     /* right to left */
.container { flex-direction: column; }          /* top to bottom */
.container { flex-direction: column-reverse; }  /* bottom to top */

When you change the direction to column, the main axis becomes vertical and the cross axis becomes horizontal. This matters for all the alignment properties below.

Alignment

Flexbox has two axes. The main axis follows the flex direction. The cross axis is perpendicular to it. Different properties control alignment on each axis.

justify-content (Main Axis)

justify-content distributes items along the main axis:

.container { justify-content: flex-start; }    /* default — items at the start */
.container { justify-content: flex-end; }      /* items at the end */
.container { justify-content: center; }        /* items centered */
.container { justify-content: space-between; } /* equal space between items */
.container { justify-content: space-around; }  /* equal space around items */
.container { justify-content: space-evenly; }  /* truly equal gaps everywhere */

align-items (Cross Axis)

align-items aligns items along the cross axis:

.container { align-items: stretch; }     /* default — items stretch to fill */
.container { align-items: flex-start; }  /* items at the top */
.container { align-items: flex-end; }    /* items at the bottom */
.container { align-items: center; }      /* items vertically centered */
.container { align-items: baseline; }    /* items aligned by text baseline */

Centering (The Classic Problem, Solved)

Centering an element both horizontally and vertically used to require hacks. With flexbox, it’s two lines:

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

That’s it. The child is perfectly centered.

gap

The gap property adds space between flex items without needing margins. It’s cleaner because it only adds space between items, not on the outer edges:

.container {
    display: flex;
    gap: 16px;
}

You can set different horizontal and vertical gaps:

.container {
    display: flex;
    flex-wrap: wrap;
    gap: 16px 24px; /* row-gap | column-gap */
}

flex-wrap

By default, flex items try to fit on one line, even if it means shrinking. flex-wrap lets them wrap to the next line:

.container {
    display: flex;
    flex-wrap: nowrap; /* default — single line */
}

.container {
    display: flex;
    flex-wrap: wrap; /* items wrap to new lines */
}

When items wrap, align-content controls how the lines are distributed (similar to justify-content but for the cross axis):

.container {
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;   /* lines packed at the top */
    align-content: center;       /* lines centered */
    align-content: space-between; /* equal space between lines */
}

Flex Item Properties

So far we’ve styled the container. These properties go on individual items.

flex-grow

flex-grow controls how much an item expands to fill available space. The default is 0 (don’t grow).

.item-a { flex-grow: 1; } /* takes 1 share of extra space */
.item-b { flex-grow: 2; } /* takes 2 shares of extra space */

If the container has 300px of extra space, item A gets 100px and item B gets 200px.

flex-shrink

flex-shrink controls how much an item shrinks when there isn’t enough space. The default is 1 (shrink equally).

.item { flex-shrink: 0; } /* don't shrink — maintain size */

flex-basis

flex-basis sets the initial size of an item before growing or shrinking. It works like width in a row layout or height in a column layout:

.item { flex-basis: 200px; }

The flex Shorthand

The flex shorthand combines all three:

.item { flex: 1; }           /* grow: 1, shrink: 1, basis: 0 */
.item { flex: 0 0 200px; }   /* don't grow, don't shrink, start at 200px */
.item { flex: 2 1 150px; }   /* grow: 2, shrink: 1, basis: 150px */

align-self

align-self overrides the container’s align-items for a single item:

.container { align-items: flex-start; }
.special { align-self: flex-end; } /* this one goes to the bottom */

Practical Example: Navigation Bar

A responsive nav bar is one of the most common flexbox use cases:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Flexbox Nav</title>
    <style>
        * { box-sizing: border-box; margin: 0; padding: 0; }

        .navbar {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 12px 24px;
            background: #2c3e50;
            color: white;
        }

        .navbar .logo {
            font-size: 1.25rem;
            font-weight: bold;
        }

        .nav-links {
            display: flex;
            gap: 20px;
            list-style: none;
        }

        .nav-links a {
            color: white;
            text-decoration: none;
        }

        .nav-links a:hover {
            text-decoration: underline;
        }
    </style>
</head>
<body>
    <nav class="navbar">
        <div class="logo">MySite</div>
        <ul class="nav-links">
            <li><a href="#">Home</a></li>
            <li><a href="#">About</a></li>
            <li><a href="#">Contact</a></li>
        </ul>
    </nav>
</body>
</html>

space-between pushes the logo to the left and the links to the right. align-items: center vertically centers everything. The inner ul is also a flex container with gap for spacing between links.

Practical Example: Card Grid

Flexbox with flex-wrap creates a responsive card grid:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Card Grid</title>
    <style>
        * { box-sizing: border-box; margin: 0; padding: 0; }

        body {
            font-family: system-ui, sans-serif;
            padding: 24px;
            background: #f5f5f5;
        }

        .grid {
            display: flex;
            flex-wrap: wrap;
            gap: 16px;
        }

        .card {
            flex: 1 1 280px;
            background: white;
            border: 1px solid #ddd;
            border-radius: 8px;
            padding: 24px;
        }

        .card h3 { margin-bottom: 8px; }
        .card p { color: #666; line-height: 1.5; }
    </style>
</head>
<body>
    <div class="grid">
        <div class="card">
            <h3>Card One</h3>
            <p>Flexbox makes this grid responsive without media queries.</p>
        </div>
        <div class="card">
            <h3>Card Two</h3>
            <p>Each card grows to fill space but won't shrink below 280px.</p>
        </div>
        <div class="card">
            <h3>Card Three</h3>
            <p>When the viewport is too narrow, cards wrap to the next row.</p>
        </div>
    </div>
</body>
</html>

The key is flex: 1 1 280px — each card starts at 280px, grows to fill available space, and wraps when the row gets too tight. No media queries needed for basic responsiveness.

When to Use Flexbox vs Grid

Flexbox is one-dimensional — it works along a single axis (row or column). CSS Grid is two-dimensional — it controls rows and columns simultaneously.

Use flexbox for:

  • Navigation bars
  • Centering content
  • Distributing items in a single row or column
  • Components where items have varying sizes

Use grid for:

  • Full page layouts
  • Card grids where you need precise row/column control
  • Any layout that’s fundamentally two-dimensional

In practice, you’ll use both — often in the same page. Flexbox for components, grid for the overall layout.

What’s Next

You now have the tools to build most common layouts with flexbox. The next step is learning CSS Grid for two-dimensional layouts, or exploring CSS Positioning for overlapping elements and fixed headers.

Thanks for visiting
We are actively updating content to this site. Thanks for visiting! Please bookmark this page and visit again soon.
Sponsor