Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Grid lines and areas

By default grid items take the cells one by one. But an item can be put into a particular place and stretched over several columns or rows. There are two ways to do it: by line numbers and by named areas.

Grid lines

Columns and rows are separated by lines. They are numbered from one: a grid of three columns has four vertical lines — from 1 at the left edge to 4 at the right one. Negative numbers count from the end: -1 is the last line.

 1        2        3        4
 | col. 1 | col. 2 | col. 3 |

Placing by lines

grid-column: 1 / 3 means "from line 1 to line 3" — the item takes two columns. The form 1 / -1 stretches an item over the full width, however many columns there are:

<style>
  .grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .grid div { padding: 12px; background: lightyellow; }
  .two { grid-column: 1 / 3; }
  .full { grid-column: 1 / -1; background: gold; }
</style>
 
<div class="grid">
  <div class="full">Full width</div>
  <div class="two">Lines 1–3</div>
  <div>One</div>
</div>

span — how many cells to take

It is often easier to say not "up to which line" but "how many columns". The word span does that. Rows have the same kind of property, grid-row:

<style>
  .grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 50px; gap: 8px; }
  .grid div { padding: 8px; background: honeydew; }
  .big { grid-column: span 2; grid-row: span 2; background: lightgreen; }
</style>
 
<div class="grid">
  <div class="big">2 × 2</div>
  <div>2</div><div>3</div><div>4</div><div>5</div>
</div>

The big item took four cells, and the others flowed around it.

Named areas

Line numbers are hard to read. The grid-template-areas property draws the grid with words: each quoted string is a row of the grid, each word is a cell. An item is assigned to an area with grid-area:

<style>
  .page {
    display: grid;
    grid-template-columns: 100px 1fr;
    grid-template-areas:
      "header header"
      "menu   main"
      "footer footer";
    gap: 8px;
  }
  .page > * { padding: 8px; background: lavender; }
  header { grid-area: header; }
  nav { grid-area: menu; }
  main { grid-area: main; }
  footer { grid-area: footer; }
</style>
 
<div class="page">
  <header>Header</header>
  <nav>Menu</nav>
  <main>The page content</main>
  <footer>Footer</footer>
</div>

Equal words next to each other merge into one area. A dot . instead of a word leaves the cell empty.

Rearranging areas

The order of areas is set in CSS, not in HTML. Rewrite grid-template-areas, and the skeleton changes — for example, the menu moves to the right:

<style>
  .page {
    display: grid;
    grid-template-columns: 1fr 100px;
    grid-template-areas: "main menu";
    gap: 8px;
  }
  .page > * { padding: 8px; background: mistyrose; }
  nav { grid-area: menu; }
  main { grid-area: main; }
</style>
 
<div class="page">
  <nav>Menu</nav>
  <main>Content</main>
</div>

In the lesson on media queries the skeleton is changed for phones in the same way.

Common mistake

An area must be a rectangle, and all rows of the template must have the same length. If an area turns out L-shaped, the browser throws away the whole grid-template-areas property, and the items end up nowhere near where you meant:

<style>
  .page {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "main side"
      "main main";
    gap: 8px;
  }
  .page > * { padding: 8px; background: lightyellow; }
  .a { grid-area: main; }
  .b { grid-area: side; }
</style>
 
<div class="page">
  <div class="a">main</div>
  <div class="b">side</div>
</div>

Here main takes three cells in an L shape — the template did not work.

Thanks for reading!

Donate to the site — we work hard for you.