Skip to content

[css-grid-3][Masonry] Intrinsic auto repeats mixed with fixed tracks #12899

@alisonmaher

Description

@alisonmaher

During the discussion at #9321 (comment) @fantasai raised a case where intrinsic auto repeats mixed with fixed track sizes could lead to overflow. I mentioned that in that case it wouldn't overflow, but this is because I forgot to divide by the span, which was needed to cause the overflow. So opening an issue to flesh out the use case and potential mitigations.

The use case that was raised was:

<style>
.masonry {
    display: masonry;
    background: gray;
    grid-template-columns: repeat(auto-fill, 100px auto);
    width: 500px;
    height: 300px;
}

.masonry > div {
    width: 300px;
    height: 100px;
    grid-column: span 2;
}
</style>
<body>
  <div class="masonry">
    <div style="background: lightskyblue;">
      Number 1
    </div>
    <div style="background: lightcoral;">
      Number 2
    </div>
  </div>
</body>

This renders as follows in Chromium:

Image

This is because per the intrinsic auto repeat heuristic the following steps happen:

  1. We expand any intrinsic auto repeats once, resulting in 10px auto
  2. We run an initial track sizing pass where we create a single spanning virtual item that gets the largest contribution from all items. Any spanning item's contribution is divided by its span. In this case, the virtual item gets a contribution size of 300/2 or 150px.
  3. We run track sizing up through the intrinsic sizing pass, and take the growth limit of the virtual item as the size of auto. In this case, that is 150px
  4. We then calculate the actual number of auto repeats for 100px auto or 100px 150px. Since the available space is 500px, we get 2 repeats, resulting in 100px auto 100px auto
  5. We then layout using the normal masonry algorithm, and the spanning items get placed in track 1 and track 3. Because they are 300px wide, auto resolves to 300 - 100 or 200px. This leads to a total of 100 + 200 + 100 + 200 sized columns, or 600px, which ends up overflowing the 500px wide container.

The reason being that the heuristic to divide by the span size doesn't quite work in all cases when there are fixed track sizes mixed in.

Some potential options that I can think of:

Option 1:
Don't allow mixing of intrinsic track sizes in a repeat with other kinds of track sizes. This means that grid-template-columns: repeat(auto-fill, 100px auto); would not be allowed. This is a possible mitigation, but doesn't prevent issues where there is a fixed track size outside of the auto repeat.

For example, you can hit similar issues with grid-template-columns: 10px repeat(auto-fill, auto);. If you replace the track definition above with this, you get the same rendering:
Image

So if we go this path, we may also want to consider restricting it further to only allow intrinsic auto repeats on their own, but this seems overly restrictive to me.

Option 2:
Instead of expanding the intrinsic auto repeat once in the first track sizing pass, expand it enough to cover the largest spanning item. Don't divide items by their span size, and place items as normal. This would fix the case mentioned above, but you could end up with different sizes for different intrinsic tracks.

For example, if you had grid-template-columns: repeat(auto-fill, 100px auto auto); in the example above, the first auto would evaluate to 200px and the second would evaluate to 150px. You could solve this by taking the largest of the final intrinsic track sizes (in this case 200px) to determine the number of auto repeats to do.

Option 3:
Instead of dividing by the total span, take each item span, and reduce it based on min(total number of tracks, item span). That means that if your item spans 5 tracks, and there are 3 tracks after expanding the intrinsic auto repeat once, you would reduce its span to 3 and adjust its contribution accordingly. This would fix the case above, but I suspect you can still come up with cases that lead to overflow.

This option, similar to 2, would require you to take the largest final initial track size per type of intrinsic track in the repeat, since you could end up with different sizes based on your track definition and items.

Option 4:
Leave the heuristic as is and accept that there are cases where it doesn't work as well that could lead to overflow.

Any other ideas?

CC @fantasai @tabatkins @Loirooriol

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Thursday Afternoon

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions