Layouts: Flexbox Basics

Layouts: Flexbox Basics

Flexbox is a one-dimensional layout system. It arranges items along one primary direction: a row or a column.

Use Flexbox when you need to:

  • align items in a row,
  • center content,
  • distribute remaining space,
  • build navigation bars,
  • create toolbars,
  • stack content responsively,
  • or control spacing between sibling elements.

The key idea is simple: the parent becomes a flex container, and its direct children become flex items.


1. The Flex Container and Flex Items

Flexbox starts with one declaration:

.container {
  display: flex;
}
<div class="container">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>

Only the direct children become flex items. Grandchildren are not flex items unless their own parent also gets display: flex.

display: flexItem 1Item 2Item 3The parent controls the layout of direct children.

2. Main Axis and Cross Axis

Flexbox always has two axes:

  • Main axis: the direction items flow.
  • Cross axis: the perpendicular direction.

The main axis changes when flex-direction changes.

.row {
  display: flex;
  flex-direction: row;
}

.column {
  display: flex;
  flex-direction: column;
}
flex-direction: rowmain axiscrossflex-direction: columnmain axiscross

Understanding axes is the key to understanding justify-content and align-items.


3. flex-direction

flex-direction sets the main axis.

.container {
  display: flex;
  flex-direction: row;
}

Values:

  • row: left to right in left-to-right languages.
  • row-reverse: right to left.
  • column: top to bottom.
  • column-reverse: bottom to top.
.stack {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

Use row for navigation and toolbars. Use column for vertical stacks, forms, and card content.


4. justify-content: Main Axis Alignment

justify-content controls how items are distributed along the main axis.

.toolbar {
  display: flex;
  justify-content: space-between;
}

Common values:

ValueMeaning
flex-startPack items at the start
centerCenter items
flex-endPack items at the end
space-betweenEqual gaps between items, no outer gaps
space-aroundEqual space around every item
space-evenlyEqual space between and around items
flex-startcenterspace-between

Remember: justify-content follows the main axis. If the direction is column, it controls vertical alignment.


5. align-items: Cross Axis Alignment

align-items controls alignment along the cross axis.

.navbar {
  display: flex;
  align-items: center;
}

Common values:

  • stretch: stretch items across the cross axis.
  • flex-start: align at the cross-axis start.
  • center: center across the cross axis.
  • flex-end: align at the cross-axis end.
  • baseline: align text baselines.

align-items: center is common for navbars because it vertically centers logos, links, and buttons.

.media-object {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}

6. gap: Space Between Flex Items

Use gap to create consistent spacing between items.

.actions {
  display: flex;
  gap: 0.75rem;
}

This is usually cleaner than adding margins to children.

Bad:

.actions button {
  margin-right: 0.75rem;
}

Better:

.actions {
  display: flex;
  gap: 0.75rem;
}

gap works with rows, columns, wrapping flex containers, and grid containers.


7. flex-wrap

By default, flex items try to stay on one line.

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

Values:

  • nowrap: all items stay on one line if possible.
  • wrap: items move to new lines.
  • wrap-reverse: items wrap in reverse cross-axis direction.
nowrap: one linewrap: multiple lines

Use wrapping for tags, chips, card lists, and button groups.


8. Item Sizing: flex-grow, flex-shrink, and flex-basis

Flex items have three sizing controls.

.item {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 200px;
}

flex-basis

flex-basis is the starting size before extra space is distributed.

.sidebar {
  flex-basis: 260px;
}

flex-grow

flex-grow controls how items absorb extra space.

.main {
  flex-grow: 1;
}

If one item has flex-grow: 2 and another has flex-grow: 1, the first receives twice as much remaining free space.

flex-shrink

flex-shrink controls how items shrink when there is not enough room.

.logo {
  flex-shrink: 0;
}

This prevents the logo from being squeezed.


9. The flex Shorthand

The shorthand is:

flex: grow shrink basis;

Examples:

.main {
  flex: 1 1 auto;
}

.sidebar {
  flex: 0 0 260px;
}

.equal-card {
  flex: 1 1 240px;
}

Useful patterns:

PatternMeaning
flex: 1Grow and shrink from 0% basis
flex: 0 0 autoKeep natural size
flex: 0 0 260pxFixed flex basis
flex: 1 1 240pxStart at 240px, grow and shrink

Use explicit three-value shorthand when layout precision matters.


10. align-self

align-self overrides align-items for one item.

.container {
  display: flex;
  align-items: center;
}

.special {
  align-self: flex-end;
}

Use this sparingly. If many items need different alignment, the design may need a different layout structure.


11. order

The order property changes visual order without changing HTML order.

.primary-action {
  order: -1;
}

Be careful. Screen readers and keyboard navigation usually follow DOM order, not visual order. Do not use order to create a visual order that contradicts the meaningful reading order.

Use order for minor visual adjustments, not for rewriting document structure.


12. Common Pattern: Navbar

<nav class="site-nav">
  <a class="logo" href="/">Nandhoo</a>
  <div class="nav-links">
    <a href="/courses">Courses</a>
    <a href="/about">About</a>
    <a href="/contact">Contact</a>
  </div>
</nav>
.site-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 2rem;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 1rem;
}

@media (max-width: 640px) {
  .site-nav,
  .nav-links {
    flex-direction: column;
  }
}

This layout uses one flex container for the nav and another for the links.


13. Common Pattern: Media Object

A media object places an image or icon beside content.

<article class="media">
  <img src="/avatar.png" alt="Student avatar">
  <div>
    <h2>Lesson Progress</h2>
    <p>You completed three chapters.</p>
  </div>
</article>
.media {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}

.media img {
  flex: 0 0 64px;
  width: 64px;
  height: 64px;
  border-radius: 50%;
}

The image keeps a fixed size while the content fills the remaining space.


14. Common Pattern: Sticky Footer

Flexbox can push a footer to the bottom of the viewport.

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

main {
  flex: 1;
}

The main area grows to absorb remaining vertical space.


15. Flexbox vs. Grid

Use Flexbox for one-dimensional layouts. Use Grid for two-dimensional layouts.

NeedBetter tool
NavbarFlexbox
Button groupFlexbox
Center one itemFlexbox
Equal-height card rowFlexbox or Grid
Full page shell with rows and columnsGrid
Photo gallery with rows and columnsGrid
Dashboard layoutGrid

Simple rule:

row OR column -> Flexbox
row AND column -> Grid

16. Debugging Flexbox

When a flex layout behaves unexpectedly, ask:

  1. Which element has display: flex?
  2. Are the elements you want to control direct children?
  3. What is the main axis?
  4. Is justify-content affecting the axis you think it is?
  5. Is align-items stretching items?
  6. Are items shrinking because flex-shrink: 1 is the default?
  7. Would gap be better than margins?
  8. Is flex-wrap needed?
  9. Is min-width preventing shrinking?
Check container and direct childrenCheck main axis and cross axisCheck grow, shrink, basis, and wrapUse DevTools flex overlay

17. Mini Practice

Build a responsive card row:

  • Cards should sit in a row on wide screens.
  • Cards should wrap when there is not enough space.
  • Each card should start around 220px.
  • Cards should grow evenly.
  • There should be a 1rem gap.

Possible answer:

.card-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

.card {
  flex: 1 1 220px;
}

Now build a split layout:

  • Sidebar fixed at 260px.
  • Main content fills remaining space.
  • Layout stacks on small screens.

Possible answer:

.layout {
  display: flex;
  gap: 2rem;
}

.sidebar {
  flex: 0 0 260px;
}

.content {
  flex: 1 1 auto;
  min-width: 0;
}

@media (max-width: 760px) {
  .layout {
    flex-direction: column;
  }

  .sidebar {
    flex-basis: auto;
  }
}

min-width: 0 helps flex children shrink instead of overflowing when they contain long text or code.