Skip to content

Managing Overflow

Let's suppose that we have a grid child that will hold a list of images. On smaller screens, we want to add a horizontal scrollbar:

When we implement it, however, our overflow: auto appears not to work:

Code Playground

Result

Enable “Tab” for indentation

We've given our image-list a max-width of 100%, and set overflow: auto, so why isn't it truncating the size??

We tend to think of the fr unit as a way to divvy up leftover space, but there's another crucial aspect of this unit: it reacts based on its contents.

If we put a really-large child in this column, the fr unit will grow to contain it.

Here's an example showing this behaviour more clearly:

Code Playground

HTML

Result

Enable “Tab” for indentation

If you inspect this in the grid devtools, you'll notice that the second column has grown to be 1000px wide. It has to do this, since the column wants to contain the child, and the child is quite large.

There are two ways to solve this problem.

Solution 1: Moving the overflow

We can solve this problem by moving our overflow: auto to the grid child directly:

Code Playground

HTML

Result

Enable “Tab” for indentation

Coming back to our original problem, we can solve the issue by moving the overflow: auto up to the direct grid child:

Code Playground

Result

Enable “Tab” for indentation

Why does this work? My hunch is that the fr has an exception built-in: if the grid child has overflow: auto, it gives the column permission to shrink below the natural width of that element. But this doesn't work recursively: it has to be on the direct grid child, not a descendant.

Solution 2: Setting a minimum width

We've specified that our second column should have a width of 1fr. With a clever use of minmax, we can specify that we're OK with the column shrinking below the child's width:

Code Playground

Result

Enable “Tab” for indentation

By changing 1fr to minmax(0, 1fr), we're telling the column that it can be as small as it wants. It shouldn't worry about trying to stretch around the children.

CSS Tricks has a wonderful article on this approach: “Preventing a Grid Blowout”. And Rachel Andrew has a particularly insightful comment, explaining this phenomenon:

The explanation here is that the minimum size of an fr unit is auto. Grid then looks at the min-content size of the item. If the item has a size (you’ve given it a width) or has something in it with a size such as an image, the min-content size might be much bigger than the share of available space you think 1fr will give you. It’s easy to think of 1fr as being “one part of the space in the grid container” when it is really one part of the space left over.

If there is space to grow then the tracks grow from that min-content size assigning space.

Using minmax, as you have pointed out, is the best thing to do if you want to forcibly have equal width tracks, as that says “I want this track to have a min-content size of 0”, you could potentially in that situation end up with overflows as you lose the squishiness.