Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Grid

Flexbox lines elements up along one line. Grid lays them out in two directions at once — in rows and columns, like a table. It suits galleries, product cards and the overall page skeleton.

Columns

display: grid turns the parent into a grid container, and grid-template-columns lists the column widths. The children fill the cells from left to right by themselves, and when the columns run out they move to the next row:

<style>
  .grid { display: grid; grid-template-columns: 100px 100px 100px; }
  .grid div { padding: 12px; background: lavender; border: 1px solid mediumpurple; }
</style>
 
<div class="grid">
  <div>1</div><div>2</div><div>3</div>
  <div>4</div><div>5</div><div>6</div>
</div>

Three values mean three columns of 100 pixels. Six items took two rows.

Fractions of free space

The fr unit (from "fraction") splits the free space into parts. Three columns of 1fr are three equal parts of the width. gap sets the spacing between cells, as in flexbox:

<style>
  .grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }
  .grid div { padding: 12px; background: lightskyblue; }
</style>
 
<div class="grid">
  <div>1</div><div>2</div><div>3</div>
</div>

The form 2fr 1fr would make the first column twice as wide as the second.

repeat and mixed sizes

The repeat(4, 1fr) function is a short way to write four equal columns. Fixed sizes and fractions can be mixed: a column in pixels takes its share, and 1fr takes the rest:

<style>
  .page { display: grid; grid-template-columns: 120px 1fr; gap: 8px; margin-bottom: 8px; }
  .four { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
  .page div, .four div { padding: 12px; background: honeydew; }
</style>
 
<div class="page"><div>Menu</div><div>The content takes the rest</div></div>
<div class="four"><div>1</div><div>2</div><div>3</div><div>4</div></div>

Rows

The row heights are set by grid-template-rows. If there are more rows than described, the extra ones get their height from grid-auto-rows:

<style>
  .grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 60px; gap: 8px; }
  .grid div { padding: 8px; background: lightyellow; }
</style>
 
<div class="grid">
  <div>1</div><div>2</div><div>3</div><div>4</div><div>5</div>
</div>

Without grid-auto-rows a row would be as tall as its content.

A responsive grid

The minmax(120px, 1fr) function sets a column no narrower than 120 pixels and no wider than one fraction. Together with repeat(auto-fill, ...) the browser decides by itself how many columns fit:

<style>
  .cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; }
  .cards div { padding: 20px 12px; background: mistyrose; text-align: center; }
</style>
 
<div class="cards">
  <div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div>
</div>

The example window stretches together with the page. Narrow the browser window — there will be fewer columns, and the cards stay at least 120 pixels wide.

Grid or flexbox

TaskWhat to choose
Items along one line: a menu, buttonsFlexbox
A grid of rows and columns: cards, a galleryGrid
The page skeleton: header, menu, contentGrid
Aligning content inside a blockFlexbox

They are often used together: grid for the grid of cards, flexbox inside each card. And to line up the parts of neighbouring cards, the inner grid can borrow rows from the outer one — see the lesson "Subgrid".

Common mistake

Percentage columns together with gap stick out of the container: three columns of 33% plus two gaps of 16px add up to more than 100%. The fr unit shares the space left after the gaps:

<style>
  .grid { display: grid; gap: 16px; margin-bottom: 8px; border: 2px dashed gray; }
  .bad { grid-template-columns: 33% 33% 33%; }
  .ok { grid-template-columns: repeat(3, 1fr); }
  .grid div { padding: 12px; background: lavender; }
</style>
 
<div class="grid bad"><div>33%</div><div>33%</div><div>33%</div></div>
<div class="grid ok"><div>1fr</div><div>1fr</div><div>1fr</div></div>

The top grid sticks out of the dashed frame, the bottom one fits exactly.

Thanks for reading!

Donate to the site — we work hard for you.