Copyright © 2011 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
This
specification is not being actively maintained, and should not be used as
a guide for implementations. It may be revived in the future, but for now
should be considered obsolete.
If you have questions or comments on this specification, please send an
email to the CSS Working Group's mailing list at www-style@w3.org. (Before sending mail
for the first time, you have to subscribe at http://lists.w3.org/Archives/Public/www-style/.)
This module describes integration of grid-based layout (similar to the grids traditionally used in books and newspapers) with CSS sizing and positioning.
This is a member-only draft. It may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
The (archived) mailing list w3c-css-wg@w3.org is preferred for discussion of this specification.
This document was produced for the CSS Working Group (part of the Style Activity).
This is the first public working draft of this module.
This CSS3 module depends on the following other CSS3 modules:
It has non-normative (informative) references to the following other CSS3 modules:
Grid systems have provided great value to print designers for many years [THEGRID]. Now same concepts are applied to online content [SXSWGRIDS], [AGBDL]. Unlike print media however, dimensions of online devices vary broadly; a single fixed-sized grid that worked perfectly for print pages only works in a subset of web scenarios. Really adaptable solutions require dealing with a grid that adapts to fit devices of varying form factors.
This module adds capabilities for sizing and positioning in terms of a scalable grid . The grid can be specified directly by author, or can be implied from existing two-dimensional structures (tables or multi-column elements).
Grid positioning addresses layout in continuous media and in paged media.
Let's start with an illustration of grid in action.
Floats in multi-column layout
Figure 1 shows a 3-column layout in paged media. It can be seen as a grid with 6 vertical lines (at each column boundary) and horizontal lines at margins.
body { columns:3; column-gap:2em; } float1 { float:page bottom left; width:3gr; } /* Figure 1 */
The statement "float:page bottom left" positions the image at the bottom left corner of the page (as defined in [CSS3GCPM])
Property "width:3gr" makes it 3 "grid units" wide, where a "grid unit" is the distance between two adjacent grid lines. Each boundary between a column and a gap automatically produces a grid line, therefore to specify "two columns, including the gap between columns, but not including any gaps outside the columns" we can just say "3gr".
Also, in this example the author has added a horizontal line to align illustrations with. This can be done by explicitly defining grid lines:
body { columns:3; column-gap:2em; grid-rows: 1.5in 1fr; } div.illustrations { float:page top left; width:5gr; height:1gr;} float1 { float:page bottom left; width:3gr; } /* Figure 2 */
In this example, "grid-rows" divides vertical space with explicit grid lines.
"1fr" is a flex unit ('fr' for 'fraction'). If multiple flex units are used, they take space proportional to their values. If we wanted to define vertical lines that would exactly match the 3-column layout with 2em gaps we could say
grid-columns: 1fr 2em 1fr 2em 1fr;
When only one value has a 'fr' unit (as in "grid-rows: 1.5in 1fr" above), it just takes all remaining space regardless of the number.
The following example illustrates the use of a grid in construction of a complex web site (see [SXSWGRIDS] for how exactly this was built). Note how groups of elements are aligned with different sets of grid lines.
Complex site designed with a grid
There are two ways to define a grid.
Grid lines can be defined in terms of rows and columns. Rows are always horizontal and columns are always vertical (this doesn't change in vertical writing modes)
grid-columns
’ and ‘grid-rows
’
propertiesName: | grid-columns |
Value: | [[<length>|<percentage>|<fraction>] | repeat([<length>|<percentage>|<fraction> ]+)]+ | none | inherit |
Initial: | none |
Applies to: | non-replaced block-level elements |
Inherited: | no |
Percentages: | refer to width of the block |
Media: | visual, paged |
Computed value: | specified value |
Name: | grid-rows |
Value: | [[<length>|<percentage>|<fraction>] | ([<length>|<percentage>|<fraction> ]+)[‘ [ ’<integer>‘] ’]? ]+ | none | inherit |
Initial: | none |
Applies to: | non-replaced block-level elements |
Inherited: | no |
Percentages: | refer to height of block |
Media: | visual, paged |
Computed value: | specified value |
When grid-rows or grid-columns are specified, grid lines are defined as follows:
Space for each column or row of the grid can be defined as
For example this rule
div { grid-columns: 50% 1fr 1fr 4em }
'fr' needs a precise definition. It is possible that there isn't any space to distribute between fractions, what happens then? fr becomes zero?
Grid lines can be defined in repeating groups using "repeat()" construct. Nested repeating groups are not allowed.
For example this rule
div { grid-rows: 4em repeat(0.25em 1em); }
It was proposed that property names refer to horizontalvertical lines instead of rows/columns (because they in fact define lines, not rows and columns). Possible alternatives: grid-horizontal-lines/grid-vertical-lines; or perhaps simply grid-horizontal/grid-vertical.
It was proposed to have syntax for repeating a certain number of times. It is not strictly necessary (if the number of times is known the values can be repeated inline) but handy.
Elements with a natural grid structure automatically define a grid that aligns with the structure. It is called an implicit grid. Such elements are
Left and right edges of each column form a grid line. There are twice as many grid lines as there are columns.
Border box of each table column defines two vertical lines; border box of each table row defines two horizontal lines. In collapsing border model there is always a pair of identical grid lines between each pair of rows and columns. Maintaining same amount of lines per column keeps the definition consistent across all table models and multi-column elements (e.g. a span over 2 columns is always 3gr)
Definition of a grid for a table is only meaningful if there is something that can use it. Currently there are no table floats. Should there be? Something like "float:top left table; float-offset:2gr 4gr" would use the table grid. Is there a use case for such floats? There is still absolute positioning that can target at table of course...
Viewport always defines a single-cell grid with the size of the viewport.
If explicit grid properties grid-columns or grid-rows are specified on an element with an implicit grid, the explicit properties have priority.
‘gr
’ is used to position
in relation to the grid lines. Actual value of each gr depends on the grid
cell in which it is used.
Example
div { columns:3; } div img { float: top left column; float-offset: 2gr; width: 1gr }
The image is positioned over the 2nd column (left edge of second column is 2nd grid line from left; its width is the distance to the next grid line).
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Vivamus a metus.
Aenean at risus
pharetra ante luctu
feugiat quis enim.
Cum sociis natoque
penatibus et magni.
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Vivamus a metus.
Aenean at risus
pharetra ante luctu
feugiat quis enim.
Cum sociis natoque
penatibus et magni.
Fractions of gr unit can be used too. In this example
div img { float:left column; float-offset: 0.5gr; width: 2gr; }
the image takes exactly the width required to stretch from the middle of first column to the middle of second column. width:2gr in the example doesn't start from exactly a grid line, therefore it is calculated as a sum of grid parts (2gr = 0.5gr + 1gr + 0.5gr), which ends in the middle of second column.
Lorem ipsum dolor sit amet. Nam at jus. Sed imp er di et ris. Cur abi tur et sapen. Fusce sed ligula a turpis. Vivamus a metus.
Lorem ipsum dolor sit amet. Nam jus.
Sed imp
er di et ris. Cur abi tur et sapen. Fusce sed ligula a turpis.
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Aenean at risus
pharetra ante luctu
feugiat quis enim.
Cum sociis natoque
penatibus et magni.
Grid units are applicable to all properties of block elements that take values of type <length>.
When applied to margins, borders and padding, grid units refer to grid lines in the direction of line progression (horizontal in layout with horizontal lines).
Grid units never apply to inline elements, including inline blocks.
Since separate grids can be defined on nested elements, it must be defined which grid is referred to for every use of 'gr' unit.
For all cases where 'gr' unit is applicable the grid is taken from the containing block (which is found as defined as defined in CSS2.1 section 10.1).
In this example, div1 is the positioning parent and therefore grid of div1 is used for positioning:
<style> .div1 { position:absolute; grid-columns:4em repeat(1em 4em); } /* this grid is used */ .div2 { columns-width:10em; column-gap:1em; } img { position:absolute; left:2gr; width:3gr; } </style> <div class="div1"> <div class="div2"> <img /> </div> </div>
However in the next example, grid of div2 is used by the float, because it is the float's containing block:
<style> .div1 { position:absolute; grid-columns:4.5em (1em 4.5em); } .div2 { columns-width:10em; column-gap:1em; } /* this grid is used */ img { float:left; float-offset:2gr; width:3gr; } </style> <div class="div1"> <div class="div2"> <img /> </div> </div>
Calculating grid units require a reference point within the grid and direction. This needs a precise definition. For the same element, grid units for position and size may have different reference points (but probably not different directions).
Define how 'gr' is used on in-flow blocks. Is '1gr' generally equivalent to '100%' there?
When a measure defined in grid units extends outside the boundaries of grid container, grid lines are repeated according to the following rules
Add an example
How important is an overflow grid? What use cases would suffer if 'gr' is just set to zero in overflow?
Specifying a grid on an element with shrink-to-fit sizing can create difficult or unsolvable problems, similar to use percentages within shrink to fit but even more complicated. Consider ignoring grid definition on anything shrink-to-fit.
On the implicit grids for multi-column elements, it might be useful to have one grid line on the left and right edge of each column, as well as a single grid line between each pair of columns. Perhaps doing the same thing for tables, one line on each side of the border spacing and another at the row/column boundary.
Should there be an option to align flow content to next available gridline? It opens really cool scenarios. But are they compelling enough to create a next available notion?
When a grid unit is used in context where there isn't an explicit or implicit grid specified, what should it be? Reaching to nearest parent with a defined grid may or may not be the right choice. There is an option to give any element a "default grid" of one cell.
It must be possible to define different grids for left and right pages. Also, any page with different dimensions (such as named pages) should be able to define its own grid.
Add grid-columns/grid-rows to @page rule
If grid is used extensively, named grid locations would be quite helpful. Defining named grid lines could look for example like this:
body { grid-columns: "left-edge" 1fr 1em 1fr 0.5em "center" 0.5em 1fr 1em 1fr "right-edge";
This syntax doesn't easily extend to named cells. It was noted however that named cells also open a possibility for named flows (by providing a sequence of named cells to fill) which makes the feature quite attractive and further approaches Advanced Layout scenarios.
"Template-based positioning" in CSS3 Advanced Layout module [CSS3LAYOUT] defines scalable templates for content to fill and also used the term "grid".
The relationship between these modules certainly needs to be well defined.
Note that technically these modules are not contradictory (as long as is defined how an advanced-layout template produces an implicit grid).
This specification is made possible by input from Håkon Wium Lie, Steve Zilles, Mike Duggan, Bill Hill, Geraldine Wade, Rikkert Koppes, Peter Linss [to be added].
Thanks to Khoi Vinh for the “Yeeaahh!” Example.
Property | Values | Initial | Applies to | Inh. | Percentages | Media |
---|---|---|---|---|---|---|
grid-columns | [[<length>|<percentage>|<fraction>] | repeat([<length>|<percentage>|<fraction> ]+)]+ | none | inherit | none | non-replaced block-level elements | no | refer to width of the block | visual, paged |
grid-rows | [[<length>|<percentage>|<fraction>] | ([<length>|<percentage>|<fraction> ]+)[‘[’<integer>‘]’]? ]+ | none | inherit | none | non-replaced block-level elements | no | refer to height of block | visual, paged |