Go Back

CSS Flexbox

Definition

CSS Flexbox (Flexible Box Layout) is a one-dimensional layout model in CSS designed to provide a more efficient way to arrange, align, and distribute space among items within a container, even when their size is unknown or dynamic. Unlike traditional layout models that rely on block and inline flow directions, Flexbox operates in two axes—main axis and cross axis—making it ideal for responsive designs that need to adapt to different screen sizes and devices.

Introduced as part of CSS3, Flexbox provides a more predictable and powerful alternative to older layout techniques like floats and positioning. It's particularly useful for components of an application's user interface and small-scale layouts, while CSS Grid (another modern layout system) is designed for larger-scale, two-dimensional layouts.

Core Concepts

Flex Container and Flex Items

A flex layout consists of two main components:

  1. Flex Container: The parent element that has display: flex or display: inline-flex applied to it
  2. Flex Items: The direct children of the flex container
<div class="flex-container">
  <div class="flex-item">Item 1</div>
  <div class="flex-item">Item 2</div>
  <div class="flex-item">Item 3</div>
</div>
.flex-container {
  display: flex;
  /* or display: inline-flex; */
}

Main Axis and Cross Axis

Flexbox layout is based on two axes:

  1. Main Axis: The primary axis along which flex items are placed (horizontal by default)
  2. Cross Axis: The axis perpendicular to the main axis

The directions of these axes are determined by the flex-direction property:

.flex-container {
  display: flex;
  flex-direction: row; /* Default: main axis is horizontal, left to right */
  /* Other values: row-reverse, column, column-reverse */
}

Container Properties

Flex Direction

Establishes the main axis, determining the direction flex items are placed:

.flex-container {
  flex-direction: row; /* Default: left to right */
  /* flex-direction: row-reverse; */ /* Right to left */
  /* flex-direction: column; */ /* Top to bottom */
  /* flex-direction: column-reverse; */ /* Bottom to top */
}

Flex Wrap

Controls whether items are forced into a single line or can wrap onto multiple lines:

.flex-container {
  flex-wrap: nowrap; /* Default: single line */
  /* flex-wrap: wrap; */ /* Multiple lines, top to bottom */
  /* flex-wrap: wrap-reverse; */ /* Multiple lines, bottom to top */
}

Flex Flow

Shorthand for flex-direction and flex-wrap:

.flex-container {
  flex-flow: row nowrap; /* Default */
  /* flex-flow: column wrap; */
  /* flex-flow: row-reverse wrap-reverse; */
}

Justify Content

Defines alignment along the main axis:

.flex-container {
  justify-content: flex-start; /* Default: items packed at start */
  /* justify-content: flex-end; */ /* Items packed at end */
  /* justify-content: center; */ /* Items centered */
  /* justify-content: space-between; */ /* First and last items at edges, equal spacing between */
  /* justify-content: space-around; */ /* Equal spacing around items */
  /* justify-content: space-evenly; */ /* Equal spacing between items and edges */
}

Align Items

Defines alignment along the cross axis:

.flex-container {
  align-items: stretch; /* Default: items stretch to fill container */
  /* align-items: flex-start; */ /* Items aligned at start of cross axis */
  /* align-items: flex-end; */ /* Items aligned at end of cross axis */
  /* align-items: center; */ /* Items centered on cross axis */
  /* align-items: baseline; */ /* Items aligned by their baselines */
}

Align Content

Aligns flex lines within the container when there's extra space in the cross axis (only applies when there are multiple lines):

.flex-container {
  flex-wrap: wrap; /* Enable wrapping for align-content to work */
  align-content: stretch; /* Default: lines stretch to fill container */
  /* align-content: flex-start; */ /* Lines packed at start */
  /* align-content: flex-end; */ /* Lines packed at end */
  /* align-content: center; */ /* Lines centered */
  /* align-content: space-between; */ /* Equal space between lines */
  /* align-content: space-around; */ /* Equal space around lines */
}

Item Properties

Order

Controls the order in which items appear:

.flex-item:nth-child(1) { order: 3; } /* Display third */
.flex-item:nth-child(2) { order: 1; } /* Display first */
.flex-item:nth-child(3) { order: 2; } /* Display second */

Flex Grow

Determines how much an item can grow relative to other items if there's available space:

.flex-item { flex-grow: 0; } /* Default: won't grow */
.primary-item { flex-grow: 1; } /* Will consume available space */
.secondary-item { flex-grow: 0.5; } /* Will grow at half the rate of primary */

Flex Shrink

Determines how much an item will shrink relative to others when there's not enough space:

.flex-item { flex-shrink: 1; } /* Default: will shrink if needed */
.important-item { flex-shrink: 0; } /* Won't shrink */
.less-important { flex-shrink: 2; } /* Will shrink twice as much */

Flex Basis

Sets the initial main size of an item before growing/shrinking:

.flex-item { flex-basis: auto; } /* Default: based on content */
.specific-width { flex-basis: 200px; } /* Initial width/height of 200px */
.percentage-width { flex-basis: 50%; } /* Initial width/height of 50% */

Flex

Shorthand for flex-grow, flex-shrink, and flex-basis:

.flex-item {
  flex: 0 1 auto; /* Default: won't grow, will shrink, auto basis */
  /* flex: 1; */ /* Same as flex: 1 1 0%; will grow and shrink, 0% basis */
  /* flex: auto; */ /* Same as flex: 1 1 auto; will grow and shrink, auto basis */
  /* flex: none; */ /* Same as flex: 0 0 auto; won't grow or shrink */
}

Align Self

Overrides the container's align-items for specific items:

.flex-container {
  align-items: center; /* Centers all items */
}

.top-aligned {
  align-self: flex-start; /* This item aligns to top */
}

.bottom-aligned {
  align-self: flex-end; /* This item aligns to bottom */
}

Common Flexbox Patterns

Centering Elements

One of the simplest and most common uses of Flexbox is perfect centering:

.centered-container {
  display: flex;
  justify-content: center; /* Horizontal centering */
  align-items: center; /* Vertical centering */
  height: 300px; /* Container height */
}

Flexbox is perfect for creating responsive navigation:

.navbar {
  display: flex;
  justify-content: space-between; /* Space between brand and nav items */
}

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

.nav-links {
  display: flex;
  gap: 20px; /* Space between nav items */
}

/* Responsive navigation */
@media (max-width: 768px) {
  .navbar {
    flex-direction: column;
  }
  
  .nav-links {
    margin-top: 10px;
  }
}

Card Layouts

Flexible card layouts that adapt to different screen sizes:

.card-container {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.card {
  flex: 1 1 300px; /* Grow, shrink, minimum width of 300px */
  display: flex;
  flex-direction: column;
}

.card-body {
  flex: 1; /* Takes up remaining space */
}

.card-footer {
  margin-top: auto; /* Pushes footer to bottom */
}

Holy Grail Layout

The classic "holy grail" layout with header, footer, and three columns:

.holy-grail {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.header, .footer {
  flex-shrink: 0; /* Don't shrink */
}

.main-content {
  display: flex;
  flex: 1; /* Take up all available space */
}

.sidebar-left, .sidebar-right {
  flex: 0 0 200px; /* Don't grow or shrink, width of 200px */
}

.content {
  flex: 1; /* Take up remaining space */
}

/* Responsive adjustment */
@media (max-width: 768px) {
  .main-content {
    flex-direction: column;
  }
  
  .sidebar-left, .sidebar-right {
    flex-basis: auto;
  }
}

Equal Height Columns

Creating columns with equal height, regardless of content:

.equal-columns {
  display: flex;
  gap: 20px;
}

.column {
  flex: 1; /* All columns get equal width */
  padding: 20px;
  background-color: #f0f0f0;
}

Advanced Techniques

Auto Margins for Spacing

Using margin: auto in Flexbox creates unique spacing opportunities:

.flex-container {
  display: flex;
}

.push-right {
  margin-left: auto; /* Pushes item to the far right */
}

.push-apart {
  margin: 0 auto; /* Centers item with auto margins on sides */
}

Nested Flexbox

Combining multiple flex containers for complex layouts:

.parent {
  display: flex;
  height: 500px;
}

.sidebar {
  flex: 0 0 200px;
}

.main {
  flex: 1;
  display: flex; /* Nested flex container */
  flex-direction: column;
}

.main-header {
  flex-shrink: 0;
}

.main-content {
  flex: 1; /* Takes remaining space */
  display: flex; /* Another nested container */
  flex-wrap: wrap;
  gap: 20px;
}

.content-item {
  flex: 1 1 200px; /* Grow, shrink, min width */
}

Flex and max-width/min-width

Combining flex properties with min/max constraints:

.flex-item {
  flex: 1 1 0%; /* Grow and shrink equally from 0% base */
  min-width: 200px; /* But never smaller than 200px */
  max-width: 300px; /* And never larger than 300px */
}

Using gap for Spacing

The gap property (relatively new to Flexbox) creates consistent spacing:

.flex-container {
  display: flex;
  gap: 20px; /* 20px between all items */
  /* row-gap: 20px; */ /* Only between rows */
  /* column-gap: 10px; */ /* Only between columns */
}

Browser Support and Fallbacks

Current Support

Flexbox is supported in all modern browsers. The most problematic legacy browser was Internet Explorer, which had partial support in IE10-11 with some bugs.

Providing Fallbacks

For older browsers, consider these fallback strategies:

/* Legacy float-based layout */
.container {
  overflow: hidden; /* Clearfix for floats */
}

.item {
  float: left;
  width: 33.33%;
}

/* Modern flexbox layout */
@supports (display: flex) {
  .container {
    display: flex;
    flex-wrap: wrap;
  }
  
  .item {
    float: none;
    flex: 1 1 33.33%;
  }
}

Flexbox vs. Grid

When to Use Flexbox

  • One-dimensional layouts (row OR column)
  • When content should dictate layout
  • For alignment and distribution within a container
  • Component-level layouts
  • Simple, content-first designs

When to Use CSS Grid

  • Two-dimensional layouts (rows AND columns)
  • When layout should dictate content
  • For precise placement in a defined grid
  • Page-level layouts
  • Complex, layout-first designs

Combining Both

In many modern layouts, Flexbox and Grid work together:

.page-layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}

.navbar {
  grid-column: 1 / -1;
  display: flex; /* Flexbox within Grid */
  justify-content: space-between;
}

.sidebar {
  grid-column: 1;
  grid-row: 2;
}

.content {
  grid-column: 2;
  grid-row: 2;
  display: flex; /* Flexbox within Grid */
  flex-wrap: wrap;
  gap: 20px;
}

.footer {
  grid-column: 1 / -1;
  grid-row: 3;
  display: flex; /* Flexbox within Grid */
  justify-content: space-between;
}

Best Practices

Performance Considerations

  • Avoid changing flex properties in animations, as they can trigger layout recalculations
  • Limit nesting of flex containers to what's necessary
  • Use will-change: transform for items that will animate

Accessibility Implications

  • Ensure that visual order (with order property) doesn't conflict with logical document order for screen readers
  • Test keyboard navigation when changing display order
  • Maintain a logical tab order even when using Flexbox to rearrange elements

Responsive Design Tips

  • Start with a mobile-first approach
  • Use flex-wrap and percentage-based flex-basis for responsiveness
  • Combine Flexbox with media queries for layout changes
  • Consider content requirements at different screen sizes
  • CSS Grid: Two-dimensional layout system complementary to Flexbox
  • Responsive Design: Design approach for creating layouts that adapt to different screen sizes
  • Box Model: Foundation of CSS layout that Flexbox builds upon
  • Media Queries: CSS technique for applying styles based on device characteristics
  • Container Queries: Emerging feature for styles based on container size rather than viewport

Conclusion

CSS Flexbox has revolutionized web layout by providing a more intuitive and powerful way to create responsive designs. Its ability to distribute space and align items dynamically makes it an essential tool in modern front-end development. While it's not the solution for every layout challenge (especially complex grid-based layouts), Flexbox excels at one-dimensional layouts and component design.

By mastering Flexbox, developers can create more flexible, maintainable, and responsive user interfaces that adapt gracefully across devices. As browser support continues to improve and new features like the gap property become more widely available, Flexbox remains a cornerstone of modern CSS layout techniques.