Open bramdoppen opened 3 years ago
What you can do right now is define your grid differently when one of the elements is not in the DOM or not displayed.
In your example this means to only specify the "picture"
and "content"
areas and only two grid-template-rows
.
Another solution for this would be allowing to define different gap sizes as discussed in #1659.
Besides those two approaches, I think a general solution for this would be to have a way to control whether to collapse gaps adjacent to empty grid tracks - something like a gap-collapse
property with the values none
and adjacent
.
Sebastian
I suspect we can't do it by default at this point anymore, but collapsing gaps seems like a good way to go here. We kinda do it already for auto-fit
repeats. Might make more sense to take the same values as border-collapse
though. :)
@matspalmgren Thoughts?
@SebastianZ Thanks for your reply!
Allowing to define different gap sizes would be awesome, but it would not be a perfect solution for this issue.
Something like a gap-collapse
property would solve this issue and it will be a gread addition to grid!
@bramdoppen maybe you found some new workaround? To have multiple css classes with different grid-template-areas
when you have a lot of blocks and any block can be removed from page, it is a pain.
Collapsing gaps came up again today, where an author added position: absolute
to empty grid cells to achieve exactly that (demo).
Would be nice if there was a property to control this, as already hinted above by @bramdoppen.
@bramus Thanks for bringing this to my attention again. I'm blown away by the position: absolute; solution. Didn't thought that that would work. But still, it would be nice if there was an option to control this. Any thoughts on this @fantasai @SebastianZ
@bramdoppen Adding display: none;
to :empty
cells also works, but it was pointed out to me that this can causes issues when you need it to be an aria-live region.
But still, it would be nice if there was an option to control this. Any thoughts on this @fantasai @SebastianZ
Well, I already threw in my idea of a gap-collapse
property. And it seems everyone here in this thread is positive about adding this feature. So I'll bring it to the agenda.
Sebastian
In this thread I just see references to collapsing gaps, but the current spec only has this concept for the gutters of a collapsed track.
It's not clear to me what this proposal would do if the track is defined to be e.g. 100px
. I don't think it makes much sense to collapse gaps if the track won't end up being zero. But it gets tricky because e.g. an auto
track sizing function may end up producing a 0px track, or something bigger, and we don't know until the end of the track sizing algorithm, but the track sizing algo needs to know which gutters are collapsing.
I guess it could be restricted to collapsing the gutters adjacent to empty tracks whose min track sizing function is either a fixed 0px
or intrinsic, and whose max track sizing function is 0px
or intrinsic but not auto
.
But I think it would be simpler to reuse the existing concept, and instead of adding a feature to only collapse gutters, add a feature to collapse empty tracks (and the adjacent gutters will collapse too).
Like empty-tracks: collapse | auto
, where collapse
(or maybe hide
to align with empty-cells
?) would collapse all empty tracks, and auto
would only collapse the empty tracks generated by an auto-fit
repetition.
In this thread I just see references to collapsing gaps, but the current spec only has this concept for the gutters of a collapsed track.
It's not clear to me what this proposal would do if the track is defined to be e.g.
100px
. I don't think it makes much sense to collapse gaps if the track won't end up being zero.
I agree. That's what I meant when I wrote "have a way to control whether to collapse gaps adjacent to empty grid tracks" but that wording was obviously ambiguous.
But I think it would be simpler to reuse the existing concept, and instead of adding a feature to only collapse gutters, add a feature to collapse empty tracks (and the adjacent gutters will collapse too).
Like
empty-tracks: collapse | auto
, wherecollapse
(or maybehide
to align withempty-cells
?) would collapse all empty tracks, andauto
would only collapse the empty tracks generated by anauto-fit
repetition.
That probably covers a lot of use cases. Though I also have an example in which this wouldn't work:
In that widget, the image on the left spans across all grid rows, so they are not empty. The contents on the right are placed in individual grid cells. The rows are defined as 1fr repeat(4, min-content) 1fr
. So one of the cells on the right is not filled. This gets obvious when a row-gap
is added:
In this case, it would make sense to collapse the adjacent gaps plus the 0-width track to always keep the contents on the right vertically centered.
So the two cases, empty and 0-width should be controllable. Not sure whether they should be handled individually or together. Though I agree that this new feature should affect collapsing both tracks and gutters.
Sebastian
I think this issue needs a more concrete proposal before it's useful to bring it up to the WG.
My proposal in https://github.com/w3c/csswg-drafts/issues/5813#issuecomment-1679417870 is quite concrete: just add a property that controls whether empty tracks should collapse. The concept of collapsing a track is already defined in the spec, so no need to invent anything complicated.
I think it's fine that it doesn't cover Sebastian's testcase, since that would probably be better addressed with a nested grid anyways.
Would be amazing to make some progress on this. I've found it really difficult to use CSS grid for complex layouts with optional slots because the gaps between columns/rows do not collapse when the adjacent column/row is otherwise unused. Usually we have to go back to using manual margins on children so that when they are not there the gaps collapse, but this has other problems that were originally solved by gaps. Another solution is to not use grid at all and to use flex instead, but this requires additional DOM wrappers that can be hard to insert in the right places (especially with responsive layouts where children move to different slots depending on the screen size).
What is missing for this to be discussed? I think the above proposal for gap-collapse
would work. The behavior would be to merge multiple adjacent gaps into a single one, similar to what border-collapse
does in tables.
Given that everybody is positive about adding this feature and @Loirooriol's proposal, I think we're in a good position to get a resolution on this.
I think the main point for discussion is whether we can and should include the use case I previously outlined in the algorithm.
The other thing is bikeshedding the name and values. There was a lot of positive feedback on my initial proposal on a gap-collapse
property. Though I get @Loirooriol's point that this also covers collapsing tracks and not just gutters.
Sebastian
I am assuming this was not discussed in yesterday’s meeting?
I think we should try for an auto
behavior that could be enabled by default on a website (ideally, if Web-compat allows it, as the initial value). It seems unlikely that people want empty zero-sized tracks to contribute gaps, so it would be a better default behavior to collapse the gaps on such tracks.
Suggestion is values show | hide | auto
where hide
collapses empty tracks regardless of their size and auto
collapses an empty grid track (merges the gaps on either side) if:
auto
OR content alignment is not stretch/normal OR there's a flexible track (i.e. this empty track can't absorb extra space)For grid a track is empty if:
For masonry the track is empty if
@SebastianZ I think it makes sense to address the case you outlined with spanners; it doesn't seem unusual at all. To do that, we need to know which of the various tracks to collapse if all the spanned tracks are otherwise empty: do we prioritize keeping the first track? the largest track? the track with the most items (unless there's a tie, then what)?
@SebastianZ I think it makes sense to address the case you outlined with spanners; it doesn't seem unusual at all. To do that, we need to know which of the various tracks to collapse if all the spanned tracks are otherwise empty: do we prioritize keeping the first track? the largest track? the track with the most items (unless there's a tie, then what)?
Do we need prioritization? I assumed, it would be sufficient to extend the track sizing algorithm to say that all spanned tracks that end up being zero-width will be collapsed.
Sebastian
@SebastianZ We need to know which tracks collapse before the track sizing algorithm (since the presence of gaps affects the result of the track sizing algorithm).
What would be a best guest timeline on this being generally available across major browsers or through polyfills? This would allow for a truly flexible grid where all items could be optional and move independently
@Loirooriol Right, but the track sizing algorithm is already run twice for row and column sizes in the grid sizing algorithm. So we could say that in steps 3 and 4 we base re-resolving the sizes and collapsing gaps on whether the tracks are zero-width at that point.
@sir-captainmorgan21 This issue is still being discussed and there is no resolution yet. So it is way too early to predict when this will be available in any browser, let alone in all of them.
Sebastian
@SebastianZ I think I agree with @Loirooriol that we should determine which tracks to collapse before doing track sizing.
I guess one solution would be that we keep the track(s) with the most items in it (i.e. keep both if there's a tie). I think that does a reasonable job of handling most spanning relationships?
@fantasai I'm not sure if extra complexity of the auto
value is really worth it, but not opposed.
minimum size is zero or content-based
What exactly is "zero"? Just 0px
? What about 0%
with a definite grid container size, that's probably zero too? What about a 100%
that resolves against 0px
? What about an indefinite percentage, do we treat it as auto
during intrinsic sizing (so typically not collapsing tracks due to the stretching) and then collapse tracks if the percentage resolves to 0px when laying out for real? Or if not stretching auto
, we collapse percentage tracks during intrinsic sizing but not when laying out for real if the percentage resolves to a positive length? That could easily lead to overflow.
no auto-placed tracks at all
Why is this needed?
we need to know which of the various tracks to collapse if all the spanned tracks are otherwise empty
I'm not sure if I follow. In @SebastianZ's example, not all of the spanned rows are otherwise (ignoring the image) empty.
@SebastianZ I would prefer to avoid extra passes of the sizing algorithm.
@SebastianZ I would prefer to avoid extra passes of the sizing algorithm.
I am imagining only an extra step (which is necessary in any case we want to solve this), not an extra pass. Maybe this check could actually be part of the grid sizing algorithm, right after step 2. So the track sizing algorithm already ran once for rows and columns.
And regarding "zero", I'd expect this to include any track that does not take up any space at that point, independent of whether that's 0px
or 0%
.
Sebastian
What exactly is "zero"? Just 0px? What about 0% with a definite grid container size, that's probably zero too?
I think for simplicity, it might be best to just take zero lengths here.
Why is this needed?
Because in masonry layout, auto-placed items contribute sizing to every track.
I'm not sure if I follow. In @SebastianZ's example, not all of the spanned rows are otherwise (ignoring the image) empty.
Yes, but if they were otherwise empty, then we need to figure out what to do.
If I understand it correctly, the proposal to handle spanning items, is that:
empty-tracks: hide
, we collapse tracks not marked as filled by some item. For empty-tracks: auto
there are more conditions on the track sizing functions.So for example, if item A spans tracks 1-5, item B spans tracks 1-5, item C spans tracks 3-7, and item D spans tracks 6-8
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|
A | A | A | A | A | |||
B | B | B | B | B | |||
C | C | C | C | C | |||
D | D | D |
Then A,B,C mark tracks 3-5 as filled, and D marks tracks 6-7 as filled. So we collapse tracks 1-2 and 8. Is that right?
@Loirooriol It's hard for me to imagine how the algorithm should work in that case given your example. Therefore, I've created a few Codepens using your example. Based on them, I'll describe what I'd expect regarding collapsing.
Collection: https://codepen.io/collection/RzMBaZ
repeat(8, min-content)
https://codepen.io/SebastianZ1983/pen/vYqrEJr
Tracks and gaps should collapse so that the result is the same as if gap
weren't set.
repeat(4, 100px min-content)
https://codepen.io/SebastianZ1983/pen/XWLYJZM
Tracks 2, 4, 6, and 8 should collapse.
repeat(2, max-content 100px min-content 50px)
https://codepen.io/SebastianZ1983/pen/wvLXBXV
Tracks 1, 3, 5, and 7 should collapse.
200px 1fr 1fr repeat(5, 100px)
with restricted container widthhttps://codepen.io/SebastianZ1983/pen/ExBRadw
Tracks 2 and 3 should collapse.
I'll add more examples and their expected outcome on demand.
If I understand the hide
value correctly, it behaves the same as auto
but also collapses empty tracks regardless of their size. If so, I wonder if this has any use cases and if this shouldn't be discussed separately, as the use cases outlined so far refer to zero-width tracks.
Sebastian
@SebastianZ Note I'm not proposing that algorithm, it's just my guess of what fantasai might have in mind.
Tracks 2, 4, 6, and 8 should collapse.
I think fantasai's idea wouldn't collapse 4 as per "we keep the track(s) with the most items in it (i.e. keep both if there's a tie)".
Tracks 1, 3, 5, and 7 should collapse.
Ditto for 3,5.
Tracks 2 and 3 should collapse.
A priori we don't know if the 1fr will have any free space to grow, so this would need multiple passes of the track sizing algorithm, which I don't like.
If so, I wonder if this has any use cases and if this shouldn't be discussed separately, as the use cases outlined so far refer to zero-width tracks.
The original use case at the top of this issue is about having tracks for optional elements that may or might not exist. Thus hide
is a much more straightforward way to achieve this. On the opposite, I'm still not super convinced that the complexity of auto
is actually worth it. The only use case that I have seen is your spanning case, which it seems that could be addressed with a nested grid.
If I understand it correctly, the proposal to handle spanning items, is that [...]
@Loirooriol Yes, that's a great example.
repeat(8, min-content) Tracks and gaps should collapse so that the result is the same as if gap weren't set.
I think you are wrong here @SebastianZ. If you requested gaps, then we must put one at least between 5/6.
repeat(4, 100px min-content) Tracks 2, 4, 6, and 8 should collapse.
What if track 7 doesn't have enough space for item D? I think we would want to avoid automatically creating overflow, especially since the author's specified design avoids such overflow.
200px 1fr 1fr repeat(5, 100px) with restricted container width Tracks 2 and 3 should collapse.
I agree strongly with @Loirooriol that we should not make track collapsing depend on the available space. If nothing else, it creates a discontinuity.
Thanks @Loirooriol and @SebastianZ for all the examples.
@SebastianZ Note I'm not proposing that algorithm, it's just my guess of what fantasai might have in mind.
And the expectations I posted were not an interpretation of fantasai's algorithm but what I'd expect as an author.
Tracks 2, 4, 6, and 8 should collapse.
I think fantasai's idea wouldn't collapse 4 as per "we keep the track(s) with the most items in it (i.e. keep both if there's a tie)".
That's what I understood as well, though again, in the examples I thought of an author's perspective, not about the proposed algorithm.
Tracks 2 and 3 should collapse.
A priori we don't know if the 1fr will have any free space to grow, so this would need multiple passes of the track sizing algorithm, which I don't like.
Again, not multiple passes. My suggestion was to choose the tracks to collapse after the first pass instead of before as suggested by you and fantasai. At that point we should know whether the 1fr resulted in zero-width tracks. But you both know the algorithm better than me, so maybe you can clarify why it's a bad idea to choose them afterwards.
If so, I wonder if this has any use cases and if this shouldn't be discussed separately, as the use cases outlined so far refer to zero-width tracks.
The original use case at the top of this issue is about having tracks for optional elements that may or might not exist. Thus
hide
is a much more straightforward way to achieve this.
I think I misunderstood hide
initially. I thought it would be based on auto
but disregard the track sizes. After re-reading, hide
only targets completely empty tracks, so disregards any spanned-over tracks and zero-width logic. So it targets the use case outlined in the first comment.
On the opposite, I'm still not super convinced that the complexity of
auto
is actually worth it. The only use case that I have seen is your spanning case, which it seems that could be addressed with a nested grid.
There are different ways to achieve this right now for my use case. Nesting grids, though that also requires nested DOM structures. Or :has()
can be used with different grid-template
definitions, which also solves the use case of comment 0. Both approaches are much more cumbersome to write than an empty-tracks: auto
, especially if web compatibility allows to make this the default as suggested by @fantasai.
repeat(8, min-content) Tracks and gaps should collapse so that the result is the same as if gap weren't set.
I think you are wrong here @SebastianZ. If you requested gaps, then we must put one at least between 5/6.
Based on your algorithm, yes. Based on author intention, it's unclear.
Though I'd also note that a grid with only spanning items which overlap in several tracks, is an edge case.
repeat(4, 100px min-content) Tracks 2, 4, 6, and 8 should collapse.
What if track 7 doesn't have enough space for item D? I think we would want to avoid automatically creating overflow, especially since the author's specified design avoids such overflow.
So if item D is wider than track 7, tracks 6 and 8 are non-zero-width, and therefore don't collapse.
200px 1fr 1fr repeat(5, 100px) with restricted container width Tracks 2 and 3 should collapse.
I agree strongly with @Loirooriol that we should not make track collapsing depend on the available space. If nothing else, it creates a discontinuity.
I'd argue that this is similar to the min-content
cases, at least in my understanding of how the algorithm could handle this.
Though I get your point about discontinuity, as tracks may collapse or not depending on the available space.
Sebastian
So, to summarize where we are right now:
We agree on adding a way to collapse grid gaps on completely empty tracks. (proposal empty-tracks: hide
)
We have two proposed solutions for also collapsing spanned-over tracks in addition to empty tracks. (proposal empty-tracks: auto
)
@Loirooriol expressed some concerns regarding the complexity of option 1 and therefore questioned whether it's worth to add this feature.
@fantasai and @Loirooriol expressed concerns regarding discontinuity issues caused by option 2.
Sebastian
Consider a grid with two minmax(auto, max-content)
columns, one small item in the 1st column, and a 2nd big item spanning both columns.
Currently, the algorithm will size the 1st column tightly around the 1st item, and the remaining size of the 2nd item will be accommodated by the 2nd column.
With fantasai's proposal of spanning items and empty-tracks: auto
by default, then we would collapse the 2nd track, so the 1st column will grow to accommodate both items. I don't think this would be web compatible.
Even if empty-tracks: auto
isn't the default, I'm not convinced that collapsing the 2nd track is desirable.
Maybe this check could actually be part of the grid sizing algorithm, right after step 2.
Steps 3 and 4 are only needed when there are things like aspect ratios or orthogonal flows, with this they would need to run more frequently.
My proposal to move this forward is just adding empty-tracks: hide
(or collapse
?) for the moment, which will collapse all empty tracks regardless of their track sizing function. Tracks containing spanning items are never considered empty.
This should address the original usecase, and be simple to spec and implement (since we are already doing that for auto-fit
repetitions).
Then open other issue(s) about new value(s) to only collapse when the track would be guaranteed to be 0px, and to consider tracks containing spanning items as empty in some cases.
Hi all! Love the work you do, but there is one thing that I would like to mention here: grid-gaps that are still taking up space when element is not in the DOM.
It works when all elements are present Everything is fine here. Nice gaps between elements.
The issue: When the last element (the filter) is removed from the page (but is still defined in the grid-template-area) the row-gap is still taking up space.
Would be great if css grid would not add those row-gaps in the future. Did some research but there is no rock-solid workaround that I can use right now, or am I missing something?