EduFlow
Modern CSS Mastery
0%

Section 2 · Layout That Holds Up

Grid: Areas, auto-fit and minmax()

18 min3 min readCode playground

Lesson at a glance

Lay out a page with named grid-template-areas and build a speaker grid that picks its own column count with repeat(auto-fit, minmax()).

  1. 1Draw the page with template areas
  2. 2The fr unit and its hidden minimum
  3. 3A speaker grid that counts its own columns
  4. 4Your turn

No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.

Flexbox lays things out in one direction and lets each line make its own decisions. That’s perfect for a row of filters and wrong for Waypoint’s speaker grid, where every card in a column should line up with the cards above and below it. When you need rows and columns to agree, you want grid.

This lesson builds two layouts on the schedule page: the page shell, with named areas, and the speaker grid, which decides its own number of columns.

Draw the page with template areas

The schedule page has a header across the top, a filter sidebar and the main content. With grid-template-areas you draw that layout directly:

layout.css
.page {
  display: grid;
  grid-template-columns: 14rem minmax(0, 1fr);
  grid-template-areas:
    "header  header"
    "filters main";
  gap: 1.5rem;
}
.site-header { grid-area: header; }
.filters     { grid-area: filters; }
.schedule    { grid-area: main; }

Each string is a row; each word inside it is a column. Repeating a name (header header) makes that area span both columns. A . marks an empty cell. Areas must be rectangles: an L-shape is invalid and the whole declaration is dropped.

The pay-off comes when the layout changes. On narrow screens the filters should sit above the sessions, so you redraw the strings instead of moving markup:

CSS
@media (width < 48rem) {
  .page {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "header"
      "filters"
      "main";
  }
}

The fr unit and its hidden minimum

fr divides the free space in the grid after fixed tracks and gaps are subtracted. Two 1fr columns in a 600px grid with a 20px gap are 290px each.

There’s a catch you’ll meet sooner or later: 1fr is shorthand for minmax(auto, 1fr), and auto as a minimum means “at least the content’s min-content width”. Put a long unbroken URL or a code block in one column and it widens, stealing space from the other. That’s why the page shell above uses minmax(0, 1fr): it lets the main column shrink below its content, and any overflow is handled inside it (with overflow-x: auto on the code block, for instance). It’s the grid cousin of the min-width: 0 fix from the previous lesson.

A speaker grid that counts its own columns

Waypoint has 23 speakers. On a phone they should stack; on a laptop, four or five across. One declaration handles every width:

speakers.css
.speakers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
}
.speaker.featured {
  grid-column: 1 / -1;
}

Read it inside out. minmax(180px, 1fr) says each column is at least 180px and at most an equal share of the free space. repeat(auto-fit, …) asks the browser to create as many such columns as fit. In a 640px container with 16px gaps, three 180px columns fit (three columns plus two gaps is 572px) and four don’t, so you get three columns, each stretched to about 203px.

grid-column: 1 / -1 makes the keynote speaker span from the first line to the last, whatever the column count. Negative line numbers count from the end of the explicit grid.

Two grids of the same width with two items each. With auto-fill, the items occupy two of four equal columns and two empty dashed tracks remain. With auto-fit, the empty tracks collapse and the two items each take half the width. auto-fill empty empty auto-fit
auto-fill keeps empty tracks; auto-fit collapses them so items stretch

The difference between auto-fit and auto-fill only shows when there are fewer items than columns. auto-fill keeps the empty tracks, so two speakers stay card-sized and leave a gap. auto-fit collapses empty tracks to zero, so the two speakers stretch across the row. For a speaker grid that’s sometimes nearly empty (day two has only four speakers), pick based on the design: auto-fill for consistent card widths, auto-fit for a full row.

Your turn

The exercise gives you the page shell and the speaker grid with hard-coded columns. Name the areas, switch the speakers to auto-fit, and make the keynote span the whole row. The checks resize the page to make sure the column count adapts. Next, you’ll make the contents of grid cards line up across cards with subgrid.

Key takeaways

  • grid-template-areas lets you draw the layout as ASCII art, and rearranging the page for another screen size means redrawing the strings, not moving markup.
  • repeat(auto-fit, minmax(12rem, 1fr)) creates as many columns as fit and stretches them to fill the row, with no media queries.
  • auto-fill keeps empty tracks when there are few items, while auto-fit collapses them so the items stretch to fill the row.
  • 1fr has an automatic minimum of the content size; use minmax(0, 1fr) when a track must be allowed to shrink below its content.

Further reading

Check your understanding

3 questions

Question 1 of 3

A speaker grid uses repeat(auto-fill, minmax(180px, 1fr)) in a 900px container but only has two speakers. What do you see?

Question 2 of 3

What does this layout put in the second row, first column?

CSS
.page {
  display: grid;
  grid-template-columns: 14rem 1fr;
  grid-template-areas:
    "header header"
    "filters main";
}
Question 3 of 3

A grid with grid-template-columns: 1fr 1fr gets a code block with a very long line in its first column, and the columns become unequal. What’s the fix?

Practice

Code playground

Name the areas, let the speakers flow

The page is fixed at 860px for this exercise.

  1. Give .page a grid-template-areas layout: header across both columns on the first row, then filters and main side by side. Assign .site-header, .filters and .speakers to those areas.
  2. Replace the speakers’ fixed repeat(3, 1fr) with columns that are at least 180px, as many as fit, and that stretch to fill the row when there are only a few speakers.
  3. Make the .featured speaker span the full row.

The checks resize the page and hide some speakers to see how your grid reacts.

<div class="page">
  <header class="site-header">Waypoint Conf 2026</header>
  <nav class="filters">Tracks</nav>
  <main class="speakers">
    <div class="speaker featured">Keynote · Ana Ortiz</div>
    <div class="speaker">Kenji Watanabe</div>
    <div class="speaker">Layla Haddad</div>
    <div class="speaker">Tom Becker</div>
    <div class="speaker">Priya Nair</div>
    <div class="speaker">Marcus Lee</div>
  </main>
</div>Loading the editor…

Ctrl/⌘ + Enter to run · Runs in a sandbox in your browser. Nothing leaves your device.

Preview

Console

(no output)

Checks

  • The page uses grid-template-areas
  • The header spans the top; filters sit left of the speakers
  • The speakers form three columns at this width
  • The featured speaker spans the full row
  • A narrower page gets two columns
  • With two speakers, they stretch to fill the row