Closed bfgeek closed 8 months ago
Thinking about it, I think you're right, that these keywords should be defined over all the masonry items (including those ending up in other tracks). Using just the first row gets you reasonable results if all your items are the same size, but is prone to broken layouts if not. Better to have a little too much space in some columns than not enough.
First cut of trying to spec this...
Track sizing works the same as in CSS Grid, except that when considering which items contribute to intrinsic sizes:
In the case of spanning items with no explicit placement, they are assumed to be placed at every possible start position, and contribute accordingly.
Example 1: Suppose there are two columns in the grid axis and that
In this case, items A, B, C, and D all contribute to sizing the first column, and A, B, and C (but not D) contribute to the second column.
Example 2: Suppose there are 5 columns in the grid axis, with the middle having a fixed size of 100px and the other two being auto-sized. An item that spans 2 tracks and has an intrinsic contribution of 220px is essentially copied and assumed to exist:
Note: This algorithm ensures that each track is at least big enough to accommodate every item that is ultimately placed in it, and does not create dependency cycles between placement and track sizing. However, depending on the variation in sizes, tracks could be larger than necessary: an exact fit is only guaranteed if all items are explicitly placed in the grid axis or all items are the same size (or matching multiples of that size, in the case of spanning items).
Items are placed in order-modified document order, but items with a definite placement are placed before items with an indefinite position (as in regular grid layout).
For each of the tracks in the grid axis, keep a running position initialized to zero. First for each item with a definite placement in the grid axis, then for each item with an indefinite placement:
I don't think its that straightforward. There are lots of dependencies on placement hidden within the grid track sizing algorithm - for example (after a very quick look):
The contribution size for a grid-item isn't the same value for "all" tracks, it needs to be calculated per placement - I'm a little concerned about the performance of this approach.
My two cents: I feel that the concept of track sizing function in grid is very tied to placement happening before sizing.
To me, it feels meaningless to have a max-content
track that ends up being sized much larger than any item placed within that track. The comparison at the beginning of the spec with multi-column layout feels much more appropiate to masonry rather than grid when thinking of @fantasai latter proposal, and it pretty much ties to @bfgeek alternate proposal, where repeat(auto-fill, auto)
will do something very similar: consider the intrinsic size of all items to determine an appropiate size for a track that will automatically repeat to fill the available space.
Providing more context on @bfgeek's last point, the final position of a grid item is relevant in case it spans something like minmax(auto, 100px)
. In such scenario, if we ignore the max track sizing function (because we don't know where the item will end up being placed) we won't constraint its automatic minimum size and accommodating its unconstrained min-content
size could overflow the maximum of the track(s) in which we end up placing it.
I would argue that "The full power of grid layout is available in the grid axis" can be tricky to achieve with such approach if two completely different behaviors are expected depending on whether masonry is in the equation or not.
PS. I'm also concerned that considering all non-explicitly placed grid items in every posible start position will likely result in bad performance, that's a guaranteed quadratic algorithm.
that's a guaranteed quadratic algorithm
It's not quadratic. It's NxM where N is the number of items and M is the number of columns. And reduces to N (same as Grid, or IanK's proposal) if the columns have the same sizing function.
The CSS Working Group just discussed [css-grid-3] Masonry - Intrinsic sizing of tracks & masonry-grid doesn't produce to good/desirable results.
, and agreed to the following:
RESOLVED: Remove first-row-is-special handling of intrinsic track sizing in Masonry spec, replace with all auto-placed items contribute to all intrinsically sized tracks
It's not quadratic. It's NxM where N is the number of items and M is the number of columns. And reduces to N (same as Grid, or IanK's proposal) if the columns have the same sizing function.
If tracks have different sizing functions then it goes quadratic however.
(edit: and I think potentially when subgrid is involved - gets super complex).
that's a guaranteed quadratic algorithm
It's not quadratic. It's NxM where N is the number of items and M is the number of columns. And reduces to N (same as Grid, or IanK's proposal) if the columns have the same sizing function.
Well, computing the intrinsic contribution of grid items would be O(N) in such case, but if we completely rely on the grid track sizing algorithm as it is right now, then equally distributing such contribution to all the possible tracks it could be placed, which are all of them, makes it O(NxM) (...unless we change how the contribution of a grid item is accommodated for masonry).
Btw we might want to consider that, in the current draft of masonry, having definite tracks mixed with intrinsic tracks might result in some items overflowing the spanning tracks in the grid axis. E.g., if we have a grid-template-columns: 50px auto
definition, if we have two auto placed items, the first one with a min-content size of 100px
and the other with 50px
, the first will be placed in the first column and overflow it, then the second would be placed in the auto
track.
Maybe we want to prioritize placing a grid item in a track that won't overflow?
@ethanjv We currently don't prioritize item placement based on the resolved size of the tracks... if that's something you thin we should add, maybe open a new issue? :)
This is a somewhat meta issue surrounding the current definition of how intrinsic track sizing works, and the intrinsic sizing of the masonry grid.
As currently defined (https://drafts.csswg.org/css-grid-3/#track-sizing) the tracks that have
min-content
,max-content
,fit-content
, andauto
don't work as they do in regular grid. For most of the tracks the content based tracks will resolve to zero, and theauto
will result to1fr
?On top of this it means that an intrinsically sized masonry grid won't match developer expectations, e.g.
width: max-content
or similar (being a flex-item, grid-item, floating, etc, etc). We currently have a similar issue for multi-line flexbox which we are trying to fix, but this is somewhat worse due to being the default.There are multiple avenues to solving the above, however one would be make masonry its own display type with a reduced subset of allowable definitions for tracks. Most masonry examples I've seen choose to size all the tracks the same size. An potential path forward would to allow repeats of "intrinsic" tracks where everything gets sizing as-if it was in one track, then decide how many tracks to insert. On top of this you could additionally allow non-intrinsic tracks in combination with the repeater. E.g.
masonry-tracks: 100px repeat(auto-fill, minmax(min-content, 100px));
Edit - a simple example of intrinsic sizing: https://www.software.hixie.ch/utilities/js/live-dom-viewer/?saved=11094