Another Collection of Interesting Facts About CSS Grid

Avatar of Manuel Matuzovic
Manuel Matuzovic on

UGURUS offers elite coaching and mentorship for agency owners looking to grow. Start with the free Agency Accelerator today.

Last year, I assembled A Collection of Interesting Facts about CSS Grid Layout after giving a workshop. This year, I worked on another workshop and I’ve learned some more exciting facts about the layout spec we all so love.

Of course, I’m not going to keep my knowledge to myself. I’m happy to share my findings once again with you, the CSS-Tricks community.

Understanding how the `grid` shortcut works

Sometimes, reading and understanding parts of the grid—or actually any other—spec can be very hard.

For example, it took me quite a while to understand how to use the grid shorthand properly. The specification states that the valid values are:

<‘grid-template’> | <‘grid-template-rows’> / [ auto-flow && dense? ] <‘grid-auto-columns’>? | [ auto-flow && dense? ] <‘grid-autwo-rows’>? / <‘grid-template-columns’>

You can make sense of it if you take your time or if you’re experienced in reading specs. I tried several combinations and all of them failed. What eventually helped me was a note in the spec:

Note that you can only specify the explicit or the implicit grid properties in a single grid declaration.

Rachel Andrew has a series of posts that help explain how to read a specification, using CSS Grid as an example.

So, we can specify a multitude of things using the grid shorthand, but just not all of them at once. Here are some examples.

Using `grid` in favor of `grid-template`

The grid-template property is a shorthand for setting grid-template-columns, grid-template-rows, and grid-template-areas in a single declaration. We can do the same with the grid shorthand, which is a little shorter.

grid: "one one" 200px 
      "two four" 
      "three four" 
      / 1fr 2fr;

/* shorthand for: */ 
/*
  grid-template-areas: "one one" "two four" "three four";
  grid-template-rows: 200px;
  grid-template-columns: 1fr 2fr;
*/

This shorthand creates three rows and two columns, with four named grid areas. The first row has an explicit height of 200px, while the second and the third have an implicit height of auto. The first column has a width of 1fr and the second a width of 2fr.

See the Pen grid shorthand – areas, explicit rows and columns by Manuel Matuzovic (@matuzo) on CodePen.

Want to know more about the difference between an explicit and an implicit grid? Check out this post I wrote on the topic here on CSS-Tricks.

We don’t have to specify areas if we don’t need them. We can use the grid shorthand just for defining explicit rows and columns. The following two snippets are essentially doing the same thing:

grid-template-rows: 100px 300px;
grid-template-columns: 3fr 1fr;
grid: 100px 300px / 3fr 1fr;

Handling implicit rows and columns

It’s possible to use the grid shorthand to specify grid-auto-flow as well, but it doesn’t exactly work as we might expect. We don’t just add the row or column keyword somewhere in the declaration. Instead, we have to use the auto-flow keyword on the correct side of the slash.

If it’s to the left of the slash, the shorthand sets grid-auto-flow to row and creates explicit columns.

grid: auto-flow / 200px 1fr;

/* shorthand for: */ 
/*
  grid-auto-flow: row;
  grid-template-columns: 200px 1fr;
*/

If it’s to the right of the slash, the shorthand sets grid-auto-flow to column and creates explicit rows.

grid: 100px 300px / auto-flow;

/* shorthand for: */ 
/*
  grid-template-rows: 100px 300px;
  grid-auto-flow: column;
*/

We can also set the size of implicit tracks together with the auto-flow keyword, which respectively sets grid-auto-rows or grid-auto-columns to the specified value.

grid: 100px 300px / auto-flow 200px;

/* shorthand for: */ 
/*
  grid-template-rows: 100px 300px;
  grid-auto-flow: column;
  grid-auto-columns: 200px;
*/

See the Pen grid shorthand – explicit rows and implicit columns by Manuel Matuzovic (@matuzo) on CodePen.

Feature queries in Edge

Checking support for CSS Grid works great with Feature Queries because all browsers that support Grid also understand feature queries. This means that we can check if a browser supports the old or the new spec, or both. Both, you ask? Starting with Edge 16, Edge does not just support the new spec, but the old one as well.

So, if you want to differentiate between versions of Edge that support the new spec and those that don’t, you have to write your queries like this:

/* Edge 16 and higher */
@supports (display: -ms-grid) and (display: grid) {
  div {
    width: auto;
  }
}

/* Edge 15 and lower */
@supports (display: -ms-grid) and (not (display: grid)) {
  div {
    margin: 0
  }
}

Here’s a handy little demo, that displays which feature query triggers in the browser you opened it with.

See the Pen display: grid support test by Manuel Matuzovic (@matuzo) on CodePen.

As a side note, you shouldn’t go overboard with (mis)using feature queries for browser sniffing, because browser detection is bad.

Specifying the exact number of items per column

Grid is great for page layouts, but it can be very useful on a component level as well. One of my favorite examples is the ability to specify the exact amount of items per column in a multi-column component.

Let’s say we have a list of 11 items and we want to add a new column after every fourth item. The first thing we want to do after setting display: grid on the parent is to change the way the grid auto-placement algorithm works. By default, it fills in each row, in turn, adding new rows as necessary. If we set grid-auto-flow to column, grid will fill each column in turn instead, which is what we want. The last thing we have to do is specify the number of items per column. This is possible by defining as many explicit rows as needed using the grid-template-rows property. We can set the height of each row explicitly or just make them as big as their contents by using the auto keyword.

ul {
  display: grid;
  grid-template-rows: auto auto auto auto;

  /* or shorter and easier to read: */
  /* grid-template-rows: repeat(4, auto); */
  grid-auto-flow: column;
}

If we have to change the number of items per column to 5, we just add another track to the track listing or we make use of the repeat-notation instead and just change the first parameter to the desired value (grid-template-rows: repeat(5, auto)).

See the Pen Limited number of items per column by Manuel Matuzovic (@matuzo) on CodePen.

Sticky footers with CSS Grid

There are many ways to create sticky footers in CSS. Some of them are hacky and complicated, but it’s pretty straightforward with Grid.

Let’s say we have a *classic* header, main content and footer page structure.

<body>
  <header>HEADER</header>
  <main>MAIN</main>
  <footer>FOOTER</footer>
</body>

First, we set the height of html and body to at least 100% of the viewport to make sure the page always uses the full vertical space. Then we apply grid-template-rows to split the body into three rows. The first (header) and the last (footer) row can have whatever size we want. If we want them to always be as big as their contents, we simply set the height to auto. The row in the middle (main) should always fill up the rest of the space. We don’t have to calculate the height because we can use the fraction unit to achieve that.

html {
  height: 100%;
}

body {
  min-height: 100%;
  display: grid;
  grid-template-rows: auto 1fr auto;
}

As a result, the main body grows and the footer adjusts accordingly and stays at the bottom of the viewport.

See the Pen CSS Grid Layout Sticky Footer by Manuel Matuzovic (@matuzo) on CodePen.

Automatic minimum size of grid items

Recently, Florian tweeted that he was wondering why truncating single line text within a grid item was so complicated. His example perfectly illustrates an interesting fact about grid items.

The starting situation is a three-column grid with a paragraph in each grid item.

<div class="grid">
  <div class="item">
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo ipsum exercitationem voluptate, autem veritatis enim soluta beatae odio accusamus molestiae, perspiciatis sunt maiores quam. Deserunt, aliquid inventore. Ullam, fugit dicta.
    </p>
  </div>
</div>
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 20px;
}

Each paragraph should only be single-line and display an ellipsis at the end of the line if the paragraph is longer than its parent item. Florian solved that by setting white-space to nowrap, which forces a single line, hiding overflow and setting text-overflow to ellipsis.

p {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

This would have worked perfectly fine on a block element, but in this grid example, the columns expand to the width of the single-line paragraph:

See the Pen Automatic minimum size of grid items by Manuel Matuzovic (@matuzo) on CodePen.

Broadly speaking, this happens, because a grid item can’t be smaller than its children. The default min-width of a grid-item (or flex-item) is set to auto, which according to the spec:

…applies an automatic minimum size in the specified axis to grid items whose overflow is visible and which span at least one track whose min track sizing function is auto.

This makes grid and flex items more flexible, but sometimes it’s not desirable that the content is able to stretch its parent items width. To avoid that we can either change the overflow property of the grid-item to something other than visible or set the min-width to 0.

See the Pen Truncate Text in CSS Grid by Manuel Matuzovic (@matuzo) on CodePen.

Read more about Automatic Minimum Size of Grid Items in the grid spec.

Wrapping up

Hopefully these recent takeaways help you feel more comfortable writing and using Grid as they have for me. There’s a lot of detail in this new specification, but it becomes more interesting and understandable with more use.