Arkendia Classrooms
Lesson 13 of 21 · 18 min

CSS Grid: laying out in two dimensions

Flexbox is superb for a row or a column, but what about a gallery with neat columns, or a page layout with a header, a sidebar and a footer? That is the job of CSS Grid. In this lesson you will learn to create grids, place items and make a responsive card gallery for your portfolio with only a few lines.

Grid in one idea

CSS Grid divides a container into rows and columns, like a spreadsheet, and lets you place items in the resulting cells. Whereas Flexbox lays items out along a single line, Grid works in two dimensions at once.

As with Flexbox, you declare a grid container and its direct children become grid items.

.gallery {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 1.5rem;
}

This creates three columns of equal width. Items are placed in the cells automatically, row after row, and new rows are created as needed.

The fr unit

The fr unit means “a fraction of the available space”. 1fr 2fr creates two columns, the second twice as wide as the first. You can mix units:

grid-template-columns: 15rem 1fr;       /* fixed sidebar and flexible content */
grid-template-columns: 2fr 1fr;         /* two thirds and one third */
grid-template-columns: repeat(3, 1fr);  /* shorthand for 1fr 1fr 1fr */

The repeat() function saves you from writing the same value several times.

Gaps

As in Flexbox, gap sets the space between rows and columns, and row-gap and column-gap set them separately. The spacing lives in the container, so items need no margin.

A responsive gallery without media queries

Combine repeat(), auto-fit and minmax() for one of the most useful CSS patterns:

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1.5rem;
}

Read it as: “create as many columns as will fit, each at least 16rem wide, and let them share the remaining space equally”. On a wide screen you may get four columns, on a tablet two, and on a phone one. No media query required, and every row has aligned columns, unlike the wrapped flex cards of the previous lesson.

Tip. auto-fit collapses unused columns so that existing items stretch. auto-fill keeps the empty columns, leaving gaps at the end of a row. Try both on a small gallery to see the difference.

Placing items

Grid lines are numbered starting at 1. A grid with three columns has four vertical lines. You can place an item by telling it where to start and end:

.featured {
  grid-column: 1 / 3;   /* from line 1 to line 3: spans two columns */
}
.tall {
  grid-row: span 2;     /* spans two rows */
}
.wide {
  grid-column: span 2;
}

This lets you make a featured project twice as large as the others. Items can also be placed on named lines or areas, as you will see next.

Grid areas: designing a page layout

grid-template-areas lets you describe a layout visually:

.page {
  display: grid;
  grid-template-columns: 14rem 1fr;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  min-height: 100vh;
}
.page > header { grid-area: header; }
.page > aside  { grid-area: sidebar; }
.page > main   { grid-area: main; }
.page > footer { grid-area: footer; }

The strings form a drawing of the layout: the header spans both columns, the sidebar and the main content sit side by side, and the footer spans both. To rearrange the page for a phone, you only need to redefine grid-template-areas with a single column. The picture reads like a map, which makes the code easy to maintain.

Sizing rows

By default, rows are as tall as their content. You can shape them with grid-template-rows or grid-auto-rows:

.gallery {
  grid-auto-rows: 12rem;               /* every row 12rem */
  grid-auto-rows: minmax(10rem, auto); /* at least 10rem, taller if the content needs it */
}

The minmax(10rem, auto) form is safest, because rows grow when their content needs more room.

Aligning items in the grid

Alignment works similarly to Flexbox, with the same names:

  • justify-items and align-items position items inside their cells (horizontally and vertically).
  • justify-content and align-content position the whole grid inside the container when it is smaller.
  • justify-self and align-self override the alignment for one item.
  • place-items: center is a shorthand for centering items in both directions.

Card content with Flexbox inside Grid

Grid and Flexbox complement each other. Use Grid for the page and gallery, and Flexbox inside each card:

.project-card {
  display: flex;
  flex-direction: column;
}
.project-card img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}
.project-card .card-body {
  flex: 1;             /* pushes the footer of the card to the bottom */
  padding: 1rem;
}

The aspect-ratio property keeps images in a consistent shape, and object-fit: cover crops each photo to fill the frame without distortion. All your cards then align neatly even if the source images differ in shape.

Grid or Flexbox?

SituationBetter choice
A menu, a toolbar, a line of buttonsFlexbox
Centering a single elementEither; Flexbox or place-items
A page with header, sidebar, main, footerGrid
A gallery of aligned cardsGrid
Items of unknown number flowing in one lineFlexbox

A useful rule of thumb: if you think in terms of content flowing, use Flexbox. If you think in terms of a layout you design first, use Grid.

Warning. As with order in Flexbox, moving items visually with Grid placement does not change the reading and tab order, which follows the HTML. Keep your source order logical, and use Grid to arrange it, not to contradict it.

Your turn

  1. Wrap your project article elements in a container with the class gallery.
  2. Make it a responsive grid with repeat(auto-fit, minmax(16rem, 1fr)) and a gap.
  3. Add an image to each card with aspect-ratio and object-fit: cover.
  4. Make the first project span two columns on wide screens.
  5. Challenge: design the page layout of about.html with grid areas, for header, main, an aside and a footer.
See a solution
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1.5rem;
}
.gallery img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}
.gallery > article:first-child {
  grid-column: span 2;
}

If the first card spans two columns on a window that only fits one, the grid creates an implicit extra column. To avoid this, apply the span 2 rule only inside a media query for wide screens, which you will learn in the next lesson.

Key takeaways

  • display: grid with grid-template-columns creates rows and columns; fr shares free space and repeat() avoids repetition.
  • repeat(auto-fit, minmax(16rem, 1fr)) gives a responsive gallery without media queries.
  • Place items with grid-column and grid-row, or design the layout with grid-template-areas.
  • aspect-ratio and object-fit: cover keep images tidy.
  • Use Grid for two-dimensional layout and Flexbox for one-dimensional components; they combine well.
Advertisement
Log in to save your progress. Log in