Lesson 11 of 12

Bootstrap Flex and Alignment

Not every layout needs the grid. A row of buttons, a logo with a menu, an icon beside some text, a card with its button pushed to the bottom: these are one-dimensional layouts, and Flexbox is the right tool. Bootstrap flex utilities let you use Flexbox straight from your HTML. If you know CSS Flexbox, you will recognise every class; if not, this lesson teaches the essentials.

Turning on flex

Add d-flex to a parent to make it a flex container; its direct children become flex items and line up in a row. d-inline-flex does the same but lets the container sit inline with text. Like all display utilities, both work with breakpoints: d-md-flex turns flex on only from 768px.

The direction is a row by default. flex-column stacks items vertically, and flex-row-reverse or flex-column-reverse reverse the order. A very common responsive pattern is flex-column flex-md-row: stacked on phones, side by side from tablets up.

Justify and align

Two families of Bootstrap flex classes do most of the work. justify-content-* spaces items along the main axis (horizontally in a row). align-items-* aligns them on the cross axis (vertically in a row). In a column, the two swap directions, which is the most common source of confusion with Flexbox.

Class familyValuesIn a row, it controls
justify-content-*start, end, center, between, around, evenlyHorizontal spacing
align-items-*start, end, center, baseline, stretchVertical alignment of all items
align-self-*Same as align-itemsVertical alignment of one item
align-content-*start, center, between…Spacing between wrapped lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Justify and align in action</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>
<body>
<div class="container py-4">
  <p class="mb-1 fw-semibold">justify-content-between</p>
  <div class="d-flex justify-content-between p-2 mb-3 bg-body-tertiary border rounded">
    <span class="p-2 border bg-body">Idli</span><span class="p-2 border bg-body">Dosa</span><span class="p-2 border bg-body">Vada</span>
  </div>

  <p class="mb-1 fw-semibold">justify-content-center</p>
  <div class="d-flex justify-content-center gap-2 p-2 mb-3 bg-body-tertiary border rounded">
    <span class="p-2 border bg-body">Idli</span><span class="p-2 border bg-body">Dosa</span><span class="p-2 border bg-body">Vada</span>
  </div>

  <p class="mb-1 fw-semibold">align-items-center (box is 100px tall)</p>
  <div class="d-flex align-items-center gap-2 p-2 mb-3 bg-body-tertiary border rounded" style="height: 100px;">
    <span class="p-2 border bg-body">Short</span>
    <span class="p-3 border bg-body">Taller item</span>
    <span class="p-2 border bg-body align-self-end">align-self-end</span>
  </div>

  <p class="mb-1 fw-semibold">Centred in both directions</p>
  <div class="d-flex justify-content-center align-items-center bg-primary-subtle border rounded" style="height: 120px;">
    <span class="fw-bold">Perfectly centred</span>
  </div>
</div>
</body>
</html>

Grow, shrink, wrap and order

  • flex-fill makes items share the space according to their content; flex-grow-1 lets one item take all the leftover space, such as a search input next to a button.
  • flex-shrink-0 stops an item from shrinking, which is useful for icons and avatars that must keep their size.
  • flex-wrap lets items move onto new lines when there is no room. The default, flex-nowrap, squeezes them into one line.
  • order-first, order-last and order-0 to order-5 change the visual order, also with breakpoints like order-md-last.

One more trick: an auto margin absorbs free space. Put ms-auto on an item in a row and it, with everything after it, is pushed to the far end. This is how a navbar puts some links on the left and a “Log in” button on the right. In a column, mt-auto pushes an item to the bottom.

gap, hstack and vstack

Use gap-* (sizes 0 to 5) on the flex container to space items evenly, instead of a margin on each child. row-gap-* and column-gap-* set the two directions separately. Bootstrap also has two shortcut helpers: hstack is a horizontal flex row with centred items, and vstack is a vertical stack. Combine them with gap-*, and add a vr element for a thin vertical divider.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Toolbar, media object and stacks</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>
<body>
<div class="container py-4">
  <div class="hstack gap-2 p-2 mb-4 border rounded">
    <button type="button" class="btn btn-sm btn-outline-secondary">Bold</button>
    <button type="button" class="btn btn-sm btn-outline-secondary">Italic</button>
    <div class="vr"></div>
    <button type="button" class="btn btn-sm btn-outline-secondary">Link</button>
    <button type="button" class="btn btn-sm btn-primary ms-auto">Publish</button>
  </div>

  <div class="d-flex gap-3 mb-4" style="max-width: 520px;">
    <div class="flex-shrink-0 rounded-circle text-bg-success d-flex align-items-center justify-content-center fw-bold" style="width: 48px; height: 48px;">MR</div>
    <div class="flex-grow-1">
      <h2 class="h6 mb-1">Meena Rajan</h2>
      <p class="mb-0">The new checkout flow tested well with users in Salem and Erode. Shall we release it to everyone on Monday?</p>
    </div>
  </div>

  <div class="vstack gap-2 col-md-5">
    <button type="button" class="btn btn-success">Pay with UPI</button>
    <button type="button" class="btn btn-outline-secondary">Pay with card</button>
    <button type="button" class="btn btn-link">Cash on delivery</button>
  </div>
</div>
</body>
</html>

The toolbar shows ms-auto pushing Publish to the right edge. The second block is the classic “media object”: the avatar keeps its size with flex-shrink-0 while the text takes the rest with flex-grow-1. The vstack with col-md-5 gives full-width stacked buttons on phones and a narrower stack from 768px.

A responsive Bootstrap flex layout

Combining a responsive direction with alignment gives you simple responsive components without the grid. The next example stacks on phones and becomes a row from 768px, with the button aligned to the right.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Stack on phones, row on wider screens</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>
<body>
<div class="container py-4">
  <div class="d-flex flex-column flex-md-row align-items-md-center gap-3 p-3 border rounded-3 bg-body-tertiary">
    <div class="flex-grow-1">
      <h2 class="h5 mb-1">Learn UI design in Tamil and English</h2>
      <p class="mb-0 text-body-secondary">Free weekend sessions in Puducherry for beginners.</p>
    </div>
    <button type="button" class="btn btn-primary flex-shrink-0">Reserve a seat</button>
  </div>
</div>
</body>
</html>

Tip: The Bootstrap grid is built on Flexbox too: a row is a flex container with wrapping. Use the grid when you need columns that line up across rows, and Bootstrap flex utilities for the inside of components. The post Flexbox vs Grid explains the difference between the two CSS layout systems.

Watch out: Reversing or reordering with flex-row-reverse or order-* changes only what people see. Keyboard focus and screen readers still follow the HTML order. Keep the source order logical and use reordering only for small visual tweaks.

Further reading

Key takeaways

  • d-flex makes a flex container; add flex-column to stack, and use breakpoints like flex-md-row.
  • justify-content-* works on the main axis and align-items-* on the cross axis.
  • flex-grow-1, flex-shrink-0, flex-wrap and order-* control sizing, wrapping and order.
  • An auto margin such as ms-auto pushes an item to the far end.
  • gap-*, hstack, vstack and vr make quick, evenly spaced layouts.

Quick quiz

Check what you learned – pick an answer.

1. In a d-flex flex-column container, which class centres items horizontally?

2. How do you push the last button in a flex row to the right edge?

3. What does hstack gap-3 create?

Practice exercise

Build a site header with flex utilities only: a brand name on the left and, on the right, a search input that grows to fill space and a "Log in" button. On phones, the brand should sit above the search row; from 768px, everything should be on one line and vertically centred.

Show a hint

Use d-flex flex-column flex-md-row align-items-md-center gap-3 on the header, and an inner d-flex gap-2 flex-grow-1 with flex-grow-1 on the input.

Show the solution
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Flex header</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>
<body>
<header class="d-flex flex-column flex-md-row align-items-md-center gap-3 p-3 border-bottom">
  <a href="#" class="fs-4 fw-bold text-decoration-none">Thoothukudi Books</a>
  <div class="d-flex gap-2 flex-grow-1">
    <input type="search" class="form-control flex-grow-1" placeholder="Search books" aria-label="Search books">
    <button type="button" class="btn btn-outline-primary flex-shrink-0">Log in</button>
  </div>
</header>
<main class="p-3">
  <p>Resize the preview to see the header change.</p>
</main>
</body>
</html>

Progress is saved in this browser only.