Loilo Loilo - 1 year ago 62
CSS Question

Prevent grid items from stretching in CSS Grid Layout

TL;DR: Is there anything like

table-layout: fixed
for CSS grids?

I tried to create a year-view calendar view with a big 3x4 grid for the months and therein nested 6x7 grids for the days.

The calendar should fill the page, so the year grid container gets a width and height of 100% each.

.year-grid {
width: 100%;
height: 100%;

display: grid;
grid-template: repeat(3, 1fr) / repeat(4, 1fr);

.month-grid {
display: grid;
grid-template: repeat(6, 1fr) / repeat(7, 1fr);

Here's a working example: https://codepen.io/loilo/full/ryXLpO/

For simplicity, in that pen every month there has 31 days and starts on a Monday.

I also chose a ridiculously small font size to demonstrate the problem:

Grid items (= day cells) are pretty condensed as there are several hundreds of them on the page. And as soon as the day number labels become too large (feel free to play around with the font size in the pen using the buttons on the upper left) the grid will just grow in size and exceed the page body size.

Is there any way to prevent this behaviour?

I initially declared my year grid to be 100% in width and height so that's probably the point to start at, but I couldn't find any grid-related CSS properties that would've fitted that need.

Disclaimer: I'm aware that there are pretty easy ways to style that calendar just without using CSS Grid Layout. However, this question is more about the general knowledge on the topic than solving the concrete example.

Answer Source

By default, a grid item cannot be smaller than the size of its content.

Grid items have an initial size of min-width: auto and min-height: auto.

You can override this behavior with min-width: 0, min-height: 0 or overflow with any value other than visible.

From the spec:

6.6. Implied Minimum Size of Grid Items

To provide a more reasonable default minimum size for grid items, this specification defines that the auto value of min-width / min-height also applies an automatic minimum size in the specified axis to grid items whose overflow is visible. (The effect is analogous to the automatic minimum size imposed on flex items.)

Being that this Grid behavior is similar to flexbox, here's a more complete explanation covering flex items: Why doesn't flex item shrink past content size? This post also covers known rendering differences between Chrome and Firefox.

To fix your layout, make these adjustments to your code:

.month-grid {
  display: grid;
  grid-template: repeat(6, 1fr) / repeat(7, 1fr);
  background: #fff;
  grid-gap: 2px;
  min-height: 0;  /* NEW */
  min-width: 0;   /* NEW; needed for Firefox */

.day-item {
  padding: 10px;
  background: #DFE7E7;
  overflow: hidden;  /* NEW */
  min-width: 0;      /* NEW; needed for Firefox */

revised codepen

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download