- From: Tab Atkins Jr. <jackalmage@gmail.com>
- Date: Tue, 27 Mar 2012 17:11:57 -0700
- To: www-style list <www-style@w3.org>
The automatic item placement algorithm works very well when attempting to flow a list of items into a grid, but it fails when you want the grid to have "gutters" between the items. Here's a specific use-case. Say you have the following markup: <container> <item /> <item /> <item /> ... </container> You'd like to flow these items into a grid, 4 per row. The following style works: <style> container { display: grid; grid-columns: 1fr[4]; grid-flow: rows; } </style> The <item>s will automatically flow into the grid, filling each row completely before starting a new one. Perfect! However, if you want a gutter between the cells, as you often do, you're screwed. The naive way to define gutters is this: container { grid-columns: 1fr 10px 1fr 10px 1fr 10px 1fr; } This is a little verbose, but whatever. This works if you explicitly position things only into columns 1, 3, 5, or 7, and remember to make your "two-column" stuff actually span 3, your "three-column stuff" actually span 5, etc. However, the automatic placement algorithm will screw things up, and attempt to place 7 items per line, with three of them in the "gutter" columns. You can get around this by throwing more code at the problem: <style> container { display: grid; grid-columns: 1fr 10px 1fr 10px 1fr 10px 1fr; grid-flow: rows; } container > :nth-child(4n+1) { grid-column: 1; } container > :nth-child(4n+2) { grid-column: 3; } container > :nth-child(4n+3) { grid-column: 5; } container > :nth-child(4n+4) { grid-column: 7; } </style> But this is ugly and silly, and is *still* incompatible with gutter rows, because there's no way to tell the grid placement algorithm to "skip" rows. (You can't rely on the implicit modulus operation that got you out of the columns problem, since you need integer division instead, and even with calc() you don't have access to the element's child index.) Gutters are very common in grid systems (for example, see the very popular fluid grid in Bootstrap <http://twitter.github.com/bootstrap/scaffolding.html#fluidGridSystem>), so we should support this use-case. I suggest a "grid-gutters: <length> <length>?;" property. (Actually it would be a <track-breadth> without the keywords.) This establishes gutter columns and rows, which take part in sizing, but can't have elements placed inside of them, or be addressed directly in any way. (Basically, this is identical to the border-spacing property for tables.) This simplifies the example considerably: <style> container { display: grid; grid-columns: 1fr[4]; grid-gutter: 10px; /* column and row gutter are both 10px */ grid-flow: rows; } </style> To put something in the second column, you just say "grid-column: 2;", not "grid-column: 3;". To make it span 3 columns, you say "grid-column-span: 3;", not "grid-column-span: 5;". Etc. We're back in the simple situation we had originally, but now we have gutters separating the cells. Grid lines gain a slight wrinkle now, since grid cells are no longer necessarily touching. This can be easily and reasonably addressed, though - the grid line still refers to the edges of the two surrounding cells, and the "correct" cell is chosen automatically. If a grid line name is provided as the first token to grid-position, it refers to the start/before edge of the cell *following* the grid line. If it's provided as the second token, it refers to the end/after edge of the cell *preceding* the grid line. (If this sounds confusing, don't worry - it's definitely the obvious solution unless you really, for some strange reason, want to position an item so that it expands into a gutter. In practice, nobody really wants to do this.) As a practical application, with this change Twitter Bootstrap could change its fluid grids to the following: .row-fluid { display: grid; grid-columns: 3fr[12]; grid-gutter: 1fr; grid-flow: rows; } .span1 { grid-column-span: 1; } .span2 { grid-column-span: 2; } .span3 { grid-column-span: 3; } ... .span12 { grid-column-span: 12; } They can't yet replicate their ".offsetX" classes, but I don't think those are necessary - it seems like they exist only because they don't have the ability to specify exactly which column something should go in, so they use offsets to simulate this. Grid appears to solve this problem adequately already. ~TJ
Received on Wednesday, 28 March 2012 00:12:45 UTC