Living Standard — Last Updated 8 September 2025
table
elementcaption
elementcolgroup
elementcol
elementtbody
elementthead
elementtfoot
elementtr
elementtd
elementth
elementtd
and th
elementstable
elementSupport in all current engines.
Support in all current engines.
caption
element, followed by zero or more
colgroup
elements, followed optionally by a thead
element, followed by
either zero or more tbody
elements or one or more tr
elements, followed
optionally by a tfoot
element, optionally intermixed with one or more
script-supporting elements.[Exposed =Window ]
interface HTMLTableElement : HTMLElement {
[HTMLConstructor ] constructor ();
[CEReactions ] attribute HTMLTableCaptionElement ? caption ;
HTMLTableCaptionElement createCaption ();
[CEReactions ] undefined deleteCaption ();
[CEReactions ] attribute HTMLTableSectionElement ? tHead ;
HTMLTableSectionElement createTHead ();
[CEReactions ] undefined deleteTHead ();
[CEReactions ] attribute HTMLTableSectionElement ? tFoot ;
HTMLTableSectionElement createTFoot ();
[CEReactions ] undefined deleteTFoot ();
[SameObject ] readonly attribute HTMLCollection tBodies ;
HTMLTableSectionElement createTBody ();
[SameObject ] readonly attribute HTMLCollection rows ;
HTMLTableRowElement insertRow (optional long index = -1);
[CEReactions ] undefined deleteRow (long index );
// also has obsolete members
};
The table
element represents data with more than one dimension, in
the form of a table.
The table
element takes part in the table
model. Tables have rows, columns, and cells given by their descendants. The rows and
columns form a grid; a table's cells must completely cover that grid without overlap.
Precise rules for determining whether this conformance requirement is met are described in the description of the table model.
Authors are encouraged to provide information describing how to interpret complex tables. Guidance on how to provide such information is given below.
Tables must not be used as layout aids. Historically, some web authors have misused tables in HTML as a way to control their page layout. This usage is non-conforming, because tools attempting to extract tabular data from such documents would obtain very confusing results. In particular, users of accessibility tools like screen readers are likely to find it very difficult to navigate pages with tables used for layout.
There are a variety of alternatives to using HTML tables for layout, such as CSS grid layout, CSS flexible box layout ("flexbox"), CSS multi-column layout, CSS positioning, and the CSS table model. [CSS]
Tables can be complicated to understand and navigate. To help users with this, user agents should clearly delineate cells in a table from each other, unless the user agent has classified the table as a (non-conforming) layout table.
Authors and implementers are encouraged to consider using some of the table design techniques described below to make tables easier to navigate for users.
User agents, especially those that do table analysis on arbitrary content, are encouraged to find heuristics to determine which tables actually contain data and which are merely being used for layout. This specification does not define a precise heuristic, but the following are suggested as possible indicators:
Feature | Indication |
---|---|
The use of the role attribute with the value presentation
| Probably a layout table |
The use of the non-conforming border attribute with the non-conforming value 0
| Probably a layout table |
The use of the non-conforming cellspacing and
cellpadding attributes with the value 0
| Probably a layout table |
The use of caption , thead , or th elements
| Probably a non-layout table |
The use of the headers and scope attributes
| Probably a non-layout table |
The use of the non-conforming border attribute with a value other than 0
| Probably a non-layout table |
Explicit visible borders set using CSS | Probably a non-layout table |
The use of the summary attribute
| Not a good indicator (both layout and non-layout tables have historically been given this attribute) |
It is quite possible that the above suggestions are wrong. Implementers are urged to provide feedback elaborating on their experiences with trying to create a layout table detection heuristic.
If a table
element has a (non-conforming) summary
attribute, and the user agent has not classified the
table as a layout table, the user agent may report the contents of that attribute to the user.
table.caption [ = value ]
Support in all current engines.
Returns the table's caption
element.
Can be set, to replace the caption
element.
caption = table.createCaption()
HTMLTableElement/createCaption
Support in all current engines.
Ensures the table has a caption
element, and returns it.
table.deleteCaption()
HTMLTableElement/deleteCaption
Support in all current engines.
Ensures the table does not have a caption
element.
table.tHead [ = value ]
Support in all current engines.
Returns the table's thead
element.
Can be set, to replace the thead
element. If the new value is not a
thead
element, throws a "HierarchyRequestError
"
DOMException
.
thead = table.createTHead()
Support in all current engines.
Ensures the table has a thead
element, and returns it.
table.deleteTHead()
Support in all current engines.
Ensures the table does not have a thead
element.
table.tFoot [ = value ]
Support in all current engines.
Returns the table's tfoot
element.
Can be set, to replace the tfoot
element. If the new value is not a
tfoot
element, throws a "HierarchyRequestError
"
DOMException
.
tfoot = table.createTFoot()
Support in all current engines.
Ensures the table has a tfoot
element, and returns it.
table.deleteTFoot()
Support in all current engines.
Ensures the table does not have a tfoot
element.
table.tBodies
Support in all current engines.
Returns an HTMLCollection
of the tbody
elements of the
table.
tbody = table.createTBody()
Support in all current engines.
Creates a tbody
element, inserts it into the table, and returns it.
table.rows
Support in all current engines.
Returns an HTMLCollection
of the tr
elements of the
table.
tr = table.insertRow([ index ])
Support in all current engines.
Creates a tr
element, along with a tbody
if required, inserts them
into the table at the position given by the argument, and returns the tr
.
The position is relative to the rows in the table. The index −1, which is the default if the argument is omitted, is equivalent to inserting at the end of the table.
If the given position is less than −1 or greater than the number of rows, throws an
"IndexSizeError
" DOMException
.
table.deleteRow(index)
Support in all current engines.
Removes the tr
element with the given position in the table.
The position is relative to the rows in the table. The index −1 is equivalent to deleting the last row of the table.
If the given position is less than −1 or greater than the index of the last row, or if
there are no rows, throws an "IndexSizeError
"
DOMException
.
In all of the following attribute and method definitions, when an element is to be
table-created, that means to create an element given the
table
element's node document, the given local name, and the HTML
namespace.
The caption
IDL attribute must return, on getting, the first caption
element child of the
table
element, if any, or null otherwise. On setting, the first caption
element child of the table
element, if any, must be removed, and the new value, if
not null, must be inserted as the first node of the table
element.
The createCaption()
method must return the first
caption
element child of the table
element, if any; otherwise a new
caption
element must be table-created, inserted as the first node of the
table
element, and then returned.
The deleteCaption()
method must remove the first
caption
element child of the table
element, if any.
The tHead
IDL
attribute must return, on getting, the first thead
element child of the
table
element, if any, or null otherwise. On setting, if the new value is null or a
thead
element, the first thead
element child of the table
element, if any, must be removed, and the new value, if not null, must be inserted immediately
before the first element in the table
element that is neither a caption
element nor a colgroup
element, if any, or at the end of the table if there are no
such elements. If the new value is neither null nor a thead
element, then a
"HierarchyRequestError
" DOMException
must be thrown
instead.
The createTHead()
method must return the first
thead
element child of the table
element, if any; otherwise a new
thead
element must be table-created and inserted immediately before the
first element in the table
element that is neither a caption
element nor
a colgroup
element, if any, or at the end of the table if there are no such elements,
and then that new element must be returned.
The deleteTHead()
method must remove the first
thead
element child of the table
element, if any.
The tFoot
IDL
attribute must return, on getting, the first tfoot
element child of the
table
element, if any, or null otherwise. On setting, if the new value is null or a
tfoot
element, the first tfoot
element child of the table
element, if any, must be removed, and the new value, if not null, must be inserted at the end of
the table. If the new value is neither null nor a tfoot
element, then a
"HierarchyRequestError
" DOMException
must be thrown
instead.
The createTFoot()
method must return the first
tfoot
element child of the table
element, if any; otherwise a new
tfoot
element must be table-created and inserted at the end of the
table, and then that new element must be returned.
The deleteTFoot()
method must remove the first
tfoot
element child of the table
element, if any.
The tBodies
attribute must return an HTMLCollection
rooted at the table
node, whose
filter matches only tbody
elements that are children of the table
element.
The createTBody()
method must table-create a new tbody
element, insert it immediately
after the last tbody
element child in the table
element, if any, or at
the end of the table
element if the table
element has no
tbody
element children, and then must return the new tbody
element.
The rows
attribute must return an HTMLCollection
rooted at the table
node, whose
filter matches only tr
elements that are either children of the table
element, or children of thead
, tbody
, or tfoot
elements
that are themselves children of the table
element. The elements in the collection
must be ordered such that those elements whose parent is a thead
are included first,
in tree order, followed by those elements whose parent is either a table
or tbody
element, again in tree order, followed finally by those
elements whose parent is a tfoot
element, still in tree order.
The behavior of the insertRow(index)
method depends on the state
of the table. When it is called, the method must act as required by the first item in the
following list of conditions that describes the state of the table and the index
argument:
rows
collection:IndexSizeError
"
DOMException
.rows
collection has zero elements in it, and the
table
has no tbody
elements in it:tbody
element, then table-create a tr
element, then
append the tr
element to the tbody
element, then append the
tbody
element to the table
element, and finally return the
tr
element.rows
collection has zero elements in it:tr
element,
append it to the last tbody
element in the table, and return the tr
element.rows
collection:tr
element,
and append it to the parent of the last tr
element in the rows
collection. Then, the newly created tr
element
must be returned.tr
element,
insert it immediately before the indexth tr
element in the rows
collection, in the same parent, and finally must return the
newly created tr
element.When the deleteRow(index)
method is called, the user
agent must run the following steps:
If index is less than −1 or greater than or equal to the number of
elements in the rows
collection, then throw an
"IndexSizeError
" DOMException
.
If index is −1, then remove
the last element in the rows
collection from its parent, or
do nothing if the rows
collection is empty.
Otherwise, remove the indexth element
in the rows
collection from its parent.
Here is an example of a table being used to mark up a Sudoku puzzle. Observe the lack of headers, which are not necessary in such a table.
< style >
# sudoku { border-collapse : collapse ; border : solid thick ; }
# sudoku colgroup , table # sudoku tbody { border : solid medium ; }
# sudoku td { border : solid thin ; height : 1.4 em ; width : 1.4 em ; text-align : center ; padding : 0 ; }
</ style >
< h1 > Today's Sudoku</ h1 >
< table id = "sudoku" >
< colgroup >< col >< col >< col >
< colgroup >< col >< col >< col >
< colgroup >< col >< col >< col >
< tbody >
< tr > < td > 1 < td > < td > 3 < td > 6 < td > < td > 4 < td > 7 < td > < td > 9
< tr > < td > < td > 2 < td > < td > < td > 9 < td > < td > < td > 1 < td >
< tr > < td > 7 < td > < td > < td > < td > < td > < td > < td > < td > 6
< tbody >
< tr > < td > 2 < td > < td > 4 < td > < td > 3 < td > < td > 9 < td > < td > 8
< tr > < td > < td > < td > < td > < td > < td > < td > < td > < td >
< tr > < td > 5 < td > < td > < td > 9 < td > < td > 7 < td > < td > < td > 1
< tbody >
< tr > < td > 6 < td > < td > < td > < td > 5 < td > < td > < td > < td > 2
< tr > < td > < td > < td > < td > < td > 7 < td > < td > < td > < td >
< tr > < td > 9 < td > < td > < td > 8 < td > < td > 2 < td > < td > < td > 5
</ table >
For tables that consist of more than just a grid of cells with headers in the first row and headers in the first column, and for any table in general where the reader might have difficulty understanding the content, authors should include explanatory information introducing the table. This information is useful for all users, but is especially useful for users who cannot see the table, e.g. users of screen readers.
Such explanatory information should introduce the purpose of the table, outline its basic cell structure, highlight any trends or patterns, and generally teach the user how to use the table.
For instance, the following table:
Negative | Characteristic | Positive |
---|---|---|
Sad | Mood | Happy |
Failing | Grade | Passing |
...might benefit from a description explaining the way the table is laid out, something like "Characteristics are given in the second column, with the negative side in the left column and the positive side in the right column".
There are a variety of ways to include this information, such as:
< p > In the following table, characteristics are given in the second
column, with the negative side in the left column and the positive
side in the right column.</ p >
< table >
< caption > Characteristics with positive and negative sides</ caption >
< thead >
< tr >
< th id = "n" > Negative
< th > Characteristic
< th > Positive
< tbody >
< tr >
< td headers = "n r1" > Sad
< th id = "r1" > Mood
< td > Happy
< tr >
< td headers = "n r2" > Failing
< th id = "r2" > Grade
< td > Passing
</ table >
caption
< table >
< caption >
< strong > Characteristics with positive and negative sides.</ strong >
< p > Characteristics are given in the second column, with the
negative side in the left column and the positive side in the right
column.</ p >
</ caption >
< thead >
< tr >
< th id = "n" > Negative
< th > Characteristic
< th > Positive
< tbody >
< tr >
< td headers = "n r1" > Sad
< th id = "r1" > Mood
< td > Happy
< tr >
< td headers = "n r2" > Failing
< th id = "r2" > Grade
< td > Passing
</ table >
caption
, in a details
element< table >
< caption >
< strong > Characteristics with positive and negative sides.</ strong >
< details >
< summary > Help</ summary >
< p > Characteristics are given in the second column, with the
negative side in the left column and the positive side in the right
column.</ p >
</ details >
</ caption >
< thead >
< tr >
< th id = "n" > Negative
< th > Characteristic
< th > Positive
< tbody >
< tr >
< td headers = "n r1" > Sad
< th id = "r1" > Mood
< td > Happy
< tr >
< td headers = "n r2" > Failing
< th id = "r2" > Grade
< td > Passing
</ table >
figure
< figure >
< figcaption > Characteristics with positive and negative sides</ figcaption >
< p > Characteristics are given in the second column, with the
negative side in the left column and the positive side in the right
column.</ p >
< table >
< thead >
< tr >
< th id = "n" > Negative
< th > Characteristic
< th > Positive
< tbody >
< tr >
< td headers = "n r1" > Sad
< th id = "r1" > Mood
< td > Happy
< tr >
< td headers = "n r2" > Failing
< th id = "r2" > Grade
< td > Passing
</ table >
</ figure >
figure
's figcaption
< figure >
< figcaption >
< strong > Characteristics with positive and negative sides</ strong >
< p > Characteristics are given in the second column, with the
negative side in the left column and the positive side in the right
column.</ p >
</ figcaption >
< table >
< thead >
< tr >
< th id = "n" > Negative
< th > Characteristic
< th > Positive
< tbody >
< tr >
< td headers = "n r1" > Sad
< th id = "r1" > Mood
< td > Happy
< tr >
< td headers = "n r2" > Failing
< th id = "r2" > Grade
< td > Passing
</ table >
</ figure >
Authors may also use other techniques, or combinations of the above techniques, as appropriate.
The best option, of course, rather than writing a description explaining the way the table is laid out, is to adjust the table such that no explanation is needed.
In the case of the table used in the examples above, a simple rearrangement of the table so
that the headers are on the top and left sides removes the need for an explanation as well as
removing the need for the use of headers
attributes:
< table >
< caption > Characteristics with positive and negative sides</ caption >
< thead >
< tr >
< th > Characteristic
< th > Negative
< th > Positive
< tbody >
< tr >
< th > Mood
< td > Sad
< td > Happy
< tr >
< th > Grade
< td > Failing
< td > Passing
</ table >
Good table design is key to making tables more readable and usable.
In visual media, providing column and row borders and alternating row backgrounds can be very effective to make complicated tables more readable.
For tables with large volumes of numeric content, using monospaced fonts can help users see patterns, especially in situations where a user agent does not render the borders. (Unfortunately, for historical reasons, not rendering borders on tables is a common default.)
In speech media, table cells can be distinguished by reporting the corresponding headers before reading the cell's contents, and by allowing users to navigate the table in a grid fashion, rather than serializing the entire contents of the table in source order.
Authors are encouraged to use CSS to achieve these effects.
User agents are encouraged to render tables using these techniques whenever the page does not use CSS and the table is not classified as a layout table.
caption
elementSupport in all current engines.
Support in all current engines.
table
element.table
elements.caption
element's end tag can be omitted if
the caption
element is not immediately followed by ASCII whitespace or a
comment.[Exposed =Window ]
interface HTMLTableCaptionElement : HTMLElement {
[HTMLConstructor ] constructor ();
// also has obsolete members
};
The caption
element represents the title of the table
that is its parent, if it has a parent and that is a table
element.
The caption
element takes part in the table model.
When a table
element is the only content in a figure
element other
than the figcaption
, the caption
element should be omitted in favor of
the figcaption
.
A caption can introduce context for a table, making it significantly easier to understand.
Consider, for instance, the following table:
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
2 | 3 | 4 | 5 | 6 | 7 | 8 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
4 | 5 | 6 | 7 | 8 | 9 | 10 |
5 | 6 | 7 | 8 | 9 | 10 | 11 |
6 | 7 | 8 | 9 | 10 | 11 | 12 |
In the abstract, this table is not clear. However, with a caption giving the table's number (for reference in the main prose) and explaining its use, it makes more sense:
< caption >
< p > Table 1.
< p > This table shows the total score obtained from rolling two
six-sided dice. The first row represents the value of the first die,
the first column the value of the second die. The total is given in
the cell that corresponds to the values of the two dice.
</ caption >
This provides the user with more context:
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
2 | 3 | 4 | 5 | 6 | 7 | 8 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
4 | 5 | 6 | 7 | 8 | 9 | 10 |
5 | 6 | 7 | 8 | 9 | 10 | 11 |
6 | 7 | 8 | 9 | 10 | 11 | 12 |
colgroup
elementSupport in all current engines.
Support in all current engines.
table
element, after any
caption
elements and before any thead
,
tbody
, tfoot
, and tr
elements.span
attribute is present: Nothing.span
attribute is absent: Zero or more col
and template
elements.colgroup
element's start tag can be
omitted if the first thing inside the colgroup
element is a col
element,
and if the element is not immediately preceded by another colgroup
element whose
end tag has been omitted. (It can't be omitted if the element
is empty.)colgroup
element's end tag can be omitted
if the colgroup
element is not immediately followed by ASCII whitespace
or a comment.span
— Number of columns spanned by the element
[Exposed =Window ]
interface HTMLTableColElement : HTMLElement {
[HTMLConstructor ] constructor ();
[CEReactions , Reflect , ReflectDefault=1, ReflectRange=(1, 1000)] attribute unsigned long span ;
// also has obsolete members
};
The colgroup
element represents a group of one or more columns in the table
that is its parent, if it has a
parent and that is a table
element.
If the colgroup
element contains no col
elements, then the element
may have a span
content attribute specified, whose value must be a valid non-negative integer greater
than zero and less than or equal to 1000.
The colgroup
element and its span
attribute take part in the table model.
col
elementSupport in all current engines.
colgroup
element that doesn't have
a span
attribute.span
— Number of columns spanned by the element
HTMLTableColElement
, as defined for colgroup
elements.If a col
element has a parent and that is a colgroup
element that
itself has a parent that is a table
element, then the col
element
represents one or more columns in the column group represented by that colgroup
.
The element may have a span
content attribute specified, whose value must be a
valid non-negative integer greater than zero and less than or equal to 1000.
The col
element and its span
attribute take
part in the table model.
tbody
elementSupport in all current engines.
Support in all current engines.
table
element, after any
caption
, colgroup
, and
thead
elements, but only if there are no
tr
elements that are children of the
table
element.tr
and script-supporting elements.tbody
element's start tag can be omitted
if the first thing inside the tbody
element is a tr
element, and if the
element is not immediately preceded by a tbody
, thead
, or
tfoot
element whose end tag has been omitted. (It
can't be omitted if the element is empty.)tbody
element's end tag can be omitted if
the tbody
element is immediately followed by a tbody
or
tfoot
element, or if there is no more content in the parent element.[Exposed =Window ]
interface HTMLTableSectionElement : HTMLElement {
[HTMLConstructor ] constructor ();
[SameObject ] readonly attribute HTMLCollection rows ;
HTMLTableRowElement insertRow (optional long index = -1);
[CEReactions ] undefined deleteRow (long index );
// also has obsolete members
};
The
HTMLTableSectionElement
interface is also used for thead
and
tfoot
elements.
The tbody
element represents a block of rows that consist of a
body of data for the parent table
element, if the tbody
element has a
parent and it is a table
.
The tbody
element takes part in the table model.
tbody.rows
Returns an HTMLCollection
of the tr
elements of the table
section.
tr = tbody.insertRow([ index ])
Creates a tr
element, inserts it into the table section at the position given by
the argument, and returns the tr
.
The position is relative to the rows in the table section. The index −1, which is the default if the argument is omitted, is equivalent to inserting at the end of the table section.
If the given position is less than −1 or greater than the number of rows, throws an
"IndexSizeError
" DOMException
.
tbody.deleteRow(index)
Removes the tr
element with the given position in the table section.
The position is relative to the rows in the table section. The index −1 is equivalent to deleting the last row of the table section.
If the given position is less than −1 or greater than the index of the last row, or if
there are no rows, throws an "IndexSizeError
"
DOMException
.
The rows
attribute must return an HTMLCollection
rooted at this element, whose filter matches only tr
elements that are children of
this element.
The insertRow(index)
method must act as
follows:
If index is less than −1 or greater than the number of elements in the
rows
collection, throw an
"IndexSizeError
" DOMException
.
Let table row be the result of creating an
element given this element's node document, "tr
", and
the HTML namespace.
If index is −1 or equal to the number of items in the rows
collection, then append table row to this element.
Otherwise, insert table row as a
child of this element, immediately before the indexth