Re: [css3-grid] Notes from the Grid discussion

On Nov 27, 2012, at 12:11 PM, Tab Atkins Jr. wrote:

The following are notes from the grid discussion that took place between me, fantasai, Peter Linss, Rossen Atanov, and Phil Cupp last week.  We discussed three major issues with Grid and how we will resolve them in the near future: positioning (with named lines, etc.), non-positioned contents of a grid, and non-child grid items.

Positioning
=========
* We're changing from grid-row/row-span/col/col-span to grid-start/end/before/after.
* Grammar is "grid-*: offset? && [ <integer> || <string> ]", where:
    * <integer> by itself refers to the nth line, counting from the named edge
    * <string> refers to the first line of that name, counting from the named edge
    * <integer> <string> refers to the nth line of that name.
    * "offset" in the property means you start counting from the line specified by the other property in the pair, *toward* the named edge.  (Don't yet know what it means to have both properties in the pair be an offset.)

So, given a grid with a single row and the following lines:
+--+--+--+--+--+--+--+--+
|  |  |  |  |  |  |  |  |
A  B  C  A  B  C  A  B  C
|  |  |  |  |  |  |  |  |
+--+--+--+--+--+--+--+--+
(this is an 8-column grid, with 9 lines between and around the columns)

The following declarations are equivalent to the following old declarations:

grid-start: 'C'; grid-end: 'C';
==>
grid-column: 3; grid-column-span: 6;

grid-start: 'C'; grid-end: offset 'C';
==>
grid-column: 3; grid-column-span: 3;

grid-start: offset 'C'; grid-end: 'C';
==>
grid-column: 6; grid-column-span: 3;

grid-start: offset 'C'; grid-end: offset 'C';
==>
???

grid-start: 5; grid-end: 'C';
==>
grid-column: 5; grid-column-span: 4;

grid-start: 5; grid-end: offset 'C';
==>
grid-column: 5; grid-column-span: 1;

grid-start: 8; grid-end: 8;
==>
??? (invalid at computed-style time, because they describe a negative span)

grid-start: 'B' 2; grid-end: offset 1;
==>
grid-column: 5; grid-column-span: 1;

A note - it makes a lot of sense, I think, for grid-end/after to count from the end/after when doing named lines.  It seems slightly confusing, though, when using numbers.  It seems like "grid-start: 3; grid-end: 5;" should mean a cell that starts at the 3rd line and spans two columns.  Maybe the direction needs to be controllable, like with an optional "from [start | end]" clause on grid-start/end?  On the other hand, you could write the preceding as "grid-start: 3; grid-end: offset 2;" or "grid-end: 5; grid-start: offset 2;", so perhaps it's fine that you don't have an explicit ability here.

Alternately, just allow negative numbers which switch things around?  I could see, for example, a cell wanting to position itself with its start edge at the last "B" line, and spanning 1 column.  You can't do that in the current syntax, but with negative numbers you could do "grid-start: 'B' -1; grid-end: offset 1;".  With the keywords, it would be "grid-start: 'B' from end; grid-end: offset 1;".

Template areas will create four named lines each, with the lines named "foo-start", where "foo" is the name of the area.

fantasai believes that auto placement may be complex when using named lines.  fantasai, could you elaborate?

I believe I see a problem with auto placement, but it's not related to named lines, rather the practice of counting from the end/after side.

Julien Chaffraix mentioned this in an earlier thread. What happens when additional grid lines are generated as a result of auto placement? For example:

div {
  display: grid;
  grid-definition-columns: 100pt 100pt;
  grid-definition-rows: auto auto;
  grid-auto-flow: columns;
}

#item1 {  /* occupies entire first row(*) */
  grid-before: 1;
  grid-after: 1; /* last vertical line */
  grid-start: 1;
  grid-end: offset 1;
}
#item2 {  /* occupies first column of second row */
  grid-before: 1;
  grid-after: offset 1;
  grid-start: 2;
  grid-end: offset 1;
}
#item3 { /* occupies second column of second row */
  grid-before: 2;
  grid-after: offset 1;
  grid-start: 2;
  grid-end: offset 1;
}
#item4 {
  grid-before: auto;
  grid-after: offset 1;
  grid-start: auto;
  grid-end: offset 1;
}

Now, where does #item4 go? The grid is initially defined with two rows and two columns, and all are filled. The auto placement algorithm will not find an available space for #item4 and generate an additional column. Once this is done, #item1 will then have to change from spanning two columns to spanning three columns, leaving an empty cell in the third column, second row, #item4 can go there.

Ok, but what if #item3 were defined as:
#item3 { /* occupies second column of second row */
  grid-before: 2;
  grid-after: 1; /* last vertical line */
  grid-start: 2;
  grid-end: offset 1;
}

Now, every time the auto placement algorithm adds a column, both #item1 and #item3 expand to consume all the newly created space.

I believe having to go back and re-adjust where items live in the grid as a result of adding a column (or row) during auto placement didn't have to happen in the earlier model (but that model lacked any kind of placement from the after/end edges which is quite powerful).

I see four ways to resolve this:
1) don't allow counting grid lines from the after/end edges
2) don't move already placed grid items at all as a result of adding columns/rows during auto placement - this would leave #item1 and #item3's after edges in the second column, and place #item4 in column 3, row 1
3) recompute all item's placement when adding a row/column, but put the auto placed item that caused the grid to grow in the first generated position regardless if it's already occupied - this would have #item1 grow to cover 3 columns but put #item4 overlapping in the third column
4) recompute all item's placement when adding a row/column and detect the race condition, falling back to option 2 or 3 only when adding a row/column didn't create any available spots, or perhaps some other fallback behavior?

Option 1 sucks because you lose the power of placing items relative to the after/end edges.
The scary part of option 2 (or 4 when falling back to 2) is that you'll have grid items whose placement doesn't match their definition. ie: the grid-after: 1; will compute to grid-after: 2;. This state will have to be maintained so that further dynamic changes to the grid don't cause them to be recomputed, except when they should…
Option 3 has the obvious problem of overlapping grid items as a result of auto placement, which auto placement would be intended to avoid in the first place.

Peter

(*) I'm writing this with the row/column language rather than a line-centric language only to match the wording in the current draft. I could have easily been referring to vertical and horizontal lines rather then columns and rows, as would be my preference.

Received on Tuesday, 27 November 2012 21:11:23 UTC