Css Layout
Table of contents
- 1. Introduction and Overview
- 2. Grid Layout Concepts and Terminology
- 3. Grid Layout Box Model
- 4. Grid Items
- 5. Defining the Grid
- 6. Placing Grid Items
- 7. Alignment
- 8. Grid Layout Algorithm
- 9. Fragmenting Grid Layout
- 10. Conformance
- Acknowledgements
- References
- Index
- Property index
1. Introduction and Overview
Grid layout contains features targeted at web application authors. The grid can be used to achieve many different layouts. It excels at dividing up space for major regions of an application, or defining the relationship in terms of size, position, and layer between parts of a control built from HTML primitives.Like tables, grid layout enables an author to align elements into columns and rows, but unlike tables, grid layout doesn't have content structure, and thus enables a wide variety of layouts not possible with tables. For example, the children of a grid container can position themselves such that they overlap and layer similar to positioned elements.
In addition, the absence of content structure in grid layout helps to manage changes to layout by using fluid and source order independent layout techniques. By combining media queries with the CSS properties that control layout of the grid container and its children, authors can adapt their layout to changes in device form factors, orientation, and available space, without needing to alter the semantic nature of their content.
A common use of design grids is to allow content to flow
normally, but "snap" components to grid lines based on their normal flow
position. Consider adding a grid placement algorithm based on such
relative positioning. Note that this is a non-trivial issue as it impacts
the static flow of content. In addition, the grid's algorithm currently
depends on knowing the position of every grid item in advance to determine
the size of its tracks; when snapping to grid lines, however, the line to
which the grid item will snap is influenced by both the item's size and
the size of tracks the item covers.
1.1. Background and Motivation
The capabilities of grid layout address these problems. It provides a mechanism for authors to divide available space for layout into columns and rows using a set of predictable sizing behaviors. Authors can then precisely position and size the building block elements of their application by into grid areas defined by these columns and rows. Figure 1 illustrates a basic layout which can be achieved with grid layout.
1.2. Adapting Layouts to Available Space
- The stats area always appears immediately under the game title.
- The game board appears to the right of the stats and title.
- The top of the game title and the game board should always align.
- The bottom of the game board and the stats area align when the game has reached its minimum height, but otherwise the game board will stretch to take advantage of all the screen real-estate available to it.
- The score area should align into the column created by the game and stats area, while the controls are centered under the board.
Note that there are multiple ways to specify the structure of the grid and to position and size grid items, each optimized for different scenarios. This example illustrates one that an author may use to define the position and space for each grid item using the ‘
grid-definition-rows
’ and ‘grid-definition-columns
’ properties on the grid container, and the ‘grid-row
’ and ‘grid-column
’
properties on each grid item.
<style type="text/css"> #grid { display: grid; /* Two columns: the first sized to content, the second receives * the remaining space, but is never smaller than the minimum * size of the board or the game controls, which occupy this * column. */ grid-definition-columns: auto minmax(min-content, 1fr); /* Three rows: the first and last sized to content, the middle * row receives the remaining space, but is never smaller than * the minimum height of the board or stats areas. */ grid-definition-rows: auto minmax(min-content, 1fr) auto } /* Each part of the game is positioned between grid lines by * referencing the starting grid line and then specifying, if more * than one, the number of rows or columns spanned to determine * the ending grid line, which establishes bounds for the part. */ #title { grid-column: 1; grid-row: 1 } #score { grid-column: 1; grid-row: 3 } #stats { grid-column: 1; grid-row: 2; justify-self: start } #board { grid-column: 2; grid-row: 1 / span 2; } #controls { grid-column: 2; grid-row: 3; align-self: center } </style> <div id="grid"> <div id="title">Game Title</div> <div id="score">Score</div> <div id="stats">Stats</div> <div id="board">Board</div> <div id="controls">Controls</div> </div>
1.3. Source Independence
The following example leverages grid layout’s ability to name the space which will be occupied by a grid item. This allows the author to avoid rewriting rules for grid items as the grid’s definition changes.
<style type="text/css"> @media (orientation: portrait) { #grid { display: grid; /* The rows, columns and areas of the grid are defined visually * using the grid-template property. Each string is a row, and * each word an area. The number of words in a string * determines the number of columns. Note the number of words * in each string must be identical. */ grid-template: "title stats" "score stats" "board board" "ctrls ctrls"; /* Columns and rows created with the template property can be * assigned a sizing function with the grid-definition-columns * and grid-definition-rows properties. */ grid-definition-columns: auto minmax(min-content, 1fr); grid-definition-rows: auto auto minmax(min-content, 1fr) auto } } @media (orientation: landscape) { #grid { display: grid; /* Again the template property defines areas of the same name, * but this time positioned differently to better suit a * landscape orientation. */ grid-template: "title board" "stats board" "score ctrls"; grid-definition-columns: auto minmax(min-content, 1fr); grid-definition-rows: auto minmax(min-content, 1fr) auto } } /* The grid-area property places a grid item into a named * region (area) of the grid. */ #title { grid-area: title } #score { grid-area: score } #stats { grid-area: stats } #board { grid-area: board } #controls { grid-area: ctrls } </style> <div id="grid"> <div id="title">Game Title</div> <div id="score">Score</div> <div id="stats">Stats</div> <div id="board">Board</div> <div id="controls">Controls</div> </div>
1.4. Grid Layering of Elements
Prior to the introduction of grid layout, the author would have likely used absolute positioning to control the top and left coordinates, along with the width and height of each HTML element that comprises the control. By leveraging grid layout, the author can instead limit script usage to handling mouse events on the thumb, which snaps to various positions along the track as the ‘
grid-definition-columns
’ property of the grid container is updated.
<style type="text/css"> #grid { display: grid; /* The grid-definition-columns and rows properties also support * naming grid lines which can then be used to position grid * items. The line names are assigned on either side of a column * or row sizing function where the line would logically exist. */ grid-definition-columns: "start" auto "track-start" 0.5fr "thumb-start" auto "fill-split" auto "thumb-end" 0.5fr "track-end" auto "end"; } /* The grid-placement properties accept named lines. Below the * lines are referred to by name. Beyond any * semantic advantage, the names also allow the author to avoid * renumbering the grid-start and grid-before properties of the * grid items. This is similar to the concept demonstrated in the * prior example with the grid-template property during orientation * changes, but grid lines can also work with layered grid items * that have overlapping areas of different shapes like the thumb * and track parts in this example. */ #lower-label { grid-start: "start" } #track { grid-column: "track-start" / "track-end"; align-self: center } #upper-label { grid-end: "end"; } /* Fill parts are drawn above the track so set z-index to 5. */ #lower-fill { grid-column: "track-start" / "fill-split"; align-self: end; z-index: 5 } #upper-fill { grid-column: "fill-split" / "track-end"; align-self: start; z-index: 5 } /* Thumb is the topmost part; assign it the highest z-index value. */ #thumb { grid-column: "thumb-start" / "thumb-end"; z-index: 10 } </style> <div id="grid"> <div id="lower-label">Lower Label</div> <div id="upper-label">Upper Label</div> <div id="track">Track</div> <div id="lower-fill">Lower Fill</div> <div id="upper-fill">Upper Fill</div> <div id="thumb">Thumb</div> </div>
2. Grid Layout Concepts and Terminology
In grid layout, the content of a grid container is laid out by positioning and aligning it into a grid. The grid is an intersecting set of horizontal and vertical grid lines that divides the grid container’s space into grid areas, into which grid items (representing the grid container’s content) can be placed. There are two sets of grid lines: one set defining columns that run along the block axis, and an orthogonal set defining rows along the inline axis. [CSS3-WRITING-MODES]2.1. Grid Tracks
Grid track is a generic term for a grid column or grid row—in other words, it is the space between two adjacent grid lines. Each grid track is assigned a sizing function, which controls how wide or tall the column or row may grow, and thus how far apart its bounding grid lines are.
In the following example there are two columns and three rows. The
first column is fixed at 150px. The second column uses flexible sizing,
which is a function of the unassigned space in the Grid, and thus will
vary as the width of the grid
container changes. If the used width of the grid container is 200px, then the
second column 50px wide. If the used width of the grid element is
100px, then the second column is 0px and any content positioned in the
column will overflow the grid
container.
<style type="text/css"> #grid { display: grid; grid-definition-columns: 150px 1fr; /* two columns */ grid-definition-rows: 50px 1fr 50px /* three rows */ } </style>
2.2. Grid Lines
Grid lines are the horizontal and vertical dividing lines of the grid. A grid line exists on either side of a column or row. They can be referred to by numerical index, or by an author-specified name. A grid item references the grid lines to determine its position within the grid using the grid-placement properties.
The following two examples create three column grid lines and four row grid lines. The first example demonstrates
how an author would position a grid item
using grid line numbers. The second
example uses explicitly named grid lines.
<style type="text/css"> #grid { display: grid; grid-definition-columns: 150px 1fr; grid-definition-rows: 50px 1fr 50px } #item1 { grid-column: 2; grid-start: 1; grid-end: 1; } </style>
<style type="text/css"> /* equivalent layout to the prior example, but using named lines */ #grid { display: grid; grid-definition-columns: 150px "item1-start" 1fr "item1-end"; grid-definition-rows: "item1-start" 50px 1fr 50px "item1-end" } #item1 { grid-column: "item1-start" / "item1-end"; grid-row: "item1-start" / "item1-end" } </style>
2.3. Grid Areas
A grid area is the logical space used to lay out one or more grid items. It is bound by four grid lines, one on each side of the grid area, and participates in the sizing of the grid tracks it intersects. A grid area can be named explicitly using the ‘grid-template
’ property of the grid container, or referenced implicitly
by its bounding grid lines. A grid item is assigned to a grid area using the grid-placement properties.
<style type="text/css"> /* using the template syntax */ #grid { display: grid; grid-template: ". a" "b a" ". a"; grid-definition-columns: 150px 1fr; grid-definition-rows: 50px 1fr 50px } #item1 { grid-area: a } #item2 { grid-area: b } #item3 { grid-area: b } /* Align items 2 and 3 at different points in the Grid Area "b". */ /* By default, Grid Items are stretched to fit their Grid Area */ /* and these items would layer one over the other. */ #item2 { align-self: head } #item3 { justify-self: end; align-self: foot } </style>A grid item’s grid area forms the containing block into which it is laid out. Percentage lengths specified on a grid item resolve against this containing block. Percentages specified for ‘
margin-top
’, ‘padding-top
’, ‘margin-bottom
’, and ‘padding-bottom
’ on a grid
item resolve against the height of its containing block, rather
than the width (as for blocks).
Grid items placed into the same grid area do not directly affect each other's layout. Indirectly, a grid item can affect the position of a grid line in a column or row that uses a contents-based relative size, which in turn can affect the position or size of another grid item.
3. Grid Layout Box Model
3.1. Grid Containers: the
‘grid
’ and ‘inline-grid
’
‘display
’ values
Name: | display |
---|---|
New Values: | grid | inline-grid |
- ‘
grid
’ - This value causes an element to generate a block-level grid container box.
- ‘
inline-grid
’ - This value causes an element to generate an inline-level grid container box.
overflow
’ property applies to grid containers.
Grid containers are not block containers, and so some properties that were designed with the assumption of block layout don't apply in the context of grid layout. In particular:
- all of the ‘
column-*
’ properties in the Multicol module have no effect on a grid container. - ‘
float
’ and ‘clear
’ have no effect on a grid item. (However, the ‘float
’ property still affects the computed value of ‘display
’ on children of a grid container, as this occurs before grid items are determined.) - ‘
vertical-align
’ has no effect on a grid item. - the ‘
::first-line
’ and ‘::first-letter
’ pseudo-elements do not apply to grid containers.
display
’ is
‘inline-grid
’ and the element is floated or
absolutely positioned, the computed value of ‘display
’ is ‘grid
’. The table in CSS 2.1 Chapter
9.7 is thus amended to contain an additional row, with ‘inline-grid
’ in
the "Specified Value" column and ‘grid
’ in the "Computed Value" column.
3.2.
Subgrids: the ‘subgrid
’ ‘display
’ value
This is a proposal to address the alignment of sub-items
across grid items, so that, for example, a grid of labels + inputs (with
each pair styled as a unit) can still align the individual elements in a
greater grid. Potential issues:
A grid item can itself be a grid container by giving it ‘- If an item is positioned outside the subgrid's declared rows/columns, does the subgrid expand further into the outer grid, or just overflow within its declared bounds?
- How to declare a subgrid? As a separate display type, as illustrated here, or by assigning a "subgrid" value to grid-definition-rows/columns (which would allow aligning to the parent grid in only one dimension)?
- Can auto-placement in the subgrid determine/increase the size of the subgrid?
- Should you be able to interleave lines from the parent grid with subgrid lines?
display: grid
’; in this case the layout of its contents
will be independent of the layout of the grid it participates in.
In some cases it might be necessary for the contents of multiple grid items to align to each other; in this case ‘
display: subgrid
’ can be used. A grid item with ‘display:
subgrid
’ behaves just like one with ‘display:
grid
’ except that:
- The ‘
grid-definition-columns
’ and ‘grid-definition-row
’ properties do not apply. Instead the number of explicit tracks is given by its grid span. - The grid span of the item is determined by the number of grid rows and grid columns it contains.
- The grid-placement properties are scoped to the tracks covered by the subgrid: numeric indices count starting from the first line of the subgrid rather than the first line of the parent grid.
- The subgrid's own grid items participate in the sizing of its parent grid and are aligned to it. In this process, the sum of the item's margin, padding, and borders are applied as an extra layer of margin to the items at those edges.
For example, suppose we have a form consisting of a list of inputs
with labels:
<ul> <li><label>Name:</label> <input name=fn> <li><label>Address:</label> <input name=address> <li><label>Phone:</label> <input name=phone> </ul>We want the labels and inputs to align, and we want to style each list item with a border. This can be accomplished with subgrid layout:
ul { display: grid; grid-auto-flow: rows; grid-definition-columns: auto 1fr; } li { display: subgrid; margin: 0.5em; border: solid; padding: 0.5em; } label { grid-column: 1; } input { grid-column: 2; }
4. Grid Items
The contents of a grid container consists of zero or more grid items: each child of a grid container becomes a grid item, and each contiguous run of text that is directly contained inside a grid element is wrapped in an anonymous grid item. However, an anonymous grid item that contains only white space is not rendered, as if it were ‘display:none
’.
This will place all of the contents of the grid on top of each other
in slot 1 1. Alternatives:
A grid item establishes a new
formatting context for its contents. The type of this formatting context
is determined by its ‘- Turn on auto-positioning by default (see ‘
grid-auto-flow
’). - Place all unpositioned elements in the grid into an anonymous grid item in slot 1 1.
- Place all unpositioned elements in the grid into an anonymous grid item whose position is given by a "*" template slot, else is in slot 1 1.
- Same as the previous, except if there is no "*" template slot, auto-position the children.
display
’ value, as
usual. The computed ‘display
’ of a grid item is determined by applying the table
in CSS 2.1
Chapter 9.7. However, grid items are grid-level boxes, not block-level
boxes: they participate in their container's grid formatting context, not in
a block formatting context.
Examples of grid items:
Some values of ‘<div style="display:grid"> <!-- grid item: block child --> <div id="item1">block</div> <!-- grid item: floated element; floating is ignored --> <div id="item2" style="float: left;">float</div> <!-- grid item: anonymous block box around inline content --> anonymous item 3 <!-- grid item: inline child --> <span> item 4 <!-- grid items do not split around blocks --> <div id=not-an-item>item 4</div> item 4 </span> </div>
display
’ trigger the
generation of anonymous boxes. For example, a misparented ‘table-cell
’ child is fixed up by generating
anonymous ‘table
’ and ‘table-row
’ elements around it. [CSS21] This fixup must occur
before a grid container’s
children are promoted to grid items. For
example, given two contiguous child elements with ‘display:table-cell
’, an anonymous table wrapper box
around them becomes the grid item.
Future display types may generate anonymous containers (e.g.
ruby) or otherwise mangle the box tree (e.g. run-ins). It is intended that
grid item determination run after these operations.
4.1. Non-children Grid Items
This is a proposal to create the ability to have
descendants of a grid item participate in a grid layout, similar to the
behavior defined by the Template Layout module.
A descendant of the grid can be pulled out of flow and participate
directly in the grid by assigning it ‘position:
grid
’. An element with ‘position:
grid
’ is pulled out of flow and participates as a grid item
belonging to the first ancestor with ‘display:
grid
’. If the element is positioned using named lines or slots,
it belongs to the first ancestor with ‘display:
grid
’ that has all of the corresponding named lines/slots. If no
such ancestor exists, the item remains in flow.
Alternatively, the item can just go into the first grid,
and missing names are treated as ‘
auto
’.
4.2. Absolutely-positioned Grid Children
An absolutely-positioned child element of a grid container does not participate directly in grid layout. Its static position is ???- The before/start corner of the grid container? (In this case, should we adjust Flexbox to match?)
- The before/start edge of the cell it would be placed in, if it were a 1x1 auto-placed grid item? (Don't let it generate new rows/columns, though, which complicates things.) (This is closer to Flexbox's current behavior.)
Below is a proposal for how to deal with abspos in grid
containers. It gives us many of the capabilities of [CSS3GRID].
If an absolutely positioned element's containing block is
generated by a grid container, the grid-placement properties can
be used to constrain it to a particular grid
area, similar to how they affect regular grid items. In this case, an ‘auto
’ value for a grid-placement property
indicates ...
- the padding edge of the grid container (as normal for abspos)
- the next/previous grid line (as normal for grid items with one ‘
auto
’ value in a dimension, as it resolves to ‘span 1
’)
This can allow an abspos to "skip past" intervening grid
containers, and resolve its grid-placement properties against a grid
container other than its closest ancestor.
4.3. Collapsed Grid
Items: the ‘visibility
’ property
Specifying ‘visibility: collapse
’ on a grid item causes it to become a collapsed
grid item. This has the same effect as ‘visibility: hidden
’, except that if all the grid items spanning a track are collapsed, the track's intrinsic
size becomes zero.
Or should the track size be set to 0 regardless of its
sizing function?
4.4. Reordered Grid Items:
the ‘order
’ property
The ‘order
’ property,
defined in [CSS3-FLEXBOX], also applies
to grid items. It affects their auto-placement and painting order.
5. Defining the Grid
The three properties ‘grid-definition-rows
’, ‘grid-definition-columns
’, and ‘grid-template
’
together define the explicit grid of a grid container. The final grid may end
up larger due to grid items placed outside
the explicit grid; in this case, any
implicit tracks are sized by the ‘grid-auto-rows
’ and ‘grid-auto-columns
’ properties.
The size of the explicit grid is determined by the larger of the number of rows/columns defined by ‘
grid-template
’ and
the number of rows/columns sized by ‘grid-definition-rows
’/‘grid-definition-columns
’. Any rows/columns
defined by ‘grid-template
’ but not sized by ‘grid-definition-rows
’/‘grid-definition-columns
’ take their size from
the ‘grid-auto-rows
’/‘grid-auto-columns
’ properties.
Numeric indexes in the grid-placement properties count from the edges of the explicit grid. Positive indexes count from the before/start side, while negative indexes count from the after/end side.
Since all three properties define the explicit grid, would
it make sense to give them all a common prefix (and possibly a shorthand
unifying them, as in Bert's ‘
grid
’ shorthand)? Current thoughts: ‘grid-template
’ as
the shorthand, with ‘grid-template-rows/columns/slots
’ as the longhands, or
‘grid-definition
’ as the shorthand, with
‘grid-definition-rows/columns/template
’ as the
longhands. Other suggestions welcome.
5.1. Track Sizing: the ‘grid-definition-rows
’ and ‘grid-definition-columns
’ properties
Name: | grid-definition-columns, grid-definition-rows |
Value: | none | <track-list> |
Initial: | none |
Applies to: | grid containers |
Inherited: | no |
Percentages: | n/a |
Media: | visual |
Computed value: | As specified, except for ‘auto ’ (see prose)
|
minmax()
’ notation, which can combine any of the
previously mentioned mechanisms to define a min and max size for the
column or row.
The ‘
grid-definition-columns
’ property specifies
the track list for the grid's columns,
while ‘grid-definition-rows
’ specifies the track list for the grid's rows. The syntax
of a track list is:
<track-list> = [ <string>* [ <track-size> | <repeat-function> ] ]+ <string>* <track-size> = minmax( <track-breadth> , <track-breadth> ) | auto | <track-breadth> <track-breadth> = <length> | <percentage> | <flex> | min-content | max-contentWhere:
- <length>
- As defined by CSS3 Values. [CSS3VAL]
- <percentage>
- As defined by CSS3 Values. [CSS3VAL]
<percentage> values are relative to the measure (logical
width) of the grid container in
grid column tracks, and the extent (logical height) of the grid container in grid row
tracks. If the measure or extent of the grid container is an indefinite
size, <percentage> values relative to that size are
treated as ‘
auto
’. - <flex>
- A non-negative dimension with the unit "fr". Each <flex> value takes a share of the remaining space in proportion to its value. See Flexible Lengths for more details.
- max-content
- Represents the largest max size contribution of the grid items occupying the grid track.
- min-content
- Represents the largest min size contribution of the grid items occupying the grid track.
- minmax(min, max)
- Defines a size range greater than or equal to min and less
than or equal to max. If max < min,
then max is ignored and ‘
minmax(min,max)
’ is treated as min. - auto
- Computes to ‘
minmax(min-content, max-content)
’.
Handling of percentages inside indefinite-sized grid
containers is more similar to blocks/etc, rather than tables. (In tables,
they imply a table size through black magic.) Is that all right?
The none value indicates that there
is no initial grid; any rows/columns will be implicitly generated, and
their size will be determined by the ‘grid-auto-rows
’ and ‘grid-auto-columns
’ properties.
Given the following ‘
grid-definition-columns
’ declaration:
grid-definition-columns: 100px 1fr max-content minmax(min-content, 1fr);Five grid lines are created:
- At the start edge of the grid container.
- 100px from the start edge of the grid container.
- A distance from the previous line equal to half the free space (the width of the grid container, minus the width of the non-flexible grid tracks).
- A distance from the previous line equal to the maximum size of any grid items belonging to the column between these two lines.
- A distance from the previous line at least as large as the largest minimum size of any grid items belonging to the column between these two lines, but no larger than the other half of the free space.
100px
’, ‘max-content
’, and ‘min-content
’) sum to
larger than the grid container’s
width, the final grid line will be a
distance equal to their sum away from the start edge of the grid container (the ‘1fr
’ sizes both resolve to ‘0
’). If the sum is less than the grid container’s width, the final grid line will be exactly at the end edge of
the grid container. This is true in
general whenever there's at least one <flex> value among the grid track sizes.
Additional examples of valid grid
track definitions:
/* examples of valid track definitions */ grid-definition-rows: 1fr minmax(min-content, 1fr); grid-definition-rows: 10px repeat(2, 1fr auto minmax(30%, 1fr)); grid-definition-rows: calc(4em - 5px)
5.1.1. Named Grid Lines
The syntax for named lines kindof sucks right now. See thread
on www-style and add your opinions!
While grid lines can always be referred
to by their numerical index, they can also be explicitly named in the
‘grid-definition-rows
’ and ‘grid-definition-columns
’ properties. This can
make the grid-placement
properties easier to understand by using meaningful names in their
values, and easier to maintain if the grid definition changes in the
future.
For example, the following code gives meaningful names to all of the
lines in the grid. Note that some of the lines have multiple names.
<style> #grid { display: grid; grid-definition-columns: "first" "nav" 150px "main" 1fr "last"; grid-definition-rows: "first" "header" 50px "main" 1fr "footer" 50px "last"; } </style>
Consider merging grid line names with grid field names.
See: http://lists.w3.org/Archives/Public/www-style/2012Sep/0047.html
for proposal.
5.1.2. Repeating Rows and
Columns: the ‘repeat()
’ notation
The ‘repeat()
’ notation represents a
repeated fragment of the track list. This
is just a syntactic shorthand that allows writing a large number of
columns or rows that exhibit a recurring pattern in a more compact form.
The syntax of the ‘repeat()
’ notation is:
<repeat-function> = repeat( <positive-integer> , [ <string>* <track-size> ]+ <string>* )The first argument specifies the number of repetitions. The second argument is a track list, which is repeated that number of times. The ‘
repeat()
’
notation cannot be nested; doing so makes the declaration invalid.
This example shows two equivalent ways of writing the same grid
definition. Both ways produce a grid with a single row and four "main"
columns, each 250px wide, surrounded by 10px "gutter" columns.
<style> #grid { display: grid; grid-definition-columns: 10px "col-start" 250px "col-end" 10px "col-start" 250px "col-end" 10px "col-start" 250px "col-end" 10px "col-start" 250px "col-end" 10px; grid-definition-rows: 1fr; } /* Equivalent definition. */ #grid { display: grid; grid-definition-columns: repeat(4, 10px "col-start" 250px "col-end") 10px; grid-definition-rows: 1fr; } </style>
5.1.3. Flexible Lengths: the
‘fr
’ unit
The ‘fr
’ unit represents a fraction of the
free space in the grid container.
The distribution of free space occurs after all non-flexible sizing functions have reached their maximum. The total size of such rows or columns is subtracted from the available space, yielding the free space, which is then divided among the flex-sized rows and columns in proportion to their flex factor.
Flexible lengths in a track
list work similarly to flexible lengths with a zero base size in
[CSS3-FLEXBOX].
Each column or row's share of the free
space can be computed as the column or row's <flex> *
<free space> / <sum of all flex factors>
. For the purpose of
this calculation, a flexible length in the min position of a
‘minmax()
’ function is treated as ‘0
’ (an inflexible length).
When the available space is infinite (which happens when the grid container’s width or height is indefinite), flex-sized grid tracks are sized to their contents while retaining their respective proportions. The used size of each flex-sized grid track is computed by determining the ‘
max-content
’
size of each flex-sized grid track and
dividing that size by the respective flex factor to determine a hypothetical 1fr size. The maximum of those
is used as the ‘1fr
’ length, which is then
multiplied by each grid track’s flex
factor to determine its final size.
5.1.4. Resolved Values
The resolved value of the ‘grid-definition-rows
’ and ‘grid-definition-columns
’ properties is the
used value, serialized as follows:
- Every track listed, whether implicitly or explicitly created.
- Every track size given as a length in pixels, regardless of sizing function.
- A contiguous run of two or more tracks that have the same size and
associated line names may be serialized with the ‘
repeat()
’ notation.
<style> #grid { width: 500px; grid-definition-columns: "a" auto "b" minmax(min-content, 1fr) "b" "c" "d" repeat(2, "e" 40px) repeat(5, auto); } </style> <div id="grid"> <div style="grid-start:1; width:50px"></div> <div style="grid-start:9; width:50px"></div> </div> <script> var gridElement = document.getElementById("grid"); getComputedStyle(gridElement).gridDefinitionColumns; // "a" 50px "b" 320px "b" "c" "d" repeat(2, "e" 40px) repeat(4, 0px) 50px </script>
In general, resolved values are the computed values, except
for a small list of legacy 2.1 properties. Do we really want these
properties to return the used value here?
5.2. Named Areas:
the ‘grid-template
’ property
Name: | grid-template |
Value: | none | <string>+ |
Initial: | none |
Applies to: | grid containers |
Inherited: | no |
Percentages: | n/a |
Media: | visual |
Computed value: | specified value |
grid-template
’ property also provides a
visualization of the structure of the grid, making the overall layout of the grid container easier to understand.
Values have the following meanings:
- ‘
none
’ - The grid container doesn't define any named grid areas.
- <string>+
- A row is created for every separate string listed for the ‘
grid-template
’ property, and a column is created for each identifier or period ("." U+002E) in the string, when the string's contents are parsed as CSS.- A period represents an unnamed area in the grid container that cannot be used to position or size a grid item.
- An identifier creates a named grid area with the identifier as its name. Multiple identical identifiers create a single named grid area that spans the corresponding grid cells.
Non-rectangular or disconnected regions may be permitted in a future version of this module.
In this example, the ‘
grid-template
’ property is used to create a
page layout where areas are defined for header content
(head
), navigational content (nav
), footer
content (foot
), and main content (main
).
Accordingly, the template creates three rows and two columns, with four
named grid areas. The
head
area spans both columns and the first row of the grid.
<style type="text/css"> #grid { display: grid; grid-template: "head head" "nav main" "foot . " } #grid > header { grid-area: head; } #grid > nav { grid-area: nav; } #grid > main { grid-area: main; } #grid > footer { grid-area: foot; } </style>
5.3. Auto-generated Rows and
Columns: the ‘grid-auto-rows
’ and ‘grid-auto-columns
’ properties
Name: | grid-auto-columns, grid-auto-rows |
Value: | <track-minmax> |
Initial: | auto |
Applies to: | grid containers |
Inherited: | no |
Percentages: | see Track Sizing |
Media: | visual |
Computed value: | see Track Sizing |
grid-definition-row
’
or ‘grid-definition-column
’, implicit
grid tracks are created to hold it. This can happen either by
explicitly positioning into a row or column that is out of range, or by
the auto-placement algorithm creating additional rows or columns.
The ‘grid-auto-columns
’ and ‘grid-auto-rows
’
properties specify the size of such implicitly-created tracks.
This example illustrates the sizing of implicit grid tracks. Note that
grid item B is positioned on grid line 5, which automatically creates
four implicit grid
columns. However, only two of them (the first and the last) are
occupied by any grid items, so the two
empty grid tracks collapse to zero
width.
<style type="text/css"> #grid { display: grid; grid-definition-columns: 20px; grid-definition-rows: 20px } #A { grid-column: 1; grid-row: 1; } #B { grid-column: 5; grid-row: 1 / span 2; } #C { grid-column: 1 / span 2; grid-row: 2; } </style> <div id="grid"> <div id="A">A</div> <div id="B">B</div> <div id="C">C</div> </div>
6. Placing Grid Items
Put in "common uses" section, like ‘
flex
’ has, to describe what you would use ‘grid-area
’ for, etc.
6.1. Line-based Placement:
the ‘grid-before
’, ‘grid-start
’, ‘grid-after
’, and ‘grid-end
’ properties
These are somewhat awkward, but nobody's been able to come
up with a clearer set of four property names. If anyone has suggestions,
please, please post them. (Other syntax improvement suggestions are also
welcome.)
Name: | grid-before, grid-start, grid-after, grid-end |
Value: | <grid-line> |
Initial: | auto |
Applies to: | grid items |
Inherited: | no |
Percentages: | n/a |
Media: | visual |
Computed value: | specified value (almost) |
<grid-line> = auto | [ <integer> || <string> ] | [ span && [ <integer> || <string> ] ] | <ident>The ‘
grid-before
’, ‘grid-start
’, ‘grid-after
’, and ‘grid-end
’ properties (collectively, the grid-placement
properties) specify, respectively, the before, start,
after, and end grid lines of
a grid item’s grid area. In each dimension (row or column),
they resolve to either a specific pair of lines (specifying a position and
implying a grid span), or just a grid span (implying auto-placement in
that dimension).
Values have the following meanings:
- <integer> || <string>
- Specifies that the corresponding edge of the item's grid area is the Nth grid line from the before/start edge of the
explicit grid. If a negative integer
is given, it instead counts in reverse, starting from the after/end edge
of the explicit grid. If a name is
given as a <string>, only lines with that name are
considered. If the <integer> is omitted, it defaults to
‘
1
’. A value of zero makes the declaration invalid. - span && [ <integer> || <string> ]
- Specifies an explicit grid span: the
corresponding edge of the item's grid
area is N grid lines
from the opposite edge of the item's grid
area. If a name is given as a <string>, only lines
with that name are considered. If the <integer> is omitted,
it defaults to ‘
1
’. Negative integers or zero are invalid. If opposing grid-placement properties both specify a grid span, they both compute to ‘auto
’. - <ident>
- Specifies that the corresponding edge of the item's grid area is the grid line at the before edge of the named grid area. If the named grid
area doesn't exist, this value is treated as ‘
auto
’ (computing either to ‘auto
’ or ‘span 1
’). - auto
- If the opposing grid-placement property
specifies a grid line, ‘
auto
’ computes to ‘span 1
’. Otherwise (if the opposing grid-placement property is ‘auto
’ or specifies an explicit grid span), it indicates that the grid item is placed using the auto-placement algorithm.
grid-after/end
’ specifies a line at or
before that specified by ‘grid-before/start
’,
it computes to ‘span 1
’.
If ‘
grid-before
’ specifies a named grid line, but no grid row lines of that name exist, the before
edge of the grid area is set to the first
grid row line (or the last, if the
<integer> is negative). If there are grid row lines of that name, but the
<integer> specified exceeds the number of such grid row lines, the before edge of the grid area is set to the last grid row line of that name (or the first, if
the <integer> is negative). Analogously for the other three
grid-placement properties.
Given a single-row, 8-column grid and the following 9 named lines:
1 2 3 4 5 6 7 8 9 +--+--+--+--+--+--+--+--+ | | | | | | | | | A B C A B C A B C | | | | | | | | | +--+--+--+--+--+--+--+--+The following declarations place the grid item between the lines indicated by index:
grid-start: 4; grid-end: auto; /* Line 4 to line 5 */ grid-start: auto; grid-end: 6; /* Line 5 to line 6 */ grid-start: 'C'; grid-end: 'C'; /* Line 3 to line 9 */ grid-start: 'C'; grid-end: span 'C'; /* Line 3 to line 6 */ grid-start: span 'C'; grid-end: 'C'; /* Line 6 to line 9 */ grid-start: span 'C'; grid-end: span 'C'; /* Error: both properties compute to ''auto'' */ grid-start: 5; grid-end: 'C'; /* Line 5 to line 9 */ grid-start: 5; grid-end: span 'C'; /* Line 5 to line 6 */ grid-start: 8; grid-end: 8; /* Error: line 8 to line 9 */ grid-start: 'B' 2; grid-end: span 1; /* Line 5 to line 6 */
6.2. Placement
Shorthands: the ‘grid-column
’, ‘grid-row
’, and ‘grid-area
’ properties
Name: | grid-column, grid-row |
Value: | <grid-line> [ / <grid-line> ]? |
Initial: | see individual properties |
Applies to: | grid items |
Inherited: | see individual properties |
Percentages: | see individual properties |
Media: | visual |
Computed value: | see individual properties |
grid-row
’
and ‘grid-column
’ properties are shorthands for
‘grid-before/after
’ and ‘grid-start/end
’, respectively.
If two <grid-line> values are specified, the before/start longhand is set to the value before the slash, and the after/end longhand is set to the value after the slash.
When the second value is omitted, if the first value is an <ident>, the after/end longhand is also set to that <ident>; otherwise, it is set to ‘
auto
’.
Name: | grid-area |
Value: | <grid-line> [ / <grid-line> ]{0,3} |
Initial: | see individual properties |
Applies to: | grid items |
Inherited: | see individual properties |
Percentages: | see individual properties |
Media: | visual |
Computed value: | see individual properties |
grid-before
’ is set to the first value, ‘grid-start
’ is set to
the second value, ‘grid-after
’ is set to the third value, and
‘grid-end
’ is set
to the fourth value.
When ‘
grid-end
’
is omitted, if ‘grid-start
’ is an <ident>, ‘grid-end
’ is set to
that <ident>; otherwise, it is set to ‘auto
’.
When ‘
grid-after
’ is omitted, if ‘grid-before
’ is an
<ident>, ‘grid-after
’ is set to that
<ident>; otherwise, it is set to ‘auto
’.
When ‘
grid-start
’ is omitted, if ‘grid-before
’ is an
<ident>, all four longhands are set to that value.
Otherwise, it is set to ‘auto
’.
The WG needs to resolve on the equivalent of t/r/b/l order
for logical shorthands. Here, we're using b/s/a/e order, because it is the
most logical. However, it is only equivalent to t/r/b/l for RTL users.
Should ‘
grid-area
’ be ‘grid-field
’?
6.3. Automatic
Placement: the ‘grid-auto-flow
’ property
Name: | grid-auto-flow |
Value: | none | rows | columns |
Initial: | none |
Applies to: | grid containers |
Inherited: | no |
Percentages: | n/a |
Media: | visual |
Computed value: | specified value |
grid-auto-flow
’ property controls the
direction in which the search for unoccupied space takes place, and
whether rows or columns are added as needed to accommodate the content.
- ‘
none
’ - The grid area of grid items that are auto-placed has its before and start edges set to the first grid line in the relevant dimension, and its after and end edges set according to the amount of span specified on the grid item (defaulting to 1 if the item doesn't specify any span).
- ‘
rows
’ - The auto-placement algorithm places items by filling each row in turn, adding new rows as necessary.
- ‘
columns
’ - The auto-placement algorithm places items by filling each column in turn, adding new columns as necessary.
order
’-modified
document order.
In the following example, there are three columns, each auto-sized to
their contents. No rows are explicitly defined. The ‘
grid-auto-flow
’
property is ‘rows
’ which instructs the grid to search across
its three columns starting with the first row, then the next, adding rows
as needed until sufficient space is located to accommodate the position
of any auto-placed grid item.
<style type="text/css"> form { display: grid; /* Define three columns, all content-sized, and name the corresponding lines. */ grid-definition-columns: "labels" auto "controls" auto "oversized" auto; grid-auto-flow: rows; } form > label { /* Place all labels in the "labels" column and automatically find the next available row. */ grid-column: "labels"; grid-row: auto; } form > input, form > select { /* Place all controls in the "controls" column and automatically find the next available row. */ grid-column: "controls"; grid-row: auto; } #department { /* Auto place this item in the "oversized" column in the first row where an area that spans three rows won't overlap other explicitly placed items or areas or any items automatically placed prior to this area. */ grid-column: "oversized"; grid-row: span 3; } /* Place all the buttons of the form in the explicitly defined grid area. */ #buttons { grid-row: auto; /* Ensure the button area spans the entire grid element in the row axis. */ grid-column: 1 / 1; text-align: end; } </style> <form> <label for="firstname">First name:</label> <input type="text" id="firstname" name="firstname" /> <label for="lastname">Last name:</label> <input type="text" id="lastname" name="lastname" /> <label for="address">Address:</label> <input type="text" id="address" name="address" /> <label for="address2">Address 2:</label> <input type="text" id="address2" name="address2" /> <label for="city">City:</label> <input type="text" id="city" name="city" /> <label for="state">State:</label> <select type="text" id="state" name="state"> <option value="WA">Washington</option> </select> <label for="zip">Zip:</label> <input type="text" id="zip" name="zip" /> <div id="department"> <label for="department">Department:</label> <select id="department" name="department" multiple> <option value="finance">Finance</option> <option value="humanresources">Human Resources</option> <option value="marketing">Marketing</option> </select> </div> <div id="buttons"> <button id="cancel">Cancel</button> <button id="back">Back</button> <button id="next">Next</button> </div> </form>
6.3.1. Automatic Grid Item Placement Algorithm
The following summarizes the algorithm for auto placement of Grid items:- For each Grid item with a major-axis
position that is not ‘
auto
’ in source order: - Determine the maximum number of minor tracks based on maximum track
number implied by the ‘
grid-template
’ property, the ‘grid-definition-rows
’ and ‘grid-definition-columns
’ properties, the position and size of any explicitly-defined grid items, or any minor-axis ‘auto
’ values resolved by the step 1 of the algorithm. Note that this step must be run prior to the layout algorithm. - Position the auto-placement cursor at position 1,1 in the grid.
- For each grid item having an
unresolved value of ‘
auto
’, in source order:- If the minor-axis position is not ‘
auto
’, then: - If the minor and major-axis positions are both ‘
auto
’, then:- Increment the minor-axis position of the auto-placement cursor until this item's grid area does not overlap another item's grid area, or causes the grid area to exceed the maximum number of minor-axis tracks previously determined in step 2.
- If this item's position is still unresolved after the previous step, then increment the cursor's major-axis position and reset the minor-axis position to 1 (creating new major-axis tracks if necessary).
- If the minor-axis position is not ‘
Two mistakes in the algorithm currently:
- Step 2 needs to take into account the major-axis spans of every item as well. Otherwise, extra-wide single items can create new columns late in auto-placement.
- Step 4 needs to verify that placement also doesn't cause the item to generate new columns. Currently, it only verifies that placement wont' overlap anything else.
This algorithm creates a "sparse" packing, where holes left
behind are never filled in. This is more efficient and predictable (items
never move to a position far above/before their preceding sibling), but
the gaps are unwanted by authors in some situations. We should have a
switch to allow for dense packing. (WebKit's current implementation does
dense packing.)
7. Alignment
After a grid container’s grid tracks have been sized, and the dimensions of all grid items are finalized, grid items can be aligned within their grid areas by using ‘auto
’ margins or the
alignment properties.
By default, grid items stretch to fill their grid area. However, if ‘
justify-self
’ or ‘align-self
’ compute to a value other than ‘stretch
’ or margins are ‘auto
’, grid items will auto-size to fit their
contents.
A value of ‘
stretch
’ causes the Grid item’s width to shrink or grow in
accordance with the equation for calculating width described in section 9.3 of the CSS3
Box Model, with the following exception: the paragraph in 9.3 which
describes the behavior of items that are larger than their containing
block is not applicable for the purpose of calculating the size of Grid items. Note that this calculation is
symmetric for both the width and height of the Grid item.
The preceding paragraph seems inconsistent with Flexbox. In
Flexbox, auto margins effectively "turn off" stretch entirely, so
underflowing items get aligned per the margins and overflowing items
overflow the line (rather than being shrunk to the size of the line). In
the preceding paragraph, it seems that stretched grid items will always
grow/shrink to the size of the grid area regardless of margins. I believe
we want the Flexbox behavior.
7.1. Aligning with ‘auto
’ margins
This section is non-normative. The normative definition of how
margins affect grid items is in the Flex
Layout Algorithm section.
Auto margins on grid items have an effect very similar to auto margins in block flow:
- During calculations of grid track
sizes, auto margins are treated as ‘
0
’. - Auto margins absorb positive free space prior to alignment via the alignment properties (defined in the next sections).
- Overflowing elements ignore their auto margins and overflow in the end/after direction.
Note that, if free space is distributed to auto margins, the
alignment properties will have no effect in that dimension because the
margins will have stolen all the free space left over after flexing.
TODO: EXAMPLE HERE
7.2. Row-axis Alignment: the
‘justify-self
’ and ‘justify-items
’ properties
Grid items can be aligned in the inline
dimension by using the ‘justify-self
’
property on the grid item or ‘justify-items
’ property on the grid container, as defined in [CSS3-ALIGN].
For example, for an English document, the inline axis
is horizontal, and so the ‘
justify-*
’
properties align the grid items
horizontally.
TODO: provide example
7.3. Column-axis Alignment:
the ‘align-self
’ and ‘align-items
’ properties
Grid items can also be aligned in the
block dimension (perpendicular to the inline dimension) by using the
‘align-self
’ property on the grid item or ‘align-items
’ property on the grid container, as defined in [CSS3-ALIGN].
7.4. Z-axis Ordering: the ‘z-index
’ property
Grid items can overlap when they are
positioned into intersecting grid areas.
Grid item boxes in non-intersecting areas
can also overlap because of negative margins or positioning.
When grid items overlap, the ‘
z-index
’ property provides control over the
drawing order of grid items. Grid items paint exactly the same as
flex items [CSS3-FLEXBOX]: they use ‘order
’-modified document
order, and ‘z-index
’ values other than
‘auto
’ create a
stacking context even if ‘position
’ is
‘static
’.
Note: Descendants that are positioned outside a grid item
still participate in any stacking context established by the grid item.
The following diagram shows several overlapping grid items, with a
combination of implicit source order and explicit ‘
z-index
’ used to control their stacking order.
<style type="text/css"> #grid { display: grid; grid-definition-columns: 1fr 1fr; grid-definition-rows: 1fr 1fr } #A { grid-column: 1 / span 2; grid-row: 2; align-self: foot } #B { grid-column: 1; grid-row: 1; z-index: 10 } #C { grid-column: 2; grid-row: 1; align-self: head; margin-left: -20px } #D { grid-column: 2; grid-row: 2; justify-self: end; align-self: head } #E { grid-column: 1 / span 2; grid-row: 1 / span 2; z-index: 5; justify-self: center; align-self: center; } </style> <div id="grid"> <div id="A">A</div> <div id="B">B</div> <div id="C">C</div> <div id="D">D</div> <div id="E">E</div> </div>
7.5. Grid Baselines
The baselines of a grid container are determined as follows:- If any of the grid items whose areas intersect the grid container’s first row/column participate in baseline alignment, the grid container's baseline is the baseline of those grid items.
- Otherwise, if the grid container has at least one grid item whose area intersects the first
row/column, and the first such grid item
(in ‘
order
’-modified grid order) has a baseline parallel to the relevant axis, the grid container's baseline is that baseline. - Otherwise, the grid container's baseline is synthesized
from the first item's (in ‘
order
’-modified grid order) content box, or, failing that, from the grid container's content box.
align-self
’ or ‘justify-self
’, as appropriate, is ‘baseline
’ and its inline axis is parallel to that
dimension.
‘
order
’-modified grid order is the order in
which grid items are encountered when
traversing the grid's grid cells, in row-major order if calculating
the inline-axis baseline, or in column-major order if calculating the
block-axis baseline. If two items are encountered at the same time, they
are taken in ‘order
’-modified document order.
When calculating the baseline according to the above rules, if the box contributing a baseline has an ‘
overflow
’
value that allows scrolling, the box must be treated as being in its
initial scroll position for the purpose of determining its baseline.
When determining the baseline of a table cell, a grid container provides a baseline just as a line box or table-row does. [CSS21]
8. Grid Layout Algorithm
8.1. Definition of Terms for use in Calculating Grid Track Sizes
- AvailableSpace
- The Grid element’s content box size in the applicable dimension.
- MaxTrackSizingFunction
- One of the <track-breadth> sizing functions assigned as the maximum breadth of a Grid track.
- MinTrackSizingFunction
- One of the <track-breadth> sizing functions assigned as the minimum breadth of a Grid track.
- RemainingSpace
- The max of zero and the AvailableSpace less the sum of all Grid track UsedBreadth values. This is undefined if AvailableSpace is undefined (i.e. the Grid element is shrink-to-fit or the height is auto.)
- SpanCount
- The number of Grid tracks crossed by a Grid item in the applicable dimension.
8.2. Grid Track Sizing Algorithm
- Call ComputedUsedBreadthOfGridTracks for Grid Columns to resolve their logical width.
- Call ComputedUsedBreadthOfGridTracks for Grid Rows to resolve their logical height. The logical width of Grid Columns from the prior step is used in the formatting of Grid items in content-sized Grid Rows to determine their required height.
- If the minimum content size of any Grid item has changed based on available height for the Grid item as computed in step 2, adjust the min content size of the Grid item and restart the Grid track Sizing algorithm (once only).
- ComputeUsedBreadthOfGridTracks
-
This is the core Grid track sizing
algorithm. It is run for Grid columns and Grid rows. The goal of the
function is to ensure:
- That each Grid track satisfies its MinTrackSizingFunction
- That each Grid track grows from the breadth which satisfied its MinTrackSizingFunction to a breadth which satisfies its MaxTrackSizingFunction, subject to RemainingSpace.
- A percentage or length value which can be trivially resolved.
- A min-content or max-content value which will be resolved based on the measurements of the Grid items which cover the Grid track.
- A flexible length which can only be resolved after determining the RemainingSpace in the Grid element’s content box after having considered all contributions from the prior two categories of Grid tracks.
In step 3, the second goal of this function is satisfied as each (non-flex-sized) Grid track attempts to grow from the UsedBreadth value to the MaxBreadth value, subject to RemainingSpace.
Finally in step 4, the third category of flex-sized Grid tracks can be resolved using what is now the RemainingSpace having updated the UsedBreadth of each Grid track at the end of step 3.
- Inputs
-
- GridTracks: The set of Grid tracks for which the Grid track variable UsedBreadth will be computed.
- Algorithm
-
- Initialize per Grid track
variables
- For each Grid track t in
GridTracks
- If t.MinTrackSizingFunction is a percentage or length, then t.UsedBreadth = resolved length
- If t.MinTrackSizingFunction is min-content, max-content, or a flexible length, then t.UsedBreadth = 0
- If t.MaxTrackSizingFunction is percentage or length, then
t.MaxBreadth = resolved length
- If the resolved length of the MaxTrackSizingFunction is less than the MinTrackSizingFunction, t.MaxBreadth = t.UsedBreadth.
- If t.MaxTrackSizingFunction is min-content, or max-content, then t.MaxBreadth = Infinity
- If t.MaxTrackSizingFunction is a flexible length, then t.MaxBreadth = t.UsedBreadth
- t.SpanGroupInWhichMaxBreadthWasMadeFinite = null
- For each Grid track t in
GridTracks
- Resolve content-based TrackSizingFunctions
- Call ResolveContentBasedTrackSizingFunctions, with arguments:
- GridItems: All Grid items.
- Call ResolveContentBasedTrackSizingFunctions, with arguments:
- Grow all Grid tracks in
GridTracks from their UsedBreadth up to their MaxBreadth value until
RemainingSpace is exhausted.
- If RemainingSpace is defined
- Iterate over all GridTracks and assign UsedBreadth to UpdatedTrackBreadth
- Call DistributeSpaceToTracks, with arguments:
- SpaceToDistribute: RemainingSpace
- TrackGrowthConstraint: A function which given a Grid track returns its MaxBreadth.
- TracksForGrowth: All Grid tracks
- SubsetOfTracksForGrowthBeyondTrackGrowthConstraint: The empty set.
- CurrentBreadth: A function which given a Grid track returns the UsedBreadth.
- Iterate over all GridTracks and assign UpdatedTrackBreadth to UsedBreadth
- Else
- For each Grid track t in
GridTracks
- t.UsedBreadth = t.MaxBreadth
- For each Grid track t in
GridTracks
- If RemainingSpace is defined
- Grow all Grid tracks having a
flexible length as the MaxTrackSizingFunction
- normalizedFlexBreadth = 0
- If RemainingSpace is defined
- normalizedFlexBreadth = Call ComputeNormalizedFlexBreadth,
with arguments:
- GridTracks: GridTracks
- SpaceToFill: AvailableSpace
- normalizedFlexBreadth = Call ComputeNormalizedFlexBreadth,
with arguments:
- Else
- For each Grid track t in
GridTracks having a flexible length as the MaxTrackSizingFunction
- normalizedFlexBreadth = Max( normalizedFlexBreadth, t.UsedBreadth / t.MaxTrackSizingFunction.FlexValue )
- For each Grid item i, which
crosses a set of GridTracks s
- itemNormalizedFlexBreadth = Call
ComputeNormalizedFlexBreadth, with arguments:
- GridTracks: s
- SpaceToFill: max-content size of i
- normalizedFlexBreadth = Max( normalizedFlexBreadth, itemNormalizedFlexBreadth )
- itemNormalizedFlexBreadth = Call
ComputeNormalizedFlexBreadth, with arguments:
- For each Grid track t in
GridTracks having a flexible length as the MaxTrackSizingFunction
- For each Grid track t in
GridTracks
- t.UsedBreadth = Max( t.UsedBreadth, normalizedFlexBreadth * t.MaxTrackSizingFunction.FlexValue )
- Initialize per Grid track
variables
- ResolveContentBasedTrackSizingFunctions
-
The purpose of this function is to resolve the contribution that each
Grid item makes to any min-content or
max-content TrackSizingFunctions for the Grid
tracks it covers. There are four permutations: min-content or
max-content in either the MinTrackSizingFunction or
MaxTrackSizingFunction. MinTrackSizingFunctions are resolved before
MaxTrackSizingFunctions, and min-content contributions are resolved
before max-content contributions. Note that when resolving min-content
contributions they may grow tracks that have either min-content or
max-content keywords, as seen in 3.a.i and 3.b.i below.
Currently this algorithm embodies several heuristics which regulate the growth of spanning Grid items to accommodate certain use cases. (E.g. the game example in Figures 2 and 3 above.) These heuristics should be a normative part of this specification to ensure interoperability. To the extent additional use cases can be identified that cannot be satisfied by following the current heuristics, the normative algorithm can be updated, or additional mechanisms can be introduced for fine-grained control of content-based TrackSizingFunction.- Inputs
-
- GridItems: The set of Grid items for which min-content or max-content keywords should be resolved.
- Algorithm
-
- Filter all Grid items into a set g, such that each Grid item has either a SpanCount of 1 or does not cross a flex-sized Grid track
- Group all Grid items in set g by their SpanCount ascending
- For each group of Grid items
- Resolve content-based MinTrackSizingFunctions
- Call ResolveContentBasedTrackSizingFunctionsForItems, with
arguments:
- GridItems: All Grid items in the current group.
- AdditionalSpaceRequiredByItem: A function which given a Grid item returns the min-content size of that Grid item less the summed UsedBreadth of all Grid tracks it covers.
- TrackGrowthConstraint: A function which given a Grid track returns its MaxBreadth.
- TracksForGrowth: A function which given a Grid item returns the set of Grid tracks covered by that Grid item that have a min-content or max-content MinTrackSizingFunction.
- SubsetOfTracksForGrowthBeyondTrackGrowthConstraint: A function which given a set of Grid tracks returns the subset of Grid tracks having a min-content or max-content MaxTrackSizingFunction. If that set is the empty set, return the input set instead.
- Accumulator: A function which given a Grid track returns a reference to its UsedBreadth variable.
- Call ResolveContentBasedTrackSizingFunctionsForItems, with
arguments:
- GridItems: All Grid items in the current group.
- AdditionalSpaceRequiredByItem: A function which given a Grid item returns the max-content size of that Grid item less the summed UsedBreadth of all Grid tracks it covers.
- TrackGrowthConstraint: A function which given a Grid track returns its MaxBreadth.
- TracksForGrowth: A function which given a Grid item returns the set of Grid tracks covered by that Grid item that have a max-content MinTrackSizingFunction.
- SubsetOfTracksForGrowthBeyondTrackGrowthConstraint: A function which given a set of Grid tracks returns the subset of Grid tracks having a max-content MaxTrackSizingFunction. If that set is the empty set, return the input set instead.
- Accumulator: A function which given a Grid track returns a reference to its UsedBreadth variable.
- Call ResolveContentBasedTrackSizingFunctionsForItems, with
arguments:
- Resolve content-based MaxTrackSizingFunctions
- Call ResolveContentBasedTrackSizingFunctionsForItems, with
arguments:
- GridItems: All Grid items in the current group.
- AdditionalSpaceRequiredByItem: A function which given a Grid item returns the min-content size of that Grid item less the summed MaxBreadth (unless the MaxBreadth is infinite, in which case use the UsedBreadth) of all Grid tracks it covers.
- TrackGrowthConstraint: A function which given a Grid track returns its MaxBreadth.
- TracksForGrowth: A function which given a Grid item returns the set of Grid tracks covered by that Grid item that have a min-content or max-content MaxTrackSizingFunction.
- SubsetOfTracksForGrowthBeyondTrackGrowthConstraint: The identity function.
- Accumulator: A function which given a Grid track returns a reference to its MaxBreadth variable.
- Call ResolveContentBasedTrackSizingFunctionsForItems, with
arguments:
- GridItems: All Grid items in the current group.
- AdditionalSpaceRequiredByItem: A function which given a Grid item returns the max-content size of that Grid item less the summed MaxBreadth (unless the MaxBreadth is infinite, in which case use the UsedBreadth) of all Grid tracks it covers.
- TrackGrowthConstraint: A function which given a Grid track returns infinity if the Grid track’s SpanGroupInWhichMaxBreadthWasMadeFinite is equal to the current group; otherwise return the Grid track’s MaxBreadth.
- TracksForGrowth: A function which given a Grid item returns the set of Grid tracks covered by that Grid item that have a max-content MaxTrackSizingFunction.
- SubsetOfTracksForGrowthBeyondTrackGrowthConstraint: The identity function.
- Accumulator: A function which given a Grid track returns a reference to its MaxBreadth variable.
- Call ResolveContentBasedTrackSizingFunctionsForItems, with
arguments:
- Resolve content-based MinTrackSizingFunctions
- For each Grid track t from the
set of all Grid tracks
- If t.MaxBreadth == infinity then t.MaxBreadth = t.UsedBreadth
- ResolveContentBasedTrackSizingFunctionsForItems
-
The above function, ResolveContentBasedTrackSizingFunctions, groups
Grid items based on the number of Grid tracks each Grid item spanned.
ResolveContentBasedTrackSizingFunctionsForItems, below, then calls
DistributeSpaceToTracks for each Grid
item in the group to determine how much each Grid item needs to grow the Grid tracks that it covers. The maximum
contribution made by any Grid item is
accumulated into a temporary, per-Grid
track variable, and at the end of the group, the space is
recorded into a final Grid track
variable as determined by the Accumulator function.
- Inputs
-
- GridItems: The set of Grid items which will contribute to the growth of Grid tracks.
- AdditionalSpaceRequiredByItem: A function which returns the difference between either the min-content or max-content for the Grid item and the space already allocated to the Grid tracks covered by the Grid item in earlier phases of the algorithm.
- TrackGrowthConstraint: A function which given a Grid track returns a value that limits the amount by which it may be grown by the Grid items which cover it.
- TracksForGrowth: A function which given a Grid item identifies the set of Grid tracks to be grown in this phase of the algorithm.
- SubsetOfTracksForGrowthBeyondTrackGrowthConstraint: A function which identifies a subset of Grid tracks from TracksForGrowth that may be grown in this phase of the algorithm after all Grid tracks in the TracksForGrowth set have already grown to their TrackGrowthConstraint.
- Accumulator: A function which given a Grid track returns the variable used to accumulate the results of the UpdatedTrackBreadth from DistributeSpaceToTracks.
- Algorithm
-
- For each Grid track t
- t.UpdatedTrackBreadth = Accumulator( t )
- For each Grid item i in GridItems
- Call DistributeSpaceToTracks, with arguments:
- SpaceToDistribute: AdditionalSpaceRequiredByItem( i )
- TrackGrowthConstraint: TrackGrowthConstraint
- TracksForGrowth: TracksForGrowth( i )
- SubsetOfTracksForGrowthBeyondTrackGrowthConstraint: SubsetOfTracksForGrowthBeyondTrackGrowthConstraint( TracksForGrowth( i ) )
- CurrentBreadth: A function which given a Grid track returns the UsedBreadth of the Grid track if Accumulator returns infinity; otherwise the value of the Accumulator is returned.
- Call DistributeSpaceToTracks, with arguments:
- For each Grid track t
- If Accumulator( t ) == infinity and t.UpdatedTrackBreadth !=
infinity
- t.SpanGroupInWhichMaxBreadthWasMadeFinite = GridItems
- Accumulator( t ) = t.UpdatedTrackBreadth
- If Accumulator( t ) == infinity and t.UpdatedTrackBreadth !=
infinity
- For each Grid track t
- DistributeSpaceToTracks
-
Ensures that for each Grid track in
RecipientTracks, a value will be computed, UpdatedTrackBreadth, that
represents the Grid track’s share of
SpaceToDistribute.
There are two parts to this function. The first for loop in step 2 is giving each Grid track an equal share of the space, but without exceeding their TrackGrowthConstraint values. Because there are different MaxBreadths assigned to the different Grid tracks, the first loop can result in their uneven growth.
If the first loop completes having grown every Grid track to its TrackGrowthConstraint, and there is still SpaceToDistribute, then SubsetOfTracksForGrowthBeyondTrackGrowthConstraint are further grown equally until SpaceToDistribute is exhausted.
Note that Grid tracks considered by this function may have a TrackGrowthConstraint equal to Infinity, which signals that these tracks have not yet been grown by a Grid item. These tracks can therefore be grown without exceeding the TrackGrowthConstraint of the track. By only growing tracks up to their TrackGrowthConstraint value, we can ensure that the grid remains "tight" - that is, that track breadth is as close to the content size of the Grid items inside as possible. Only once all Grid tracks have a CurrentBreadth equal to a TrackGrowthConstraint do we move to the second for loop and grow tracks further, thereby making the Grid element less tight.
- Inputs
-
- SpaceToDistribute: A length to be distributed among the supplied set of Grid tracks.
- TrackGrowthConstraint: A function which given a Grid track returns the maximum breadth of the track, unless the track is in the SubsetOfTracksForGrowthBeyoundTrackGrowthConstraint.
- TracksForGrowth: A set of Grid tracks to be grown up to their TrackGrowthConstraint while SpaceToDistribute remains.
- SubsetOfTracksForGrowthBeyondTrackGrowthConstraint: A subset of Grid tracks from TracksForGrowth that may be grown beyond their TrackGrowthConstraint after all Grid tracks in the TracksForGrowth set have already grown to their TrackGrowthConstraint if there is remaining SpaceToDistribute.
- CurrentBreadth: A function which given a Grid track returns a value to use as a starting point from which to grow this track.
- Algorithm
-
- Sort TracksForGrowth by TrackGrowthConstraint( t ) - CurrentBreadth( t ) ascending (where t is an element in the RecipientTrack set).
- For i = 0 to TracksForGrowth.length - 1
- t = TracksForGrowth[i]
- share = Min ((SpaceToDistribute / ( TracksForGrowth.length - i )), (TrackGrowthConstraint( t ) - CurrentBreadth( t )))
- t.TempBreadth = CurrentBreadth( t ) + share
- SpaceToDistribute -= share
- If SpaceToDistribute > 0
- Let tracks = SubsetOfTracksForGrowthBeyondTrackGrowthConstraint( TracksForGrowth )
- For i = 0 to tracks.length - 1
- t = tracks[i]
- share = SpaceToDistribute / ( tracks.length - i )
- t.TempBreadth += share
- SpaceToDistribute -= share
- For each Grid track t in
TracksForGrowth
- If t.UpdatedTrackBreadth == infinity
- t.UpdatedTrackBreadth = t.TempBreadth
- Else
- t.UpdatedTrackBreadth = Max( t.UpdatedTrackBreadth, t.TempBreadth )
- If t.UpdatedTrackBreadth == infinity
- CalculateNormalizedFlexBreadth
- This method computes a ‘
1fr
’ value, referred to as the NormalizedFlexBreadth, for a set of Grid tracks. The value computed will ensure that when the NormalizedFlexBreadth is multiplied by the flex factors associated with GridTracks, that the UsedBreadths of GridTracks will increase by an amount equal to the maximum of zero and the specified SpaceToFill less the sum of the current UsedBreadths.- Inputs
-
- GridTracks: The set of Grid tracks whose flex sizing functions are considered for the purposes of a computing a NormalizedFlexBreadth that will cause GridTracks to fill SpaceToFill.
- SpaceToFill: The space to be filled by GridTracks.
- Returns
-
- The 1fr value required by GridTracks to fill SpaceToFill.
- Algorithm
-
- allocatedSpace = the sum of the UsedBreadth for each Grid track in GridTracks
- flexTracks = the subset of GridTracks whose MaxTrackSizingFunction is a flexible length
- For each Grid track t in
flexTracks
- t.NormalizedFlexValue = t.UsedBreadth / t.MaxTrackSizingFunction.FractionValue
- Sort flexTracks by their NormalizedFlexValue ascending
- spaceNeededFromFlexTracks = SpaceToFill - allocatedSpace
- currentBandFractionBreadth = accumulatedFractions = 0
- For each Grid track t in
flexTracks
- If t.NormalizedFlexValue > currentBandFractionBreadth
- If t.NormalizedFlexValue * accumulatedFractions > spaceNeededFromFlexTracks then break from for loop
- currentBandFractionBreadth = t.NormalizedFlexValue
- accumulatedFractions += t.MaxTrackSizingFunction.FractionValue
- spaceNeededFromFlexTracks += t.UsedBreadth
- If t.NormalizedFlexValue > currentBandFractionBreadth
- return spaceNeededFromFlexTracks / accumulatedFractions
8.3. Defining the Shrink-to-fit Behavior of Grid Elements
The CSS3 Box Model defines the shrink-to-fit behavior of an element as min(max(preferred minimum width, available width), preferred width), with available width defined in the Box Model spec. Accordingly, for the Grid element we define the preferred minimum width as the sum of the UsedBreadths of the Grid tracks just before step 3 in ComputeUsedBreadthOfGridTracks, and the preferred width as the sum of the UsedBreadths of the Grid tracks after the entire track sizing algorithm has been run with infinite space.9. Fragmenting Grid Layout
Fill this in.
10. Conformance
10.1. Module interactions
This module extends the definition of the ‘display
’ property [CSS21], adding a new block-level and
new inline-level display type, and defining a new type of formatting
context along with properties to control its layout. None of the
properties defined in this module apply to the ‘::first-line
’ or ‘::first-letter
’ pseudo-elements.
10.2. Values
This specification follows the CSS property definition conventions from [CSS21]. Value types not defined in this specification are defined in CSS Level 2 Revision 1 [CSS21]. Other CSS modules may expand the definitions of these value types: for example [CSS3VAL], when combined with this module, expands the definition of the <length> value type as used in this specification.In addition to the property-specific values listed in their definitions, all properties defined in this specification also accept the ‘
inherit
’ keyword as their property value. For
readability it has not been repeated explicitly.
10.3. Document conventions
Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]
Examples in this specification are introduced with the words “for example” or are set apart from the normative text with
class="example"
, like this:
This is an example of an informative example.
Informative notes begin with the word “Note” and are set apart from
the normative text with class="note"
, like this:
Note, this is an informative note.
10.4. Conformance classes
Conformance to CSS Grid Layout Module is defined for three conformance classes:- style sheet
- A CSS style sheet.
- renderer
- A UA that interprets the semantics of a style sheet and renders documents that use them.
- authoring tool
- A UA that writes a style sheet.
A renderer is conformant to CSS Grid Layout Module if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by CSS Grid Layout Module by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)
An authoring tool is conformant to CSS Grid Layout Module if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.
10.5. Partial implementations
So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.10.6. Experimental implementations
To avoid clashes with future CSS features, the CSS2.1 specification reserves a prefixed syntax for proprietary and experimental extensions to CSS.Prior to a specification reaching the Candidate Recommendation stage in the W3C process, all implementations of a CSS feature are considered experimental. The CSS Working Group recommends that implementations use a vendor-prefixed syntax for such features, including those in W3C Working Drafts. This avoids incompatibilities with future changes in the draft.
10.7. Non-experimental implementations
Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.
Further information on submitting testcases and implementation reports can be found from on the CSS Working Group's website at http://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.
Acknowledgements
This specification is made possible by input from Erik Anderson, Rossen Atanassov, Arron Eicholz, Sylvain Galineau, Markus Mielke, John Jansen, Chris Jones, Kathy Kam, Veljko Miljanic, Peter Salas, Christian Stockwell, Eugene Veselov, and the CSS Working Group members. Thanks to Eliot Graff for editorial input.References
Normative references
- [CSS21]
- Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 7 June 2011. W3C Recommendation. URL: http://www.w3.org/TR/2011/REC-CSS2-20110607
- [CSS3-ALIGN]
- Elika J. Etemad. CSS Box Alignment Module Level 3. 12 June 2012. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/2012/WD-css3-align-20120612/
- [CSS3-FLEXBOX]
- Tab Atkins Jr.; Elika J. Etemad; Alex Mogilevsky. CSS Flexible Box Layout Module. 18 September 2012. W3C Candidate Recommendation. (Work in progress.) URL: http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/
- [CSS3-WRITING-MODES]
- Elika J. Etemad; Koji Ishii. CSS Writing Modes Module Level 3. 15 November 2012. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/2012/WD-css3-writing-modes-20121115/
- [CSS3VAL]
- HÃ¥kon Wium Lie; Tab Atkins; Elika J. Etemad. CSS Values and Units Module Level 3. 28 August 2012. W3C Candidate Recommendation. (Work in progress.) URL: http://www.w3.org/TR/2012/CR-css3-values-20120828/
- [RFC2119]
- S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. Internet RFC 2119. URL: http://www.ietf.org/rfc/rfc2119.txt
Other references
- [CSS3GRID]
- Alex Mogilevsky; Markus Mielke. CSS Grid Positioning Module Level 3. 5 September 2007. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/2007/WD-css3-grid-20070905
Index
- Algorithm, 8.2., 8.2., 8.2., 8.2., 8.2.
- authoring tool, 10.4.
- auto, 5.1.
- AvailableSpace, 8.1.
- CalculateNormalizedFlexBreadth, 8.2.
- collapsed, 4.3.
- collapsed grid item, 4.3.
- column, 2.
- ‘
columns
’, 6.3. - ComputeUsedBreadthOfGridTracks, 8.2.
- DistributeSpaceToTracks, 8.2.
- explicit grid, 5.
- <flex>, 5.1.
- free space, 5.1.3.
- grid, 2.
- ‘
grid
’, 3.1. - grid-after, 6.1.
- grid area, 2.3.
- grid-area, 6.2.
- grid-auto-columns, 5.3.
- grid-auto-flow, 6.3.
- grid-auto-rows, 5.3.
- grid-before, 6.1.
- grid column, 2.
- grid-column, 6.2.
- grid column line, 2.2.
- grid container, 3.1.
- grid-definition-columns, 5.1.
- grid-definition-rows, 5.1.
- grid-end, 6.1.
- grid formatting context, 3.1.
- grid item, 4.
- grid layout, 2.
- <grid-line>, 6.1.
- grid line, 2.2.
- grid-placement properties, 6.1.
- grid-placement property, 6.1.
- grid row, 2.
- grid-row, 6.2.
- grid row line, 2.2.
- grid span, 6.1.
- grid-start, 6.1.
- grid-template, 5.2.
- Grid track, 2.1.
- hypothetical 1fr size, 5.1.3.
- implicit grid column, 5.3.
- implicit grid row, 5.3.
- implicit grid track, 5.3.
- ‘
inline-grid
’, 3.1. - Inputs, 8.2., 8.2., 8.2., 8.2., 8.2.
- max-content, 5.1.
- MaxTrackSizingFunction, 8.1.
- min-content, 5.1.
- minmax(min, max), 5.1.
- MinTrackSizingFunction, 8.1.
- named grid area, 5.2.
- none, 5.1.
- ‘
none
’, 6.3. - ‘
order
’, 4.4. - ‘
order
’-modified grid order, 7.5. - participates in baseline alignment, 7.5.
- RemainingSpace, 8.1.
- renderer, 10.4.
- <repeat-function>, 5.1.2.
- ResolveContentBasedTrackSizingFunctions, 8.2.
- ResolveContentBasedTrackSizingFunctionsForItems, 8.2.
- Returns, 8.2.
- row, 2.
- ‘
rows
’, 6.3. - SpanCount, 8.1.
- style sheet
- as conformance class, 10.4.
- <track-breadth>, 5.1.
- <track-list>, 5.1.
- track list, 5.1.
- <track-size>, 5.1.
Property index
Property | Values | Initial | Applies to | Inh. | Percentages | Media |
---|---|---|---|---|---|---|
grid-after | <grid-line> | auto | grid items | no | n/a | visual |
grid-area | <grid-line> [ / <grid-line> ]{0,3} | see individual properties | grid items | see individual properties | see individual properties | visual |
grid-auto-columns | <track-minmax> | auto | grid containers | no | see Track Sizing | visual |
grid-auto-flow | none | rows | columns | none | grid containers | no | n/a | visual |
grid-auto-rows | <track-minmax> | auto | grid containers | no | see Track Sizing | visual |
grid-before | <grid-line> | auto | grid items | no | n/a | visual |
grid-column | <grid-line> [ / <grid-line> ]? | see individual properties | grid items | see individual properties | see individual properties | visual |
grid-definition-columns | none | <track-list> | none | grid containers | no | n/a | visual |
grid-definition-rows | none | <track-list> | none | grid containers | no | n/a | visual |
grid-end | <grid-line> | auto | grid items | no | n/a | visual |
grid-row | <grid-line> [ / <grid-line> ]? | see individual properties | grid items | see individual properties | see individual properties | visual |
grid-start | <grid-line> | auto | grid items | no | n/a | visual |
grid-template | none | <string>+ | none | grid containers | no | n/a | visual |
No comments:
Post a Comment