The definition for grid spans says:
How many grid tracks the grid item occupies. A grid item鈥檚 grid span is always _definite_, defaulting to 1 if it can鈥檛 be otherwise determined.
Though there are use cases, for which an indefinite span size (up to the border of the grid) is desired.
Example:
Grid with two columns and a varying number of items with the first item being the row number spanning over all grid rows.
CSS:
.row {
display: grid;
grid-template-columns: 50px 1fr 1fr;
}
.rowNumber {
grid-row-end: span 2; /* <-- Grid cell should span to the end of the grid, not have a fixed value. */
}
HTML:
<div class="row">
<div class="rowNumber">1</div>
<div>a</div>
<div>b</div>
<div>c</div>
...
</div>
I'd expect to have start
and end
keywords for this case, so I can write grid-row-end: span end
and the spanning of the grid cell to dynamically adjust up to the end of the grid.
Sebastian
You want to auto-place an item and have it span to the end of the grid no matter what slot it's in?? For what purpose?
In my use case they are always in the left-most grid track. Other use cases may span over all (or some) columns of the grid up to the grid row end to build some kind of heading area.
Sure, my example may also be achieved by wrapping the items within another element, but I think allowing grid tracks to span up to the edge of the grid is obvious.
Sebastian
That's doable anyway - set the appropriate -end
property to -1, and it'll go to the end.
For the actually-useful case of "fill the grid regardless of how many columns it has", you can write grid-column: 1 / -1
;
That's doable anyway - set the appropriate
-end
property to -1, and it'll go to the end.
If that worked, it would be great, but it only works for an explicit grid, right? In my use case there are no explicit track rows defined, because they vary depending on the number of items.
Sebastian
I think you need to nest grids here. I suspect in many cases the markup will lend itself to that anyway.
I'm also in need of this capability. In my case there are a variable number of items laid out in an implicitly defined grid using auto-fit with minmax(). The result is a variable number of rows and columns (the latter varying with screen size), with items generally being auto-placed within them.
The problem is the last item on the last row; I would like to span it to fill any "spare" space, but I don't know beforehand which column it will be in, nor how many columns it will need to span. I had hoped that something like one of the following would work, where "end-line" is a named line:
grid-column: auto / span -1;
grid-column auto / span end-line;
I think it should be possible to specify that an item should have its start column set automatically, but then span to a particular end location (assuming the end column is to the right of the automatic start column). It's really just a variation on setting a fixed span, but where the value is dynamically calculated as "named-end-column minus computed-start-column" rather than being hard-coded.
Yeah, that's not possible right now. It would require some special handling in the auto-placement algorithm to indicate that it wants to fill to some particular end-line; the logic definitely isn't hard, but it's also definitely not handled right now.
It would require some special syntax in grid-column, since grid-column: auto / span end-line;
is identical to just grid-column-end: end-line;
, and will result in an explicit-column item with a span of 1.
Fwiw, I explored this a bit by implementing the placement part in Gecko. Here's the algorithm I used:
Assume we have grid-column/row: auto / <thing>
cursor
to zeroauto / span 1
instead (i.e. find the next unoccupied slot)START
<thing>
to a line as if the declaration had been START / <thing>
cursor
by 1 and go to step 2.This allows you to auto-place an item with an arbitrary fixed line on the other side, or span to an arbitrary line. So, for example:
auto / auto(-1)
: auto-place the item and then set the end to the last line of the explicit gridauto / auto(-2)
: auto-place the item and then set the end to the next-to-last line of the explicit gridauto / auto(A 2)
: auto-place the item and then set the end to the second "A" line in the gridauto / auto(span A)
: auto-place the item and then set the end to the next "A" line from that pointThe above was fairly trivial to implement since most of the needed primitives already exist.
I had a few other ideas while exploring this... :-)
It might also be useful to be able to specify a min/max constraint on the span length since it's hard to predict how many tracks the item will span. For example:
<div class="grid" style="grid-template-columns: repeat(5,20px) [b];">
<span style="grid-row:1; grid-column: 1 / span 4"></span>
<span style="grid-row:auto; grid-column: auto / auto(span b)"></span>
</div>
This will place the 2nd item as grid-column: 5 / 6
. But with a minimum span of two tracks:
grid-column: auto / auto(span b) span-min(2);
it would instead be placed on the next row and span all columns.
... similarly, adding a span max-constraint:
grid-column: auto / auto(span b) span-minmax(2, 3);
it would be placed on the next row but only occupy column 1 to 3.
If the grid-row
instead is definite for the 2nd item:
grid-row: 1;
grid-column: auto / auto(span b) span-min(2);
it would be placed at line 5 with a span of 2 and thus generate an implicit 6th column.
It would also be fairly easy to skip the "is this grid area unoccupied" check that is the default behavior for all grid auto-placement currently, for example:
<div class="grid" style="grid-template-columns: repeat(5,20px);">
<span style="grid-column: 1"></span>
<span style="grid-column: 3"></span>
<span style="grid-row:auto; grid-column: auto / auto(-1)"></span>
</div>
This would normally place the third item as grid-column: 4 / 6
, since placing it in the unoccupied 2nd column and spanning from there to the last line isn't allowed because it would overlap the 2nd item. We could easily skip that check, for example:
grid-column: auto / auto(-1) may-overlap;
this would be equivalent to grid-column: 2 / -1
(although it would occur in the auto-placement phase)
It would also be nice to have a fill feature to make an item fill empty grid areas as much as possible, for example:
<div class="grid" style="grid-template-columns: repeat(5,20px);">
<span style="grid-column: 1"></span>
<span style="grid-column: 4"></span>
<span style="grid-column: auto / span(fill)"></span>
</div>
which would result in grid-column: 2 / 4
.
It should also be possible to fill non-auto-placed items:
<div class="grid" style="grid-template-columns: repeat(5,20px);">
<span style="grid-column: 1"></span>
<span style="grid-column: 5"></span>
<span style="grid-column: 3 / span(fill)"></span>
</div>
This would make the third item have grid-column: 3 / 5
.
It might also be nice to have min/max line constraints on the auto-position, for example:
<div class="grid" style="grid-template-columns: repeat(5,[a] 20px);">
<span style="grid-column: 1"></span>
<span style="grid-row:auto; grid-column: auto min(a 3) / span(fill) max(4)"></span>
</div>
Here we would normally place the 2nd item in column 2, but since the author specified line 3 as the minimum we try line 3 and then fill it from there - this would result in grid-column: 3 / 6
but this is constrained by the max end line 4 so we get grid-column: 3 / 4
.
We might also want to disallow the range from wrapping around when end <= start, for example:
<div class="grid" style="grid-template-columns: [a] 20px [b] repeat(4,20px);">
<span style="grid-column: 1 / span 2"></span>
<span style="grid-row:auto; grid-column: auto / auto(b) forward"></span>
</div>
which would resolve to grid-column: 3 / 2
but since we disallowed the range from wrapping this is rejected and we move to the next row and instead resolve to grid-column: 1 / 2
All these new features should be possible to combine and should apply also to existing placement features.
I believe all of the above should be fairly easy to implement in the placement code.
I've created an example using JavaScript to adjust the spanning of an element. This example doesn't cover all different cases (like e.g. having multiple indefinite spans or having a column flow), though it allows to adjust the placement of the spanning element, how many column tracks it spans, and a few other things.
Sebastian
The span-minmax(2, 3)
proposal solves the use-case I run into most often:
auto-fit
/auto-fill
repeating grid-columnsCurrently, that requires an explicit media-query to change grid-column-end
at the proper widths 鈥撀燼nd some math to calculate that proper width. I was imagining something like span-available 3
- but span-minmax()
provides even more control and flexibility.
span-minmax(1, 3)
would also allow the grid to be fully responsive when using something like grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
. Right now, if you have anything spanning N columns, as soon as you resize the grid so less than N columns fit, the last column will overflow the grid (as in this SO question) or the following example:
Most helpful comment
Fwiw, I explored this a bit by implementing the placement part in Gecko. Here's the algorithm I used:
Assume we have
grid-column/row: auto / <thing>
cursor
to zeroauto / span 1
instead (i.e. find the next unoccupied slot)with the constraint that line > cursor, call this line number
START
<thing>
to a line as if the declaration had beenSTART / <thing>
if so, these are the lines to use and we're done
cursor
by 1 and go to step 2.This allows you to auto-place an item with an arbitrary fixed line on the other side, or span to an arbitrary line. So, for example:
auto / auto(-1)
: auto-place the item and then set the end to the last line of the explicit gridauto / auto(-2)
: auto-place the item and then set the end to the next-to-last line of the explicit gridauto / auto(A 2)
: auto-place the item and then set the end to the second "A" line in the gridauto / auto(span A)
: auto-place the item and then set the end to the next "A" line from that pointThe above was fairly trivial to implement since most of the needed primitives already exist.
I had a few other ideas while exploring this... :-)
It might also be useful to be able to specify a min/max constraint on the span length since it's hard to predict how many tracks the item will span. For example:
This will place the 2nd item as
grid-column: 5 / 6
. But with a minimum span of two tracks:it would instead be placed on the next row and span all columns.
... similarly, adding a span max-constraint:
it would be placed on the next row but only occupy column 1 to 3.
If the
grid-row
instead is definite for the 2nd item:it would be placed at line 5 with a span of 2 and thus generate an implicit 6th column.
It would also be fairly easy to skip the "is this grid area unoccupied" check that is the default behavior for all grid auto-placement currently, for example:
This would normally place the third item as
grid-column: 4 / 6
, since placing it in the unoccupied 2nd column and spanning from there to the last line isn't allowed because it would overlap the 2nd item. We could easily skip that check, for example:this would be equivalent to
grid-column: 2 / -1
(although it would occur in the auto-placement phase)It would also be nice to have a fill feature to make an item fill empty grid areas as much as possible, for example:
which would result in
grid-column: 2 / 4
.It should also be possible to fill non-auto-placed items:
This would make the third item have
grid-column: 3 / 5
.It might also be nice to have min/max line constraints on the auto-position, for example:
Here we would normally place the 2nd item in column 2, but since the author specified line 3 as the minimum we try line 3 and then fill it from there - this would result in
grid-column: 3 / 6
but this is constrained by the max end line 4 so we getgrid-column: 3 / 4
.We might also want to disallow the range from wrapping around when end <= start, for example:
which would resolve to
grid-column: 3 / 2
but since we disallowed the range from wrapping this is rejected and we move to the next row and instead resolve togrid-column: 1 / 2
All these new features should be possible to combine and should apply also to existing placement features.
I believe all of the above should be fairly easy to implement in the placement code.