Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

css grid grows over 100% width with fr but not with minmax

Tags:

html

css

css-grid

.small-container { width: 200px; }
.small-container > div { margin: 16px; }
.border { box-shadow: 0 0 2px 2px black; }

.break-long-text {
    width: 100%;
    word-wrap: break-word;
    overflow-wrap: break-word;
}

.grid-fr {
    display: grid;
    grid-template-columns: 1fr;
}

.grid-minmax {
    display: grid;
    grid-template-columns: minmax(120px, 1fr);
}
<div class="small-container">
  <div class="grid-fr">
    <div class="break-long-text border">
      LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG
    </div>
  </div>
  <div class="grid-minmax">
    <div class="break-long-text border">
      LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG
    </div>
  </div>
</div>

The two grids are completely the same, the only difference is the grid-template-columns value. However, one grid respects the width of its parent (200px) and the other ignores the width.

  1. grid: grid-template-columns: 1fr; => ignores parent-width and continues until the content is filled

  2. grid: grid-template-columns: minmax(120px, 1fr); => Only goes up to parent-width (200px) and then becomes as high as necessary. However, it is still larger than the defined min-width (120px), which is of course correct since 1fr is larger than 120px in this example.

Since in the end both should have the same width of 1fr, I wonder about different results. Is this a bug or expected behavior? And why does the second grid work the way I expect it to and not the first?

So should I always use minmax if I don't want one cell to be larger than its parent?

like image 418
Putzi San Avatar asked Jul 09 '18 19:07

Putzi San


People also ask

Why is CSS Grid overflowing?

By default, a content-based minimum width could result in a large table or large image stretching the size of the entire content area, potentially into an overflow zone, and thereby making lines of text needlessly long and hard to read.

How do I fix grid size?

Select View > More. In the Ruler & Grid box, select Fixed for Grid spacing Horizontal and Grid spacing Vertical. Type the spacing you want between gridlines in Minimum spacing. Select OK.

How do I stop the grid from stretching?

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 .


1 Answers

Here's the solution to the second grid.

.grid-minmax {
   display: grid;
   grid-template-columns: minmax(120px, 1fr);
 }

This is how the browsers calculate the track size:

(200px container) - (120px nonflexible track size) + (1fr leftover space) = 200px

Using the guidance provided in the specification (see below), the behavior above is relatively simple and straightforward.

But why does the content in the first container overflow?

That's a tricky scenario and, at this point, I can see two potential paths to the answer.

  1. There is an issue / problem / bug in the workings between:

    .break-long-text {
        word-wrap: break-word;
        overflow-wrap: break-word;
     }
    

    and

    grid-template-columns: 1fr;
    

    I say this because when the string is broken up, the problem in the question doesn't exist. In other words, both grid containers behave the same (demo).

OR

  1. I'm not finding the answer in the specification. I've reviewed the following sections.

    • § 7.2.3. Flexible Lengths: the fr unit
    • § 11.7. Expand Flexible Tracks
    • § 11.7.1. Find the Size of an fr

Here's how the fr unit works, in detail:

From the spec:

§ 7.2.3. Flexible Lengths: the fr unit

A flexible length or <flex> is a dimension with the fr unit, which represents a fraction of the leftover space in the grid container.

Tracks sized with fr units are called flexible tracks as they flex in response to leftover space similar to how flex items fill space in a flex container.

Okay. So far, so good. The fr unit in grid layout functions similarly to flex-grow in flex layout.

Moving on with the spec...

The distribution of leftover space occurs after all non-flexible track sizing functions have reached their maximum.

The total size of such rows or columns is subtracted from the available space, yielding the leftover space, which is then divided among the flex-sized rows and columns in proportion to their flex factor.

(emphasis mine)

In other words all non-flexible track sizes (such as those based on pixels or ems) are first subtracted from the available space (200px, in this case). Whatever space remains is considered leftover space, which then gets targeted by the fr unit.

Also, what exactly is a "track sizing function"?

Each track sizing function can be specified as a length, a percentage of the grid container’s size, a measurement of the contents occupying the column or row, or a fraction of the free space in the grid.

It can also be specified as a range using the minmax() notation, which can combine any of the previously mentioned mechanisms to specify separate min and max track sizing functions for the column or row.

https://www.w3.org/TR/css3-grid-layout/#grid-template-rows-track-sizing-function

This explains the workings for the second grid container (with minmax()) but not the first (with 1fr).

like image 105
Michael Benjamin Avatar answered Sep 27 '22 17:09

Michael Benjamin