314

TL;DR: Is there anything like table-layout: fixed for CSS grids?


I tried to create a year-view calendar with a big 4x3 grid for the months and therein nested 7x6 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, every month in that pen 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's 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.

Loilo
  • 13,466
  • 8
  • 37
  • 47
  • What do you want to happen instead? The font in each cell can just be whatever size and it never causes the grid cell size to increase? – Michael Coker Apr 09 '17 at 21:13
  • 1
    Exactly. Basically a more convenient way of what would happen if I set the sizes of the grid items to according percentage values instead of fractions. – Loilo Apr 09 '17 at 21:19
  • I'm basically looking for a grid-layouty version of table-layout: fixed (see: https://codepen.io/loilo/pen/dvxpvq?editors=1100) – Loilo Apr 09 '17 at 21:30
  • 32
    This the the biggest pain in the whole CSS Grid specification. Their needs to be a setting where grids areas cannot escape the dimensions of any of their parent grid containers! As is, it is a nightmare for deeply nested grid structures. – Lonnie Best Sep 05 '18 at 17:48

3 Answers3

556

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 by setting grid items to min-width: 0, min-height: 0 or overflow with any value other than visible.

From the spec:

6.6. Automatic 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.)

Here's a more detailed explanation covering flex items, but it applies to grid items, as well:

This post also covers potential problems with nested containers and known rendering differences among major browsers.


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 */
}

jsFiddle demo


1fr vs minmax(0, 1fr)

The solution above operates at the grid item level. For a container-level solution, see this post:

Gianfranco P.
  • 10,049
  • 6
  • 51
  • 68
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 9
    Wow. That's fascinating and interesting at the same time, and I would've definitely not have come up with that by just trying around. Did you just take a glance through the spec for that information? Because after not knowing what to google for, that's what I tried before, but I ended up reading the wrong section (after concluding the wrong cause of the problem). – Loilo Apr 10 '17 at 00:20
  • 2
    I had run into this problem before with [**flex items**](http://stackoverflow.com/q/36247140/3597276). Being that there are many similarities between flex and grid items, I figured the behavior might be the same and zeroed in on that section of the spec. – Michael Benjamin Apr 10 '17 at 00:37
  • 3
    It fixes the height, but it continues to grow in the horizontal direction, `min-width: 0;` doesn't help. Am i missing something? – user Apr 15 '17 at 18:25
  • 2
    @user, the Grid Layout implementations clearly vary between Chrome and Firefox. The original code in my answer works in Chrome. But it needs further adjustment to work in FF. Add `min-width: 0` to both `.month-grid` and `.day-item`. Answer revised. – Michael Benjamin Apr 15 '17 at 18:40
  • 1
    you could also mention that `max-width:100%;` has also the effect to contain elements within their grid cell ;) https://stackoverflow.com/questions/47168389/css-flexbox-truncated-text-in-css-grid-firefox-only/47168571#47168571 – G-Cyrillus Nov 08 '17 at 21:19
  • 8
    For nested grids we need to apply this to all levels. But I really came here to upvote and thank you.. – Knack Mar 06 '18 at 08:29
  • 2
    I always wondered why specifying height as x% doesn't work when the parent's height is defined in %/vh/vw. The content always ended up expanding the div and breaking the parent. This min-height thing is magic! It does sorta make sense too. Why don't the tutorial websites discuss these reasons!? Any place someone could find more such explanations as a pre curated list? – Pragy Agarwal Aug 29 '18 at 14:51
  • 2
    @PragyAgarwal.. https://stackoverflow.com/users/3597276/michael-b?tab=answers :-) – Michael Benjamin Aug 29 '18 at 15:07
  • 8
    css spec contributors should stop taking drugs. Why not a new keyword ? Why making a special behavior of an already existing property that do not even make sense ? ... Will css become a day easy and intuitive ? – Hugo Mallet Jan 17 '20 at 15:07
  • 2
    You're the Real MVP! Thank you for the 'min-width: 0;' solution. I was able to fix my slick slider overflowing a cell (kenwheeler). – Peter Feb 26 '20 at 08:40
  • 3
    `minmax` did the rick just perfect! – vovchisko Feb 08 '21 at 13:18
  • 1
    saved me so much time. but sheesh what a terrible state of things. absolutely no way to predict or figure out this problem logically. – Ben Steward Jun 15 '21 at 22:13
  • 1
    Using minmax(0,1fr) over 1fr was the key for me. Thank you! – Matt. Dec 21 '22 at 14:31
162

The previous answer is pretty good, but I also wanted to mention that there is a fixed layout equivalent for grids, you just need to write minmax(0, 1fr) instead of 1fr as your track size.

FremyCompany
  • 2,430
  • 1
  • 14
  • 18
  • 18
    I recommend this approach over the previous, accepted answer. – Thierry Prost Nov 25 '18 at 09:02
  • 2
    Although this works, I don't understand a bit of it ... Could you maybe explain why this works? What is minmax(0, 1fr) doing? Should that not always be 0? I'm confused :( – BAERUS Jan 21 '19 at 18:37
  • 14
    `minmax(0, 1fr)` works because `1fr` is really a shorthand for `minmax(auto,1fr)`, which is not the correct value for the original question. – Mikko Rantalainen Feb 07 '19 at 07:40
  • 2
    For additional details, see https://github.com/w3c/csswg-drafts/issues/1777 – Mikko Rantalainen Feb 07 '19 at 07:47
  • 6
    all other answers are hacks, this should be the accepted answer – shinzou Jul 30 '20 at 12:41
  • I'm glad I scrolled further. This is exactly what I needed– a fixed grid that does not nudge at all and place items on the grid lines crossings. Designers like to think that way and I love that CSS is able to adapt to that. – katerlouis Jul 21 '23 at 08:05
13

The existing answers solve most cases. However, I ran into a case where I needed the content of the grid-cell to be overflow: visible. I solved it by absolutely positioning within a wrapper (not ideal, but the best I know), like this:


.month-grid {
  display: grid;
  grid-template: repeat(6, 1fr) / repeat(7, 1fr);
  background: #fff;
  grid-gap: 2px;  
}

.day-item-wrapper {
  position: relative;
}

.day-item {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 10px;

  background: rgba(0,0,0,0.1);
}

https://codepen.io/bjnsn/pen/vYYVPZv

bjnsn
  • 2,710
  • 2
  • 16
  • 14