Height-retaining tabs component using css grid

When creating UI components for the web, you want to avoid jumping content where one component pushes another away. However, this is not always as easy as it seems.

A SIMPLE TABS IMPLEMENTATION

Take a tabs component as an example. You have multiple content containers and if you want to avoid jumping of the content you need to make sure that the whole component is large enough to contain the largest of the content containers.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<div class="tabs">
  <div class="tabs__header">
    <button class="tabs__title active">Tab1</button>
    <button class="tabs__title">Tab2</button>
  </div>
  <div class="tabs__content-wrapper">
    <div class="tabs__content active">
      <p>Molestiae voluptatem autem molestias quidem. In cupiditate id eligendi debitis. Repellat vel quod aut magni quo.</p>
    </div>

    <div class="tabs__content">
      <p>Eos veritatis occaecati provident vel. Voluptate consectetur deserunt quia iusto asperiores quibusdam voluptas aut. Culpa tenetur consequatur ea sunt sit impedit. Rerum voluptas sed enim et asperiores. Labore facere facilis sunt illo ut praesentium.</p>
      <p>Ex aut explicabo esse in consequuntur ad. Pariatur molestias minima facilis. Aut sed a quia. Dicta eum architecto et cumque sed.</p>
    </div>
  </div>
</div>
<div class="other">Other Content</div>

See the live example.

USING CSS GRID

Until now, we resorted to using JavaScript to determine the maximum height of the content and setting it on the component. But with the dawn of CSS Grid there is an easier pure CSS solution to the problem. The trick is to put all content containers into one CSS Grid cell. The grid will then make sure that the cell is big enough for every content container.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
.tabs__content-wrapper {
    display: grid;
}

.tabs__content {
  grid-column-start: 1;
  grid-row-start: 1;
  visibility: hidden;
}

.tabs__content.active {
  visibility: visible;
}

See the live example.

Browser Support

Even though the browser support for CSS grid is still mediocre, we can utilise @supports to gracefully degrade to the original solution without height retainment.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@supports (display: grid) {
.tabs__content-wrapper {
    display: grid;
}

  .tabs__content {
    grid-column-start: 1;
    grid-row-start: 1;
    display: block;
    visibility: hidden;
  }

  .tabs__content.active {
    visibility: visible;
  }
}

OTHER USAGES

The same solution also works for similar use cases where I want to dynamically switch the content but retain the overall height like details containers or fading from one component into another.