Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-grid-3] Allow <auto-repeat> (i.e. repeat(auto-fill|auto-fit, ...)) to accept intrinsic sizes #9321

Open
fantasai opened this issue Sep 7, 2023 · 6 comments
Labels

Comments

@fantasai
Copy link
Collaborator

fantasai commented Sep 7, 2023

From @bfgeek in #9041:

One thing that seems desirable is to allow a wider/different syntax for rows/columns than is currently allowed for grid, e.g. masonry-template: repeat(auto-fill, auto).
(Above would measure all the masonry items, and select the best number of tracks to fit the content).
(Arguably above might be a better default than masonry-template: auto for example).
This isn't possible for grid-template for good reasons - but we could accept it for masonry.
One open question is if we need different track sizes or just one would suffice. All the designs I have personally seen have just one track repeated N times. Accepting just one track template would allow easier intrinsic sizing of spanners for example.

This is behavior probably doable (and desirable!) in Grid itself. A typical use case is a grid of cards, where the size of the cards isn't known (or is awkward to know) ahead of time when writing the stylesheet. We probably want to introduce new keywords to convey the "items contribute on all tracks" aspect of it, though, so that keyword track sizes within repeat() aren't treated differently to the identical keyword track sizes outside it.

@fantasai
Copy link
Collaborator Author

fantasai commented Sep 7, 2023

@bfgeek suggested restricting the repetition to a single track, to avoid complications. Here are the three plausible levels of restrictions I can think of:

  • Most restricted: the repeat() function can only accept one track size (not a listing), and must be the sole value of the grid-template in that axis. Otherwise the declaration is invalid.
    This has the fewest complications.
  • Less restricted: the repeat() function can only accept one tracks size (not a listing), but there can be additional columns in the grid-template of that axis.
    _This creates some confusing possibilities with items that span outside the repetition sequence. It's possible to account for, but you have to track all possible spanning positions rather than just divide the space by the span count.
  • Least restricted: the repeat() function can accept multi-track listings including the new intrinsic-size-evenly values, and there can be additional columns in the grid-template of that axis.
    This is even more complicated to calculate, but can probably also be done if we need to.

I think we can start with the most restricted version, and expand if there's demand for it. Most use cases aren't going to need anything further.

@Loirooriol
Copy link
Contributor

Note <auto-repeat> already accepts intrinsic sizes, as long as at least one of the min or max sizing functions is not intrinsic nor flexible.

How would the number of repetitions be calculated if both are intrinsic?

What are the "intrinsic-size-evenly values"?

@fantasai
Copy link
Collaborator Author

fantasai commented Sep 7, 2023

How would the number of repetitions be calculated if both are intrinsic?

You'd have to define an intrinsic size that doesn't depend on placement, e.g. assume every track contains every (auto-placed) item and compute its size from the resulting size contributions, or something like that.

@bfgeek
Copy link

bfgeek commented Nov 22, 2023

I think this is one of the cases where this makes sense for masonry - but doesn't make a lot of sense for grid. Consider:

.grid {
  grid-template-rows: repeat(auto-fill, fit-content);
  grid-template-columns: repeat(3, auto);
}

The repeats have to be expanded before placement occurs, and any sizing of the tracks. When trying to evaluate the fit-content you need to give it the grid items some inline-size in order to perform layout to retrieve the intrinsic block-size.

None of the tracks are resolved (and you haven't placed yet either) - so this inline-size will be very different from what the final inline-size is, and as a result the intrinsic fit-content sizes used for the repeats will be very different from the final fit-content of the grid.

This will result in a lot of free-space in the tracks, or not enough tracks confusing web developers.

This doesn't occur with masonry as described in the alternate approach as the inline-size you choose will be stable across the operations.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-grid-3] Allow <auto-repeat> (i.e. repeat(auto-fill|auto-fit, ...)) to accept intrinsic sizes.

The full IRC log of that discussion <TabAtkins> fantasai: Ian suggested it might useful to bea ble to use auto-fill with the intrinsic sizing keywords, particularly in Masonry
<TabAtkins> fantasai: Because, before you can stat placing items you need to know the size of the tracks
<TabAtkins> fantasai: Currently the spec says that you resolve the sizes as if all items were in that track
<TabAtkins> fantasai: So you can do an auto-repeat based on that size
<TabAtkins> fantasai: Can give you odd results if you have wildly differing sizes, and all the thins happens to in one column
<TabAtkins> fantasai: But mostly you'll want this where sizes are similar to even identical
<TabAtkins> fantasai: Grid could maybe also benefit from this
<TabAtkins> fantasai: There's cases where you want to ahve some number of items in your autoplaced grid, but not hardcode the size of the items into the track listing, you want the size to come from the items themselves
<TabAtkins> fantasai: So doing something similar - take the size of the largest grid item - could work
<TabAtkins> fantasai: So question is: is this somethign we're interested in adding?
<iank_> q+
<oriol> q+
<TabAtkins> fantasai: We can add various restrictions as necessary. Like, maybe only the intrinsic-auto-fill can be auto sized
<TabAtkins> fantasai: So you can have one repeat, it can have one track in it, and it's the only intrinsic size in the axis
<TabAtkins> fantasai: More possibilities gets increasingly confusing
<Rossen_> ack iank_
<TabAtkins> iank_: I think this is one of the cases where it's potentiallyc onfsuing for authors in Grid
<TabAtkins> iank_: But makes more sense in Masonry
<TabAtkins> iank_: I typed out an example in the issue
<TabAtkins> iank_: When you're determining the intrinsic size for your items, you need to give them some constraints in the opposite axis
<TabAtkins> iank_: Most noticably, working out the intrinsic block size, you need some inline size
<TabAtkins> iank_: In Grid, since this is before placement, you dont' know what tracks they'll end up in, what size those tracks are, so you ahve to give it *some* inline size
<TabAtkins> iank_: And this'll differ wildly from the item's actual inline size
<TabAtkins> iank_: So the intrinsic block size you're using for repetitions and what it'll actually look like can be very very different
<TabAtkins> iank_: This isn't a problem for Masonry, since the inline size between these steps is stable, it doesn't change. Only a problem for the Grid case
<TabAtkins> iank_: So you'll end up with items where repetitions have a bunch of free space where they shouldn't and we'll get bug reports about Grid looking bad
<Rossen_> ack oriol
<TabAtkins> oriol: Similar to what Ian is saying, I don't see a way to make this work in Grid
<TabAtkins> oriol: Might make sense for Masonry but not seeing it for Grid
<TabAtkins> Rossen_: Suggestions?
<TabAtkins> iank_: The reason a separate display type might be useful is we make things work great for Masonry even if they don't work for Grid
<TabAtkins> fantasai: If the track sizing in the other axis is all the same...
<TabAtkins> fantasai: So like in Grid if the other axis is all auto because you haven't specified row heights
<TabAtkins> fantasai: YOu're auto filling the columns - however many will fit - and the rows are auto height intrinsic grid tracks
<TabAtkins> fantasai: So one thing we could do is handle this by saying if the track sizes in opposite axis are all the same size, then autofill with an intrinsic size will take that size and use it to calculate an intrinsic size for all items in the grid, and repeat that for all tracks
<TabAtkins> fantasai: If there's more than one track size, like author is alternating 500px and auto row heights, then the repetition is just 1
<TabAtkins> fantasai: Functionally disabling the auto repeat, but it's predictable
<TabAtkins> iank_: I don't think that works
<TabAtkins> iank_: If the columns are auto, you still might place something in a particular area that'll increase a particular column by a large amount
<TabAtkins> iank_: And the inline size you use for calculating the intrinsic block size is again very different
<TabAtkins> fantasai: Elaborate?
<TabAtkins> fantasai: Rows are auto-fill, columns are all auto
<TabAtkins> iank_: And you may place one item with a large minimum size in the first column, so all the column will end up different sizes
<TabAtkins> iank_: The inline size you use... you can't tak that into account when determining intrinsic block.
<TabAtkins> iank_: So you'll end up with a bunch of free space
<TabAtkins> Rossen_: Think we should go back to issue

@ethanjv
Copy link

ethanjv commented Dec 11, 2023

Following @bfgeek comment, masonry is very straightforward in how to compute the containing block for items and works fine for its use case of "measure first, place later". One of the tricky cases I was evaluating for masonry is having orthogonal items:

  • The intrinsic size of an orthogonal item in the grid axis might rely on its available size in the masonry axis, but the masonry spec is very clear that the available size in the masonry axis is taken from the container size, then its contribution size is independent of its placement (or stable as Ian commented).
  • On the other hand, the grid spec states that the grid area where a grid item is placed determines its containing block. This affects both, the proposed intrinsic auto-fill behavior and the track sizing algorithm for the grid axis. Also, should the intrinsic auto-fill consider what happens if the track sizing algorithm triggers a second pass?

I believe that many concepts from grid are applicable and much simpler when ported to masonry, but some are probably not going to work because placement needs to happen at different points in the algorithm for grid and masonry.

@fantasai fantasai removed the Agenda+ label Dec 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants