Mastering CSS Grid and Flexbox

by Ada
Last updated on May 24, 2024

Mastering CSS Grid and Flexbox

Learn how to create powerful, responsive layouts using CSS Grid and Flexbox. This guide covers everything from basic concepts to advanced layout patterns.

When to Use Grid vs Flexbox

Use Flexbox When:

  • You need one-dimensional layouts (rows OR columns)
  • Content should determine layout size
  • You need simple alignment and spacing
  • Building navigation bars, card layouts, or toolbars

Use Grid When:

  • You need two-dimensional layouts (rows AND columns)
  • Layout should determine content size
  • You need precise control over rows and columns
  • Building page layouts, galleries, or dashboards

Flexbox Fundamentals

Basic Flex Container

css
.container {
  display: flex;
  /* Default: flex-direction: row */
}

Flex Direction

css
/* Horizontal (default) */
.row {
  display: flex;
  flex-direction: row;
}

/* Vertical */
.column {
  display: flex;
  flex-direction: column;
}

/* Reversed */
.row-reverse {
  flex-direction: row-reverse;
}

Justify Content (Main Axis)

css
.container {
  display: flex;

  /* Align items along main axis */
  justify-content: flex-start;    /* Default */
  justify-content: flex-end;
  justify-content: center;
  justify-content: space-between;  /* Equal space between items */
  justify-content: space-around;   /* Equal space around items */
  justify-content: space-evenly;   /* Equal space everywhere */
}

Align Items (Cross Axis)

css
.container {
  display: flex;

  /* Align items along cross axis */
  align-items: stretch;     /* Default */
  align-items: flex-start;
  align-items: flex-end;
  align-items: center;
  align-items: baseline;    /* Align text baselines */
}

Flex Wrap

css
.container {
  display: flex;
  flex-wrap: wrap;           /* Items wrap to new line */
  flex-wrap: nowrap;         /* Default - no wrapping */
  flex-wrap: wrap-reverse;   /* Wrap in reverse */
}

Gap

css
.container {
  display: flex;
  gap: 1rem;                 /* Space between items */
  row-gap: 1rem;            /* Vertical spacing */
  column-gap: 2rem;         /* Horizontal spacing */
}

Flex Items Properties

Flex Grow

css
.item {
  flex-grow: 1;  /* Item grows to fill available space */
}

.item-double {
  flex-grow: 2;  /* Grows twice as much as flex-grow: 1 */
}

Flex Shrink

css
.item {
  flex-shrink: 1;  /* Default - item can shrink */
  flex-shrink: 0;  /* Item won't shrink */
}

Flex Basis

css
.item {
  flex-basis: 200px;  /* Starting size before growing/shrinking */
  flex-basis: 25%;    /* Percentage of container */
  flex-basis: auto;   /* Default - based on content */
}

Flex Shorthand

css
.item {
  /* flex: grow shrink basis */
  flex: 1 0 200px;

  /* Common patterns */
  flex: 1;           /* Grow to fill, can shrink, auto basis */
  flex: 0 0 auto;    /* Don't grow or shrink */
  flex: auto;        /* Same as 1 1 auto */
}

Practical Flexbox Examples

Centered Content

css
.center {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}
html
<div class="center">
  <div>Perfectly centered content</div>
</div>

Navigation Bar

css
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 2rem;
}

.nav-links {
  display: flex;
  gap: 2rem;
  list-style: none;
}
html
<nav class="navbar">
  <div class="logo">Brand</div>
  <ul class="nav-links">
    <li><a href="/">Home</a></li>
    <li><a href="/about">About</a></li>
    <li><a href="/contact">Contact</a></li>
  </ul>
</nav>

Card Layout

css
.cards {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
}

.card {
  flex: 1 1 300px;  /* Grow, shrink, min 300px */
  max-width: 400px;
}

Holy Grail Layout

css
.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.header,
.footer {
  flex-shrink: 0;
}

.main {
  display: flex;
  flex: 1;  /* Grow to fill available space */
}

.content {
  flex: 1;
}

.sidebar {
  flex: 0 0 250px;  /* Fixed width sidebar */
}

CSS Grid Fundamentals

Basic Grid Container

css
.container {
  display: grid;
  grid-template-columns: 200px 200px 200px;
  grid-template-rows: 100px 100px;
  gap: 1rem;
}

Fractional Units (fr)

css
.grid {
  display: grid;

  /* Equal columns */
  grid-template-columns: 1fr 1fr 1fr;

  /* Mixed units */
  grid-template-columns: 200px 1fr 2fr;

  /* Sidebar + main content */
  grid-template-columns: 250px 1fr;
}

Repeat Function

css
.grid {
  /* Instead of: 1fr 1fr 1fr 1fr */
  grid-template-columns: repeat(4, 1fr);

  /* Mixed patterns */
  grid-template-columns: repeat(3, 100px 1fr);

  /* Auto-fill: creates as many columns as fit */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

  /* Auto-fit: collapses empty columns */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

Grid Template Areas

css
.layout {
  display: grid;
  grid-template-areas:
    "header header header"
    "sidebar content content"
    "footer footer footer";
  grid-template-columns: 250px 1fr 1fr;
  grid-template-rows: auto 1fr auto;
  gap: 1rem;
  min-height: 100vh;
}

.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer  { grid-area: footer; }

Grid Item Placement

css
/* Column placement */
.item {
  grid-column-start: 1;
  grid-column-end: 3;

  /* Shorthand */
  grid-column: 1 / 3;

  /* Span syntax */
  grid-column: span 2;
}

/* Row placement */
.item {
  grid-row: 1 / 3;
  grid-row: span 2;
}

/* Both at once */
.item {
  grid-area: 1 / 1 / 3 / 3;  /* row-start / col-start / row-end / col-end */
}

Alignment in Grid

css
.grid {
  display: grid;

  /* Align all items */
  justify-items: start | end | center | stretch;
  align-items: start | end | center | stretch;
  place-items: center;  /* Shorthand for both */

  /* Align grid tracks */
  justify-content: start | end | center | space-between | space-around;
  align-content: start | end | center | space-between | space-around;
  place-content: center;  /* Shorthand for both */
}

/* Align individual item */
.item {
  justify-self: center;
  align-self: center;
  place-self: center;  /* Shorthand */
}

Practical Grid Examples

Responsive Card Grid

css
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 2rem;
}

Dashboard Layout

css
.dashboard {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-template-rows: auto 1fr auto;
  gap: 1rem;
  min-height: 100vh;
}

.header {
  grid-column: 1 / -1;  /* Full width */
}

.sidebar {
  grid-column: 1 / 3;   /* 2 columns */
  grid-row: 2;
}

.main {
  grid-column: 3 / -1;  /* Remaining columns */
  grid-row: 2;
}

.footer {
  grid-column: 1 / -1;
  grid-row: 3;
}

Magazine Layout

css
.magazine {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-auto-rows: 200px;
  gap: 1rem;
}

.featured {
  grid-column: span 4;
  grid-row: span 2;
}

.article {
  grid-column: span 2;
}

.sidebar {
  grid-column: span 2;
  grid-row: span 3;
}

Image Gallery

css
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  grid-auto-rows: 250px;
  gap: 1rem;
}

.gallery-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Create irregular sizes */
.wide {
  grid-column: span 2;
}

.tall {
  grid-row: span 2;
}

.large {
  grid-column: span 2;
  grid-row: span 2;
}

Combining Grid and Flexbox

css
/* Grid for page layout */
.page {
  display: grid;
  grid-template-areas:
    "header"
    "main"
    "footer";
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}

/* Flexbox for header content */
.header {
  grid-area: header;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 2rem;
}

/* Grid for main content */
.main {
  grid-area: main;
  display: grid;
  grid-template-columns: 250px 1fr;
  gap: 2rem;
  padding: 2rem;
}

/* Flexbox for cards */
.card {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

Responsive Patterns

Mobile-First Approach

css
/* Mobile: single column */
.grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}

/* Tablet: 2 columns */
@media (min-width: 768px) {
  .grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* Desktop: 3 columns */
@media (min-width: 1024px) {
  .grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

Auto-Responsive Grid

css
/* No media queries needed! */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 1rem;
}

Responsive with Grid Template Areas

css
.layout {
  display: grid;
  grid-template-areas:
    "header"
    "content"
    "sidebar"
    "footer";
  gap: 1rem;
}

@media (min-width: 768px) {
  .layout {
    grid-template-areas:
      "header header"
      "content sidebar"
      "footer footer";
    grid-template-columns: 1fr 300px;
  }
}

Common Patterns

Sticky Footer

css
.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.content {
  flex: 1;
}

Equal Height Columns

css
/* Flexbox */
.columns {
  display: flex;
  gap: 2rem;
}

.column {
  flex: 1;
}

/* Grid */
.columns {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
}

Aspect Ratio Boxes

css
.box {
  aspect-ratio: 16 / 9;
}

/* Alternative with padding trick */
.box-old {
  position: relative;
  padding-bottom: 56.25%; /* 16:9 ratio */
}

.box-old > * {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

Resources