Responsive Layout Patterns with CSS

Build the layouts every site needs, card grids, sidebars, holy grail pages, switchers and sticky footers, so they adapt to any screen with grid and flexbox.

Lesson 38 of 49Intermediate16 min read

Look closely at a hundred websites and you'll see the same few layouts again and again: a header with a main area and footer, a grid of cards, a sidebar next to content, a row of features that stacks on phones. Once you know how to build these layout patterns responsively, you can assemble almost any page from them.

Modern CSS makes these patterns short. Grid is ideal for two-dimensional page structure and card grids, and flexbox for rows of items that wrap. Many patterns need no media queries at all, because auto-fit, minmax() and flex-wrap let the content decide when to stack. Where a bigger change is needed, a single media query can rearrange a whole page with grid-template-areas.

In this lesson you'll build six patterns you'll reuse for years: the auto-fit card grid, the sidebar layout, the switcher, the holy grail page with named areas, the sticky footer, and the full-bleed article.

Pattern 1: The auto-fit card grid

CSS
.grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
  • minmax(240px, 1fr) means each column is at least 240px and shares the leftover space.
  • auto-fit creates as many columns as fit in a row.
  • Wrapping the minimum in min(240px, 100%) stops a single column overflowing on screens narrower than 240px.
  • auto-fill is similar, but keeps empty column tracks when there are few items, so cards don't stretch as wide.

Pattern 2: Sidebar and switcher with flexbox

The sidebar pattern puts a fixed-width side panel next to flexible content and stacks them when space runs out:

CSS
.with-sidebar { display: flex; flex-wrap: wrap; gap: 16px; }
.sidebar { flex: 1 1 240px; }
.content { flex: 999 1 400px; }

The huge flex-grow on .content makes it take almost all the extra space. When the container is too narrow for 240 + 400 pixels, the items wrap into one column, with no media query. The switcher is the same idea for equal items: flex: 1 1 200px on each, so they sit in a row when they fit and stack when they don't.

Pattern 3: Page layout with grid-template-areas

CSS
.page { display: grid; grid-template-areas: "header" "main" "aside" "footer"; }

@media (min-width: 900px) {
  .page {
    grid-template-columns: 1fr 280px;
    grid-template-areas:
      "header header"
      "main   aside"
      "footer footer";
  }
}

Named areas read like a picture of the layout. Each element is placed with grid-area: header and so on. On phones the areas stack in one column, and one media query redraws the whole map for wider screens. This is often called the holy grail layout: header, footer, main content and one or two sidebars.

CSS Responsive Layouts Syntax

Layout patterns

.cards { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
.with-sidebar { display: flex; flex-wrap: wrap; gap: 1rem; }
.with-sidebar > :first-child { flex: 1 1 240px; }
.with-sidebar > :last-child { flex: 999 1 400px; }
body { min-height: 100dvh; display: grid; grid-template-rows: auto 1fr auto; }
.page { display: grid; grid-template-areas: "header" "main" "footer"; }

CSS Responsive Layouts Summary

  • repeat(auto-fit, minmax(min(240px, 100%), 1fr)) makes a card grid with no media queries.
  • Flexbox with flex-wrap and a large flex-grow makes sidebars that stack automatically.
  • grid-template-areas describes a page layout and can be redrawn in one media query.
  • grid-template-rows: auto 1fr auto with min-height: 100dvh gives a sticky footer.
  • Change visual order carefully; keep the HTML in reading order.

CSS Responsive Layouts Examples

Each example runs in the page. Edit the code and press Run to see what changes.

Example 1

A holy grail page with named areas

Drag the result wider than 700px to see the layout change.

.page {
  display: grid;
  gap: 8px;
  grid-template-areas: "header" "nav" "main" "aside" "footer";
  font: 600 15px sans-serif;
}
.page > * { padding: 16px; border-radius: 8px; background: #e0e7ff; }
header { grid-area: header; } nav { grid-area: nav; } main { grid-area: main; min-height: 120px; background: #dcfce7; }
aside { grid-area: aside; } footer { grid-area: footer; }

@media (min-width: 700px) {
  .page {
    grid-template-columns: 160px 1fr 180px;
    grid-template-areas:
      "header header header"
      "nav    main   aside"
      "footer footer footer";
  }
}
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 4On phones every area stacks in one column.
  2. Lines 8 to 9Each element is assigned to a named area.
  3. Lines 12 to 17On wider screens, the same names are arranged into three columns.
Example 2

A sidebar that stacks itself

No media query: narrow the panel and the sidebar drops above the content.

.with-sidebar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font: 600 15px sans-serif;
}

.side {
  flex: 1 1 180px;
  background: #fef3c7;
  padding: 16px;
  border-radius: 8px;
}

.content {
  flex: 999 1 320px;
  min-height: 140px;
  background: #e0f2fe;
  padding: 16px;
  border-radius: 8px;
}
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 3Items wrap when they don't fit side by side.
  2. Line 9The sidebar wants 180px.
  3. Line 16Content wants at least 320px and takes nearly all the spare space.
Example 3

Sticky footer and full-bleed article

.shell {
  min-height: 420px;
  display: grid;
  grid-template-rows: auto 1fr auto;
  font-family: sans-serif;
}
header, footer { padding: 12px; background: #1f2937; color: white; }

.article {
  display: grid;
  grid-template-columns: 1fr min(40ch, 100% - 32px) 1fr;
  align-content: start;
}
.article > * { grid-column: 2; }
.article > .full { grid-column: 1 / -1; width: 100%; height: auto; }
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Lines 2 to 4The middle row grows, pushing the footer to the bottom. On a real page use min-height: 100dvh.
  2. Line 11A centre column for text, with flexible space on each side.
  3. Line 15The image spans all three columns, edge to edge.

Common CSS Responsive Layouts Mistakes

Using order to fix bad HTML

Don't
/* HTML: footer, main, header */
footer { order: 3; } header { order: 1; }
Do
/* HTML: header, main, footer, in reading order */

Screen readers and the Tab key follow the HTML order, not the visual order.

minmax that overflows phones

Don't
.grid { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); } /* overflows a 300px space */
Do
.grid { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }

A footer floating halfway up short pages

Don't
footer { position: absolute; bottom: 0; } /* overlaps content on long pages */
Do
body { min-height: 100dvh; display: grid; grid-template-rows: auto 1fr auto; }

CSS Responsive Layouts in Real Projects

Patterns in production

Online shops use auto-fit grids for product listings and sidebar layouts for filters. Dashboards use grid-template-areas for header, navigation and widgets. Blogs use the full-bleed pattern for wide photos in articles. The "Every Layout" approach, popular with front-end developers, builds whole sites from small intrinsic patterns like the sidebar and switcher, with very few media queries.

CSS Responsive Layouts Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Fit as many 200px columns as possible in each row.

.grid {
  display: grid;
  grid-template-columns: repeat(, minmax(200px, 1fr));
}
Multiple choiceeasy

Which property places an element in a named grid area?

Multiple choicemedium

What gives a sticky footer on short pages?

Multiple choicemedium

Why does .content { flex: 999 1 400px; } work in a sidebar layout?

Fix the bugmedium

The layout should stack on phones and show main and aside side by side from 600px using named areas. Fix the area names and the media query.

.pg { display: grid; grid-template-areas: "main" "aside"; }
.m { grid-area: content; }
.a { grid-area: aside; }
@media (max-width: 600px) {
  .pg { grid-template-columns: 2fr 1fr; grid-template-areas: "main aside"; }
}
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Main uses the main area
  • Mobile first media query
  • Side by side on wide screens

CSS Responsive Layouts Quiz

5 questions to check what you learned.

  1. Which tool suits a two-dimensional page layout best?

    • float
    • CSS grid
    • inline-block
    • tables
  2. What's the difference between auto-fit and auto-fill?

    • There's none
    • auto-fit only works in flexbox
    • auto-fill keeps empty tracks, so a few items don't stretch as wide
    • auto-fill needs a media query
  3. Why wrap the minimum in min(240px, 100%)?

    • So a single column never overflows a container narrower than 240px
    • To make cards bigger
    • It's required syntax
    • To add a gap
  4. What does the full-bleed pattern's middle column do?

    • Hides overflow
    • Keeps text in a readable column while wide elements span all columns
    • Centres images only
    • Adds a sidebar
  5. Why should you avoid using order to rearrange content heavily?

    • It's slow
    • It's not supported
    • It breaks grid
    • Keyboard and screen reader users follow the HTML order, which then doesn't match what they see

CSS Responsive Layouts Challenge

A product listing page

  1. Make .page a grid with grid-template-areas: "filters" "list" and gap: 16px
  2. Assign .filters to filters and .list to list
  3. From min-width: 800px, use grid-template-columns: 220px 1fr and areas "filters list"
  4. Make .list a grid with grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr)) and gap: 12px
.item { padding: 20px; background: #f1f5f9; }
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • Page uses named areas
  • Page gap is 16px
  • List is an auto-fit grid
  • Wide screen layout in a media query