Home > Mobile >  What is the difference in grid-template-columns between fractions smaller than 1 to higher than 1?
What is the difference in grid-template-columns between fractions smaller than 1 to higher than 1?

Time:09-23

in grid-template-columns, isn't the only thing matter are the proportions between the fractions ? and if so, why do the divs look different when the fractions are higher than 1 vs. smaller than 1 ?

.gizim {
  display: grid;
  grid-template-columns: 0.3fr 0.4fr 0.3fr;
  margin: 5em;
  grid-gap: 1em;
  width: 400px;
}
.gizim div {
    border: 1px solid red;
}
.gizim div:first-child {
    width: 100px;  
}

.gidoo {
  display: grid;
  grid-template-columns: 3fr 4fr 3fr;
  margin: 5em;
  grid-gap: 1em;
  width: 400px;
}
.gidoo div {
    border: 1px solid blue;
}
.gidoo div:first-child {
    width: 100px;  
}

JSBIN example

CodePudding user response:

I suspect this is is expected behaviour although an edge case

According to the spec.

<flex> values between 0fr and 1fr have a somewhat special behavior: when the sum of the flex factors is less than 1, they will take up less than 100% of the leftover space.

A track’s value is effectively a request for some proportion of the leftover space, with 1fr meaning “100% of the leftover space”; then if the tracks in that axis are requesting more than 100% in total, the requests are rebalanced to keep the same ratio but use up exactly 100% of it. However, if the tracks request less than the full amount (such as three tracks that are each .25fr) then they’ll each get exactly what they request (25% of the leftover space to each, with the final 25% left unfilled). See § 11.7 Expand Flexible Tracks for the exact details of how leftover space is distributed.

This pattern is required for continuous behavior as fr values approach zero (which means the tracks wants none of the leftover space). Without this, a 1fr track would take all of the leftover space; but so would a 0.1fr track, and a 0.01fr track, etc., until finally the value is small enough to underflow to zero and the track suddenly takes up none of the leftover space. With this behavior, the track instead gradually takes less of the leftover space as its flex factor shrinks below 1fr, smoothly transitioning to taking none of the leftover space at zero.

Indeed the spec recommends NOT using fraction fr values.

Unless this “partial fill” behavior is specifically what’s desired, authors should stick to values ≥ 1; for example, using 1fr and 2fr is usually better than using .33fr and .67fr, as they’re more likely to behave as intended if tracks are added or removed.

Clearly in your example the total is 1fr but the container still behaves as though it is less as the setting widths and having content wider that .3fr disrupts the calculation

CodePudding user response:

To understand this you need to understand a tricky behavior related to 1fr. 1fr is equivalent to minmax(auto,1fr) as explained here: Why does minmax(0, 1fr) work for long elements while 1fr doesn't? which means "the track cannot be smaller than the size of the grid item"

You are wondering how this answer your question so Let's start with an example to illustrate the issue.

.gizim{
  display: grid;
  grid-template-columns: 0.3fr 0.4fr 0.3fr;
  margin: 5px auto;
  grid-gap: 1em;
  width: 400px;
  border:1px solid;
}

.gizim div {
  border: 1px solid red;
  min-height:20px;
}

.alt {
  grid-template-columns: minmax(0,0.3fr) minmax(0,0.4fr) minmax(0,0.3fr);
}
<div class="gizim">
  <div>1</div>
  <div>2</div>
  <div>3</div>
</div>
<div class="gizim">
  <div>1</div>
  <div>2</div>
  <div>333333333333333</div>
</div>
<div class="gizim alt">
  <div>1</div>
  <div>2</div>
  <div>333333333333333</div>
</div>

The first case will behave like you want because all your xfr are bigger than auto. Now let's understand the second case.

First we need to identify the "leftover" (https://www.w3.org/TR/css3-grid-layout/#leftover-space). It's the space left if we first consider the column sized to their default content. Something like below:

You can see the "leftover" space at the right. If we do some calculation we can find 400px - 2x16px(gap) - 120px(width of 3) = 248px so 1fr = 248px*. This will give us the logical result of:

 0.3fr = 74.4px
 0.4fr = 99.2px

It's important to note that the third element has an initial width bigger than .3fr so he will keep that width while the other will increase in width following the above calculation:

*In reality the calculation is more complex to explain in detail but the important part here is that the content play a role in defining how the fr will behave but if we use minmax(0,xfr) you will get the expected result because we are no more considering the content.


Such issue doesn't occur when using more than 1fr because we are going to use more than the "leftover" space so we will for sure fill all the columns but still the content play a role:

  • Related