CSS Table Module Level 3

Editor’s Draft,

More details about this document
This version:
https://drafts.csswg.org/css-tables-3/
Latest published version:
https://www.w3.org/TR/css-tables-3/
Previous Versions:
Feedback:
CSSWG Issues Repository
Inline In Spec
Editors:
François Remy (Invited Expert)
Greg Whitworth (Microsoft)
Former Editors:
Bert Bos (W3C)
L. David Baron (Mozilla)
Markus Mielke (Microsoft)
Saloni Mira Rai (Microsoft)
Suggest an Edit for this Spec:
GitHub Editor
Not Ready For Implementation

This spec is not yet ready for implementation. It exists in this repository to record the ideas and promote discussion.

Before attempting to implement this spec, please contact the CSSWG at www-style@w3.org.


Abstract

This CSS module defines a two-dimensional grid-based layout system, optimized for tabular data rendering. In the table layout model, each display node is assigned to an intersection between a set of consecutive rows and a set of consecutive columns, themselves generated from the table structure and sized according to their content.

CSS is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, etc.

Status of this document

This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.

Please send feedback by filing issues in GitHub (preferred), including the spec code “css-tables” in the title, like this: “[css-tables] …summary of comment…”. All issues and comments are archived. Alternately, feedback can be sent to the (archived) public mailing list www-style@w3.org.

This document is governed by the 03 November 2023 W3C Process Document.

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:

[see-caption-below]
Two representations of the structure of a table (tree vs layout)

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 had display: 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 had display: 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 row r and a column c 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 if r lies in the interval between rowStart (included) and rowStart+rowSpan (excluded), and c lies in the interval between colStart (included) and colStart+colSpan (excluded);

Such table-cell is said to originate from row rowStart and column colStart. 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 columns c 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:

  1. Remove irrelevant boxes:
    The following boxes are discarded as if they were display:none:
    1. Children of a table-column.
    2. Children of a table-column-group which are not a table-column.
    3. Anonymous inline boxes which contain only white space and are between two immediate siblings each of which is a table-non-root box.
    4. Anonymous inline boxes which meet all of the following criteria:
  2. Generate missing child wrappers:
    1. 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
    2. 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
    3. 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
  3. Generate missing parents:
    1. An anonymous table-row box must be generated around each sequence of consecutive table-cell boxes whose parent is not a table-row. Testcase
    2. 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. Testcase Testcase !Testcase
    3. 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.
Please note that some layout modes such as flexbox and grid override the display type of their children. These transformations happen before the table fixup.
Please note that the float and position properties sometimes affect the computed value of display. When those properties are used on what should have been table internal boxes, they switch to block instead. This transformation happen before the table fixup.
We have modified the text of this section from CSS 2.2 to make it easier to read. If you find any mistakes due to these changes please file an issue

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.</div>
  <div class="row">This is the bottom row.</div>
</div>
.inline-table { display: inline-table; }
.row { display: table-row; }

This will produce layout boxes as though this was the initial HTML:

<table>
  <tr>
    <td>This is the top row.</td>
  </tr>
  <tr>
    <td>This is the middle row.</td>
  </tr>
  <tr>
    <td>This is the bottom row.</td>
  </tr>
</table>

3. Layout

3.1. Core layout principles

Unlike other block-level boxes, tables do not fill their containing block by default. When their width computes to auto, they behave as if they had fit-content specified instead. This is different from most block-level boxes, which behave as if they had stretch instead.

The min-content width of a table is the width required to fit all of its columns min-content widths and its undistributable spaces.

The max-content width of a table is the width required to fit all of its columns max-content widths and its undistributable spaces.

If the width assigned to a table is larger than its min-content width, the Available Width Distribution algorithm will adjust column widths in consequence.

This section overrides the general-purpose rules that apply to calculating widths described in other specifications. In particular, if the margins of a table are set to 0 and the width to auto, the table will not automatically size to fill its containing block. However, once the used value of width for the table is found (using the algorithms given below) then the other parts of those rules do apply. Therefore, a table can be centered using left and right auto margins, for instance.

3.2. Table layout algorithm

To layout a table, user agents must apply the following actions:

  1. Determine the number of rows/columns the table requires.
    This is done by executing the steps described in § 3.3 Dimensioning the row/column grid.
  2. [A] If the row/column grid has at least one slot:
    1. Ensure each cell slot is occupied by at least one cell.
      This is done by executing the steps described in § 3.4 Missing cells fixup.
    2. Compute the minimum width of each column.
      This is done by executing the steps described in § 3.8 Computing table measures.
    3. Compute the width of the table.
      This is done by executing the steps described in § 3.9.1 Computing the table width.
    4. Distribute the width of the table among columns.
      This is done by executing the steps described in § 3.9.3 Distribution algorithm.
    5. Compute the height of the table.
      This is done by executing the steps described in § 3.10.1 Computing the table height.
    6. Distribute the height of the table among rows.
      This is done by executing the steps described in § 3.10.5 Distribution algorithm.

    [B] Else, an empty table is laid out:

    1. Compute the width of the table.
      This is done by returning the largest value of CAPMIN and the computed width of the table grid box (including borders and paddings) if it is definite (use zero otherwise).
    2. Compute the height of the table.
      This is done by returning the sum of all table-caption heights (their width being set to the table width, with margins taken into consideration appropriately) and the computed height of the table grid box (including borders and paddings) if it is definite (use zero otherwise).
  3. Assign to each table-caption and table-cell their position and size.
    This is done by running the steps of § 3.11 Positioning of cells, captions and other internal table boxes.

The following schema describes the algorithm in a different way, to make it easier to understand.

[see-caption-below]
Overview of the table layout algorithm. Not normative.

3.3. Dimensioning the row/column grid

Like mentioned in the Table structure section, how many rows and columns a table has can be determined from the table structure. Both dimensioning the row/column grid and assigning table-cells their slot(s) in that grid do require running the HTML Algorithms for tables.

3.3.1. HTML Algorithm

CSS Boxes that do not originate from an HTML table element equivalent to their display type need to be converted to their HTML equivalent before we can apply this algorithm, see below. There is no way to specify the span of a cell in css only in this level of the spec, the use of an HTML td element is required to do so.

Apply the HTML5 Table Formatting algorithm, where boxes act like the HTML element equivalent to their display type, and use the attributes of their originating element if and only if it is an HTML element of the same type (otherwise, they act like if they didn’t have any attribute).

<ul class="table">
  <li><b>One</b><i>1</i></li>
  <li><b>Two</b><i>2</i></li>
  <li><b>Three</b><i>3</i></li>
</ul>
<style>
  ul.table { display: table; }
  ul.table > li { display: table-row; }
  ul.table > li > * { display: table-cell; }
</style>

produces the same row/column grid as

<table><tbody>
  <tr>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td></td>
    <td></td>
  </tr>
</tbody></table>
<!-- built using dom api, as this would be fixed by the html parser -->
<grid style="display: table">
  <row style="display: table-row">
    <th rowspan="2">1</th>
    <colgroup style="display: table-cell" span="2" colspan="2">2</colgroup>
  </row>
  <tr>
    <td>A</td>
    <td>B</td>
    <td>C</td>
  </tr>
</grid>

produces the same row/column grid as

<table>
  <tr>
    <th rowspan="2">1</th>
    <td>2</td>
  </tr>
  <tr>
    <td>A</td>
    <td>B</td>
    <td>C</td>
  </tr>
</table>

Note how the second cell of the first row doesn’t have ```colspan=2``` applied, because its originating element is not an HTML TD element.

Testcase. !!Testcase. !Test case. !!Test case. !!Test case.

3.3.2. Track merging

The HTML Table Formatting algorithm sometimes generates more tracks than necessary to layout the table properly. Those tracks have historically been ignored by user agents, so the next step just gets rid of them entirely to avoid dealing with them as exceptions later in the spec. We have tried to maintain the functionality with this change, but if you happen to find any issues due to this change please file an issue.

Modify iteratively the obtained grid by merging consecutive tracks as follows: As long as there exists an eligible track in the obtained row/column grid such that there is no table-column/table-row box defining the said track explicitly, and both the said track and the previous one are spanned by the exact same set of cells, those two tracks must be merged into one single track for the purpose of computing the layout of the table. Reduce the span of the cells that spanned the deleted track by one to compensate, and shift similarly the tracks from which cells originate when needed. (see spanning-ghost-rows test cases)

For tables in auto mode, every track is an eligible track for the purpose of the track-merging algorithm. For tables in fixed mode, only rows are eligible to be merged that way; which means that every column is preserved.

Finally, assign to the table-root grid its correct number of rows and columns (from its mapped element), and to each table-cell its accurate rowStart/colStart/rowSpan/colSpan (from its mapped element).

3.4. Missing cells fixup

The following section clarifies and extends the CSS 2.1 statement saying that missing cells are rendered as if an anonymous table-cell box occupied their position in the grid (a "missing cell" is a slot in the row/column grid that is not covered yet by any table-cell box).

Once the amount of columns in a table is known, any table-row box must be modified such that it owns enough cells to fill all the columns of the table, when taking spans into account. New table-cell anonymous boxes must be appended to its rows content until this condition is met.

3.5. Table layout modes

This section covers the flags which modify the way tables are being laid out. There are three major flags for table layout: table-layout, border-collapse, and caption-side. The border-collapse flag has an optional border-spacing parameter.

3.5.1. The Table-Layout property

Name: table-layout
Value: auto | fixed
Initial: auto
Applies to: table grid boxes
Inherited: no
Percentages: n/a
Computed value: specified keyword
Canonical order: per grammar
Animation type: discrete

A table-root is said to be laid out in fixed mode whenever the computed value of the table-layout property is equal to fixed, and the specified width of the table root is either a <length-percentage>, min-content or fit-content. When the specified width is not one of those values, or if the computed value of the table-layout property is auto, then the table-root is said to be laid out in auto mode.

When a table-root is laid out in fixed mode, the content of its table-cells is ignored for the purpose of width computation, the aggregation algorithm for column sizing considers only table-cells belonging to the first row track, such that layout only depends on the values explicitly specified for the table-columns or cells of the first row of the table; columns with indefinite widths are attributed their fair share of the remaining space after the columns with a definite width have been considered, or 0px if there is no remaining space (see § 3.8.3 Computing Column Measures).

3.5.2. The Border-Collapse property

Name: border-collapse
Value: separate | collapse
Initial: separate
Applies to: table grid boxes
Inherited: yes
Percentages: n/a
Computed value: specified keyword
Canonical order: per grammar
Animation type: discrete

When the border-collapse property has collapse as its value, the borders of adjacent cells are merged together such that each cell draws only half of the shared border. As a result, some other properties like border-spacing will not applied in this case (see § 3.6.2 Overrides applying in collapsed-borders mode), (see § 3.7 Border-collapsing).

A table-root is said to be laid out in collapsed-borders mode in this case. Otherwise, the table-root is said to be laid out in separated-borders mode.

3.5.2.1. The Border-Spacing property
Name: border-spacing
Value: <length>{1,2}
Initial: 0px 0px
Applies to: table grid boxes when border-collapse is separate
Inherited: yes
Percentages: n/a
Computed value: two absolute lengths
Canonical order: per grammar
Animation type: by computed value

The lengths specify the distance that separates adjoining cell borders in separated-borders mode, and must not be strictly negative.

If one length is specified, it gives both the horizontal and vertical spacing. If two are specified, the first gives the horizontal spacing and the second the vertical spacing.

See § 3.8.1 Computing Undistributable Space for details on how this affects the table layout.

3.5.3. The Caption-Side property

Name: caption-side
Value: top | bottom
Initial: top
Applies to: table-caption boxes
Inherited: yes
Percentages: n/a
Computed value: specified keyword
Canonical order: per grammar
Animation type: discrete

This property specifies the position of the caption box with respect to the table grid box. Values have the following meanings:

top
Positions the caption box above the table grid box.
bottom
Positions the caption box below the table grid box.
CSS2 described a different width and horizontal alignment behavior. That behavior was supposed to be introduced in CSS3 using the values top-outside and bottom-outside. #REF
Gecko also supports the "left" and "right" values, but currently this specification is not attempting to define their implementation of said values.
Gecko has a bug when dealing with multiple captions. !Testcase

To align caption content horizontally within the caption box, use the text-align property.

In this example, the caption-side property places captions below tables. The caption will be as wide as the parent of the table, and caption text will be left-justified.

caption {
  caption-side: bottom;
    width: auto;
    text-align: left
}

3.6. Style overrides

Some css properties behave differently inside css tables. The following sections list the exceptions and their effects.

3.6.1. Overrides applying in all modes

The following rules apply to all tables, irrespective of the layout mode in use.

3.6.2. Overrides applying in collapsed-borders mode

When a table is laid out in collapsed-borders mode, the following rules apply:

3.7. Border-collapsing

This entire section is a proposal to make the rendering of collapsed borders sane. As implementations diverge very visibly, it is expected to require more discussion than some other parts. Since browsers handle this so differently, convergence cannot happen without reimplementation. A major concern for this proposal was to support as many cases as possible, and yet keep the effort required for a new implementation of tables as low as possible.

Background: CSS+HTML allow unprecedented combinations of border modes for table junctions, and it makes it difficult to support all cases properly; in fact some combinations are not well-posed problems, so no rendering algorithm could be optimal.

Because they grew from something simple (HTML) to something very complex (HTML+CSS), the current table rendering models (backgrounds and borders) used by web browsers are insane (in the sense they are buggy, not interoperable and not CSSish at all). Many usual CSS assumptions are broken, and renderings diverge widely.

This proposal aims at fixing this situation.

border-collapsing breaking change from 2.1 [Issue #604]

3.7.1. Conflict Resolution for Collapsed Borders

When they are laid out in collapsed-borders mode, table-root and table-cell boxes sharing a border attempt to unify their borders so that they render using the same style, width, and color (whenever this is possible). This is accomplished by running the following algorithm.

3.7.1.1. Conflict Resolution Algorithm for Collapsed Borders
For the purpose of this algorithm, “harmonizing” a set of borders means applying the “Harmonization Algorithm for Collapsed Borders” on the given set of borders, and set those borders' used values to the value resulting from the algorithm, except for cells having a border-image-source different from none: those keep their initial values.

For any table-cell C° of a table-root:

Conformance

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.

Advisements are normative sections styled to evoke special attention and are set apart from other normative text with <strong class="advisement">, like this: UAs MUST provide an accessible alternative.

Tests

Tests relating to the content of this specification may be documented in “Tests” blocks like this one. Any such block is non-normative.


Conformance classes

Conformance to this specification 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 style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.

A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification 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 this specification 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.

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.

Implementations of Unstable and Proprietary Features

To avoid clashes with future stable CSS features, the CSSWG recommends following best practices for the implementation of unstable features and proprietary extensions to CSS.

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.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[COMPOSITING-2]
Compositing and Blending Level 2. Editor's Draft. URL: https://drafts.fxtf.org/compositing-2/
[CSS-BACKGROUNDS-3]
Elika Etemad; Brad Kemper. CSS Backgrounds and Borders Module Level 3. URL: https://drafts.csswg.org/css-backgrounds/
[CSS-BOX-4]
Elika Etemad. CSS Box Model Module Level 4. URL: https://drafts.csswg.org/css-box-4/
[CSS-BREAK-3]
Rossen Atanassov; Elika Etemad. CSS Fragmentation Module Level 3. URL: https://drafts.csswg.org/css-break/
[CSS-COLOR-4]
Tab Atkins Jr.; Chris Lilley; Lea Verou. CSS Color Module Level 4. URL: https://drafts.csswg.org/css-color/
[CSS-DISPLAY-4]
CSS Display Module Level 4. Editor's Draft. URL: https://drafts.csswg.org/css-display-4/
[CSS-GRID-2]
Tab Atkins Jr.; Elika Etemad; Rossen Atanassov. CSS Grid Layout Module Level 2. URL: https://drafts.csswg.org/css-grid-2/
[CSS-INLINE-3]
Dave Cramer; Elika Etemad. CSS Inline Layout Module Level 3. URL: https://drafts.csswg.org/css-inline-3/
[CSS-MASKING-1]
Dirk Schulze; Brian Birtles; Tab Atkins Jr.. CSS Masking Module Level 1. URL: https://drafts.fxtf.org/css-masking-1/
[CSS-OVERFLOW-3]
Elika Etemad; Florian Rivoal. CSS Overflow Module Level 3. URL: https://drafts.csswg.org/css-overflow-3/
[CSS-POSITION-3]
Elika Etemad; Tab Atkins Jr.. CSS Positioned Layout Module Level 3. URL: https://drafts.csswg.org/css-position-3/
[CSS-SIZING-3]
Tab Atkins Jr.; Elika Etemad. CSS Box Sizing Module Level 3. URL: https://drafts.csswg.org/css-sizing-3/
[CSS-TEXT-4]
Elika Etemad; et al. CSS Text Module Level 4. URL: https://drafts.csswg.org/css-text-4/
[CSS-TRANSFORMS-1]
Simon Fraser; et al. CSS Transforms Module Level 1. URL: https://drafts.csswg.org/css-transforms/
[CSS-TRANSFORMS-2]
Tab Atkins Jr.; et al. CSS Transforms Module Level 2. URL: https://drafts.csswg.org/css-transforms-2/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 3. URL: https://drafts.csswg.org/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. URL: https://drafts.csswg.org/css-values-4/
[CSS2]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. URL: https://drafts.csswg.org/css2/
[CSS22]
Bert Bos. Cascading Style Sheets Level 2 Revision 2 (CSS 2.2) Specification. URL: https://drafts.csswg.org/css2/
[FILTER-EFFECTS-1]
Dirk Schulze; Dean Jackson. Filter Effects Module Level 1. URL: https://drafts.fxtf.org/filter-effects-1/
[MEDIAQUERIES-5]
Dean Jackson; et al. Media Queries Level 5. URL: https://drafts.csswg.org/mediaqueries-5/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119

Informative References

[CSS-DISPLAY-3]
Elika Etemad; Tab Atkins Jr.. CSS Display Module Level 3. URL: https://drafts.csswg.org/css-display/
[CSS-TEXT-3]
Elika Etemad; Koji Ishii; Florian Rivoal. CSS Text Module Level 3. URL: https://drafts.csswg.org/css-text-3/

Property Index

Name Value Initial Applies to Inh. %ages Anim­ation type Canonical order Com­puted value
border-collapse separate | collapse separate table grid boxes yes n/a discrete per grammar specified keyword
border-spacing <length>{1,2} 0px 0px table grid boxes when border-collapse is separate yes n/a by computed value per grammar two absolute lengths
caption-side top | bottom top table-caption boxes yes n/a discrete per grammar specified keyword
empty-cells show | hide show table-cell boxes yes n/a discrete per grammar specified keyword
table-layout auto | fixed auto table grid boxes no n/a discrete per grammar specified keyword

Issues Index

border-collapsing breaking change from 2.1 [Issue #604]
Change specificity in harmonization of collapsed borders? [Issue #606]
Handling of intrinsic offsets when in border collapsing mode [Issue #608]
EDITORIAL. The way this describes distribution of widths from colspanning cells is wrong. For min-content and max-content widths it should refer to the rules for distributing excess width to columns for intrinsic width calculation.
EDITORIAL. Import the relevant section of § 3.8.3 Computing Column Measures here.
EDITORIAL. TODO. For current proposal, skip to § 3.10.5 Distribution algorithm.
We need a resolution on what visibility:collapse does. [Issue #478]
This only works in Firefox. It would make it easier to implement position:sticky in the future, though. [Chrome bug] [Interop risk: Firefox bug] [Issue #858]
Can we simplify empty-cells:hide? [Issue #605]
Should we hide the row-group background by saying cells only draw the backgrounds of visibility:visible grouping elements?