1. Introduction
This section is not normative
Many types of information (ex: weather readings collected over the past year) are best visually represented in a two-axis grid where rows represent one item of the list (ex: a date, and the various weather properties measured during that day), and where columns represent the successive values of an item’s property (ex: the temperatures measured over the past year).
Sometimes, to make the representation easier to understand, some cells of the grid are used to represent a description or summary of their parent row/column, instead of actual data. This happens more frequently for the cells found on the first row and/or column (called headers) or the cells found on the last row and/or column (called footers).
This kind of tabular data representation is usually known as tables. Tables layout can be abused to render other grid-like representations like calendars or timelines, though authors should prefer other layout modes when the information being represented does not make sense as a data table.
The rendering of tables in HTML has been defined for a long time in the HTML specification. However, its interactions with features defined in CSS remained for a long time undefined. The goal of this specification is to define the expected behavior of user agents supporting both HTML tables and CSS.
Please be aware that some behaviors defined in this document will not be the most logical or useful way of solving the problem they aim to solve, but such behaviors are often the result of compatibility requirements and not a deliberate choice of the editors of this specification. Authors wishing to use more complex layouts are encouraged to rely on more modern CSS modules such as CSS Grid.
1.1. Value Definitions
This specification follows the CSS property definition conventions from [CSS2] using the value definition syntax from [CSS-VALUES-3]. Value types not defined in this specification are defined in CSS Values & Units [CSS-VALUES-3]. Combination with other CSS modules may expand the definitions of these value types.
In addition to the property-specific values listed in their definitions, all properties defined in this specification also accept the CSS-wide keywords as their property value. For readability they have not been repeated explicitly.
2. Content Model
2.1. Table Structure
The CSS table model is based on the HTML4 table model, in which the structure of a table closely parallels the visual layout of the table. In this model, a table consists of an optional caption and any number of rows of cells.
In addition, adjacent rows and columns may be grouped structurally and this grouping can be reflected in presentation (e.g., a border may be drawn around a group of rows).
The table model is said to be "row primary" since authors specify rows, not columns, explicitly in the document language. Columns are derived once all the rows have been specified: the first cell of the first row belongs to the first column and as many other columns as spanning requires (and it creates them if needed), and the following cells of that row each belong to the next available column and as many other columns as spanning requires (creating those if needed); the cells of the following rows each belong to the next available column for that row (taking rowspan into account) and as many other columns as spanning requires (creating those if needed). (see § 3.3 Dimensioning the row/column grid).
To summarize, an instance of the table model consists of:
-
Its table-root containing:
-
Zero, one or more table rows, optionally in row groups,
- Each of them containing one or more table cells
- Optionally: one or more table columns, optionally in column groups
- Optionally: one or more table caption.
-
Zero, one or more table rows, optionally in row groups,
![[see-caption-below]](https://www.downtownmelody.com/_x/ZHJhZnRzLmNzc3dnLm9yZw/images/table-structure.png)
The CSS model does not require that the document language include elements that correspond to each of these components. For document languages (such as XML applications) that do not have pre-defined table elements, authors must map document language elements to table elements. This is done with the display property.
The following display values assign table formatting rules to an arbitrary element:
- table (equivalent to HTML: <table>)
- Specifies that an element defines a table that is block-level when placed in flow layout.
- inline-table (equivalent to HTML: <table>)
- Specifies that an element defines a table that is inline-level when placed in flow layout.
- table-row (equivalent to HTML: <tr>)
- Specifies that an element is a row of cells.
- table-row-group (equivalent to HTML: <tbody>)
-
Specifies that an element groups some amount of rows.
Unless explicitly mentioned otherwise, mentions of table-row-groups in this spec also encompass the specialized table-header-groups and table-footer-groups.
- table-header-group (equivalent to HTML: <thead>)
-
Like table-row-group but, for layout purposes,
the first such row group is always displayed before all other rows and row groups.
If a table owns multiple
display: table-header-group
boxes, only the first is treated as a header; the others are treated as if they haddisplay: table-row-group
. - table-footer-group (equivalent to HTML: <tfoot>)
-
Like table-row-group but, for layout purposes,
the fist such row group is always displayed after all other rows and row groups.
If a table owns multiple
display: table-footer-group
boxes, only the first is treated as a footer; the others are treated as if they haddisplay: table-row-group
. - table-column (equivalent to HTML: <col>)
- Specifies that an element describes a column of cells.
- table-column-group (equivalent to HTML: <colgroup>)
- Specifies that an element groups one or more columns.
- table-cell (equivalent to HTML: <td> or <th>)
- Specifies that an element represents a table cell.
- table-caption (equivalent to HTML: <caption>)
- Specifies a caption for the table. Table captions are positioned between the table margins and its borders.
Note: Replaced elements with a display value of table-row, table-row-group , table-header-group, table-footer-group, table-column, table-column-group, table-cell, and table-caption are treated as inline-level boxes, as per CSS Display 3 § 2.4 Layout-Internal Display Types: the table-* and ruby-* keywords; replaced elements with a display value of table or inline-table behave according to their outer display type, as per CSS Display 3 § 2.1 Outer Display Roles for Flow Layout: the block, inline, and run-in keywords. This is a breaking change from CSS 2.1 but matches implementations.
2.1.1. Terminology
In addition to the table structure display types, the following wording is also being used in this spec:
- table wrapper box
- A block container box generated around table grid boxes to account for any space occupied by each table-caption it owns.
- table grid box
- A block-level box containing the table-internal boxes, excluding its captions.
- table-root element
- An element whose inner display type is table.
- table-non-root box or element
- A proper table child, or a table-cell box.
- table-track box or element
- A table-row, or table-column box.
- table-track-group box or element
- A table-row-group, or table-column-group box.
- proper table child box or element
- A table-track-group, table-track, or table-caption box.
- proper table-row parent box or element
- A table-root or a table-row-group box.
- table-internal box or element
- A table-cell, table-track or table-track-group box.
- tabular container
- A table-row or proper table-row parent box.
- consecutive boxes
- Two sibling boxes are consecutive if they have no intervening siblings other than, optionally, an anonymous inline containing only white spaces. A sequence of sibling boxes is consecutive if each box in the sequence is consecutive to the one before it in the sequence.
- table grid
-
A matrix
containing as many rows and columns
as needed to describe the position of all the table-rows and table-cells of a table-root,
as determined by the grid-dimensioning algorithm.
Each row of the grid might correspond to a table-row, and each column to a table-column.
- slot of the table grid
-
A slot
(r,c)
is an available space created by the intersection of a rowr
and a columnc
in the table grid.Each slot of the table grid is covered by at least one table-cell (some of them anonymous), and at most two. Each table-cell of a table-root covers at least one slot.
Table-cells which cover more than one slot do so densely, meaning the set of slots they cover can always be described as a set of four strictly-positive integers
(rowStart, colStart, rowSpan, colSpan)
such that a slot(r,c)
is covered by the table-cell if and only ifr
lies in the interval betweenrowStart
(included) androwStart+rowSpan
(excluded), andc
lies in the interval betweencolStart
(included) andcolStart+colSpan
(excluded);Such table-cell is said to originate from row
rowStart
and columncolStart
. Also:- A table-cell is said to originate a table-row (resp. table-column) if it originates its corresponding row (resp. column)
- A table-cell is said to originate a table-row-group (resp. table-column-group) if the group contains the cell’s originating row (resp. column)
Such table-cell is said to span all rows
r
and columnsc
matching the above condition. Also:- A table-cell is said to span a table-row (resp. table-column) if it spans its corresponding row (resp. column)
- A table-row (resp. table-column) corresponding to a row (resp. column) is said to span this row (resp. column)
- A table-row (resp. table-column) is said to span all columns of the grid (resp. row)
- A table-row-group (resp. table-column) containing a row (resp. column) is said to span the row (resp. column)
- A table-row-group (resp. table-column) is said to span all columns of the grid (resp. row)
2.2. Fixup
Document languages other than HTML may not contain all the elements in the CSS 2.1 table model. In these cases, the "missing" elements must be assumed in order for the table model to work.
Any table-internal element will automatically generate necessary anonymous table objects around itself, if necessary. Any descendant of a table-root that is not table-internal must have a set of ancestors in the table consisting of at least three nested objects corresponding to a table/inline-table, a table-row, and a table-cell. Missing boxes cause the generation of anonymous boxes according to the following rules:
2.2.1. Fixup Algorithm
For the purposes of these rules, out-of-flow elements are represented as inline elements of zero width and height. Their containing blocks are chosen accordingly.
The following steps are performed in three stages:
-
Remove irrelevant boxes:
The following boxes are discarded as if they weredisplay:none
:- Children of a table-column.
- Children of a table-column-group which are not a table-column.
- Anonymous inline boxes which contain only white space and are between two immediate siblings each of which is a table-non-root box.
-
Anonymous inline boxes which meet all of the following criteria:
- they contain only white space
- they are the first and/or last child of a tabular container
- whose immediate sibling, if any, is a table-non-root box
-
Generate missing child wrappers:
- An anonymous table-row box must be generated around each sequence of consecutive children of a table-root box which are not proper table child boxes. !!Testcase
- An anonymous table-row box must be generated around each sequence of consecutive children of a table-row-group box which are not table-row boxes. !Testcase
- An anonymous table-cell box must be generated around each sequence of consecutive children of a table-row box which are not table-cell boxes. !Testcase
-
Generate missing parents:
- An anonymous table-row box must be generated around each sequence of consecutive table-cell boxes whose parent is not a table-row. Testcase
-
An anonymous table or inline-table box must be generated
around each sequence of consecutive proper table child boxes
which are misparented.
If the box’s parent is an inline, run-in, or ruby box (or any box that would perform inlinification of its children),
then an inline-table box must be generated;
otherwise it must be a table box.
- A table-row is misparented if its parent is neither a table-row-group nor a table-root box.
- A table-column box is misparented if its parent is neither a table-column-group box nor a table-root box.
- A table-row-group, table-column-group, or table-caption box is misparented if its parent is not a table-root box.
- An anonymous table-wrapper box must be generated around each table-root.
Its display type is
inline-block
for inline-table boxes and block for table boxes. The table wrapper box establishes a block formatting context. The table-root box (not the table-wrapper box) is used when doing baseline vertical alignment for an inline-table. The width of the table-wrapper box is the border-edge width of the table grid box inside it. Percentages which would depend on the width and height on the table-wrapper box’s size are relative to the table-wrapper box’s containing block instead, not the table-wrapper box itself.
block
instead.
This transformation happen before the table fixup.
2.2.2. Characteristics of fixup boxes
Beside their display type, the anonymous boxes created for fixup purposes do not receive any specific or default styling, except where otherwise mentioned by this specification.
This means in particular that their computed background is “transparent”, their computed padding is “0px”, their computed border-style is “none”.
It is also worth reminding that an anonymous box inherits property values through the box tree.
2.2.3. Examples
< div class = "row" > < div class = "cell" > George</ div > < div class = "cell" > 4287</ div > < div class = "cell" > 1998</ div > </ div >
Here is the associated styles:
.row{ display : table-row} .cell{ display : table-cell}
After fixup, this will produce layout boxes as though this was the initial HTML:
< table > < tr > < td > George</ td > < td > 4287</ td > < td > 1998</ td > </ tr > </ table >
In this example, three table-cell anonymous boxes are assumed to contain the text in the rows. The text inside
of the divs with a display: table-row
are encapsulated in anonymous inline boxes, as explained in
visual formatting model:
< div class = "inline-table" > < div class = "row" > This is the top row.</ div > < div class = "row" > This is the middle row.