Re: [csswg-drafts] [css-grid] Indefinite spans

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>`
1. set `cursor` to zero
2. place the item as if it were `auto / span 1` instead (i.e. find the next unoccupied slot)
   with the constraint that line > cursor, call this line number `START`
3. resolve `<thing>` to a line as if the declaration had been `START / <thing>`
4. check if this range is unoccupied using the now fully resolved lines from step 2 & 3:
   if so, these are the lines to use and we're done
5. otherwise, increment `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 grid
* `auto / auto(-2)` : auto-place the item and then set the end to the next-to-last line of the explicit grid
* `auto / auto(A 2)` : auto-place the item and then set the end to the second "A" line in the grid
* `auto / auto(span A)` : auto-place the item and then set the end to the next "A" line from that point

The 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:
```html
<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:
```css
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:
```css
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:
```css
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:
```html
<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:
```css
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:
```html
<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:
```html
<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:
```html
<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:
```html
<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.


-- 
GitHub Notification of comment by MatsPalmgren
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/388#issuecomment-304476365 using your GitHub account

Received on Saturday, 27 May 2017 21:01:30 UTC