[css-grid-3][masonry] Handling negative margins and dense packing for baseline calculation in the masonry axis
Following up on #9530 , a key question arises when working in the container level baseline in the masonry axis: How should cases be handled where an item is moved to a higher position within the container either via negative margins or via dense packing? Specifically, how should such an item be considered in the container-level baseline calculation?
Example Scenario:
Consider the following cases:
Example 1:
Item 1 has a negative margin-bottom, causing Item 3 to be positioned above it. Should Item 1 or Item 3 be treated as the first baseline in the track? If it’s based on the order items are placed in, it would be Item 1. If it’s based on where they are positioned, it would be Item 3. Note that in a multicolumn layout, Item 1 is treated as the first baseline in the track, based on the order in which items are placed.
Example 2:
- Without dense packing, Item 2 is the first baseline candidate in tracks 2 and 3.
- With dense packing, Item 3 is placed above Item 2. In this case, which should be the first baseline candidate in track 3: Item 3 or Item 2? If it’s based on the order items are placed in, it would be Item 2. If it’s based on where they are positioned, it would be Item 3.
Example 3:
- Item 5 has a negative margin-top.
- Without dense packing, Item 2 would serve as the first baseline candidate in this track.
- With dense packing, however, Item 5 is repositioned above Item 2 due to its negative margin.
This raises the question: Should Item 5 now be treated as the first baseline candidate in this track?
Approaches to Handling Dense Packing and Baseline Calculation
1. Ignore cases involving dense packing
One approach is to disregard situations involving dense packing. For example, when calculating the first baseline, if a later item is moved to an earlier position and becomes the first item in a track, this item would still be considered lower than the first items in other tracks. In other words, first baseline candidates are determined by the order items are placed in rather than where in the track they are placed. The same approach applies to last baseline calculations. If we decide to do with this approach, then that fixes the problem ran into with negative margins because instead of looking at offsets, we would now only care about the order items are processed in.
2. Do not ignore cases involving dense packing
Alternatively, two options are available if dense packing cases are not ignored:
- Option 1: Always use the visually highest or lowest item (with a usable baseline) as the first or last baseline candidate in a track. This would apply to dense packing and cases with negative margins. With this approach, item 5 in the third example above would be treated as first baseline candidate.
- Option 2: Follow the resolution of the issue regarding #13164/Effect of negative bottom margins on running position + dense-packing
A problem with ignoring dense packing (i.e. always using the last order-modified document order element) is that it could make a very simple dense packing usage produce an unintuitive baseline result.
Take an example where the web dev feeds a collection of elements in an arbitrary order, all of the same style, into a 3 column Masonry. If the order of items ends up being 2x1 (red), 1x1 (blue), 3x1 (green) we get a last-baseline that also visually matches the lowest item (green 3x1). If, however, the order of items ends up being 2x1 (red), 3x1 (green), 1x1 (blue), we get the same visual result, but a last-baseline that is unintuitively higher (blue 1x1).
If we accept that this means we should not be ignoring dense packing (eliminating Approach 1), we are still left with (at least) 2 options for how to proceed.
- Option 1 - Decide based on the item's visually rendered location
- Option 2 - Establish a "track order" similar to the "grid order" - defined as the visual order elements would be in if dense packing was enabled, but negative margins were ignored. In the above example, the "track order" for column 3 would be the 1x1 item, followed by the 3x1 item, independent of which order they appeared in the document. The first/last item would then be chosen based on this "track order", and the baseline determined from that item.
@yanlingwang23 - This Option 1 matches your Approach 2 - Option 1 above, but I'm not clear on what your above Approach 2 - Option 2 is proposing, so am not sure if this is just rephrasing your Option 2, or if that is an additional option I should be considering.
Both of these options would produce intuitive results for all the reasonable cases I have come up with, so I don't have a strong argument between them. I lean slightly towards the "track order" option, as it feels more consistent with how Grids currently behave - choosing the element to use based on an established "order", rather than based on rendered position.
Similar to the other cases, I don't think negative margins should factor into any first/last calculations. We select the first/last element based on placement, then look at where it's baseline is (which can be affected by margins/etc), and that's it.
Wrt dense packing, in Grid we care about densely-packed items the same as any other; what matters is just if they're in the first/last track, for any reason. Same thing should apply here, I believe.
That is, we rely on the placement rules (including dense packing) to determine what the first and last items placed in each track are. Then we lay out the items, and among the already-selected first/last, take the highest/lowest baselines, as needed.
This would result in:
- Example 1, using Item 1 for the first baseline. (Item 3 is placed later in track 1, so isn't consulted.)
- Example 2, using Item 3 for the 3rd column baseline. (Item 3 is densely-placed earlier in track 3 than Item 2.)
- Example 3, using Item 2 for the first baseline. (Item 5 is placed later in track 2, so isn't consulted.)
Thanks for all the responses. It makes sense to me to rely on the placement rules/track order. Here're my thoughts in determining the first/last baseline candidate within a track:
In normal cases: When an item arrives, if the related tracks do not yet have a first baseline, we use this item’s baseline as the first baseline. If a first baseline is already set, we skip this item because we know another item was placed earlier. For the last baseline, we simply override the last baseline value in the related tracks. At the end, this gives us the logically last placed item as the last baseline candidate.
For dense packing: Based on the spec stating that the running position of a track never decreases, we can rely on the running position to decide whether a densely-placed item should be treated as a first or last baseline candidate. If the running position of this densely-placed item is equal to or greater than that of the current first/last baseline candidate, then the densely-placed item is considered later in placement order.