CSS Grid Gap Behavior with Hidden Elements

Posted on February 14, 2023
Takes about 4 minutes to read

I was recently prototyping a component layout that included a way to toggle the visibility of sibling elements inside a grid display. What tripped me up was, while these elements were hidden, all of the container's gap gutters remained, leaving undesired extra visual spacing. I expected these gutters to collapse. The reason they stick around is related to explicitly defining grid templates.

Template or auto layout?

What are the differences between grid-template-* and grid-auto-* when declared for columns or rows in a grid layout? Ire Aderinokun has a fantastic article that thoroughly explains these distinctions and I recommend giving it a read. I'll try to quickly summarize: grid-template-* sets explicit column and row tracks, while grid-auto-* creates implicit track patterns.

The following excerpt in the "How grid-auto works" section from the article stood out to me:

Unlike the grid-template-* properties, the grid-auto-* properties only accept a single length value.

After some experimentation and confirming through examples from the Syntax section in the grid-auto-rows MDN web docs, I found that multiple track-size values can be used as well. Let's try an example to create a layout commonly referred to as the pancake stack. Its value of auto 1fr auto will either:

Visualize the gap

In the CodePen demo below, tick on the "Hide elements" checkbox to assign display: none on all but the first two elements in both grid containers.

Open CodePen demo

So what's happening here? When collapsed, the grid-template-rows container is slightly taller than its grid-auto-rows counterpart because of the extra space appearing beneath the remaining visible elements. Recall that rows are explicitly set with grid-template-rows. In this situation, the gap gutters still apply even when elements are hidden or removed from the container.

I ended up moving forward with grid-auto-rows for my component's layout needs. You can see a stripped down version of it in the CodePen below. The classic small screen navigation!

Open CodePen demo

A template solution

If using grid-template-* is preferred or necessary, the solution is to override the property value to match the expected visual result. The above demo could even get by on a single ruleset that applies the template only when the menu is open:

.nav.is-open {
  grid-template-rows: auto 1fr auto;
}

This same solution can also work for grid-template-areas. While it leads to writing more code, it self-documents really nicely.

.nav {
  grid-template-areas: "logo toggle";
}

.nav.is-open {
  grid-template-areas:
    "logo toggle"
    "menu menu"
    "cta  cta";
}

.nav .logo {
  grid-area: logo;
}
.nav .toggle {
  grid-area: toggle;
}
.nav .menu {
  grid-area: menu;
}
.nav .cta {
  grid-area: cta;
}

Helpful resources

Back to all blog posts

Webmentions for this post Learn about webmentions

7 reposts
6 replies
  • Brandon
    @hexagoncircle yep just another reason why CSS grid is maniacal. Imagine a "grid-gap-behavior: collapse;" property 😥
  • Victor Foster
    Such a great read on CSS grid templates
  • Pablo Lara H
    🔴🟣 CSS Grid Gap Behavior with Hidden Elements by Ryan Mulligan @hexagoncircle @hexagoncircle@fosstodon.org #CSS #cssgridgap #webdev ryanmulligan.dev/blog/grid-gap/
  • 황규연 / Kyooyeon Hwang
    숨겨진 요소가 있는 CSS 그리드 간격 동작 grid-template 및 grid-auto 레이아웃에서 항목을 숨길 때 CSS 간격 속성이 작동하는 방식에 대한 몇 가지 발견 (그냥 그리드 관련 글인가 궁금했는데 그리드에 대한 정보를 또 하나 발견... )
  • Frontend Dogma
    CSS Grid Gap Behavior with Hidden Elements, by @hexagoncircle@fosstodon.org: ryanmulligan.dev/blog/grid-gap/
  • mentioned in https://zahidecconsultants.com/2023/10/23/edition-312-by-anselm-hannemann/