<table>: The Table element #
::: section-content
The <table>
HTML element represents tabular data — that
is, information presented in a two-dimensional table comprised of rows
and columns of cells containing data.
:::
Try it #
::: section-content ::: iframe ::: {.output-header .border-rounded-top}
HTML Demo: <table> #
Reset :::
::: {#warning-no-script .warning-container} ::: warning The interactive example cannot be shown because JavaScript is disabled. ::: :::
::: {#warning-mathml-not-supported .warning-container .hidden} ::: warning The interactive example cannot be shown because MathML is not supported by your browser. ::: :::
::: {#editor-container .editor-container .tabbed-standard .hidden .border-rounded-bottom editor-type=“tabbed”} ::: {#tab-container .section .tabs} ::: {#tablist .tab-list role=“tablist”} HTML
CSS
JavaScript :::
::: {#html-panel .section .hidden tabindex=“0” role=“tabpanel” aria-labelledby=“html” aria-hidden=“true”} ::: {#html-editor}
The table header | |
---|---|
The table body | with two columns |
::: {#css-panel .section .hidden tabindex=“0” role=“tabpanel” aria-labelledby=“css” aria-hidden=“true”} ::: {#css-editor} table, td { border: 1px solid #333; }
thead,
tfoot {
background-color: #333;
color: #fff;
}
::: :::
::: {#js-panel .section .hidden tabindex=“0” role=“tabpanel” aria-labelledby=“js” aria-hidden=“true”} ::: {#js-editor} ::: ::: :::
::: {#output .output-container}
Output #
::: :::
::: {.section .console-container .hidden aria-hidden=“true”}
Console Output #
![] clear console
::: {#console .console} ::: :::
::: {#html-output .output .editor-tabbed} %html-content% ::: :::
Content categories | Flow content |
---|---|
Permitted content | In this order: |
Tag omission | None, both the starting and ending tag are mandatory. |
Permitted parents | Any element that accepts flow content |
Implicit ARIA role | table |
Permitted ARIA roles | Any |
DOM interface | HTMLTableElement |
Attributes #
::: section-content This element includes the global attributes. :::
Deprecated attributes #
::: section-content
align
[Deprecated]{.visually-hidden}This enumerated attribute indicates how the table must be aligned inside the containing document. It may have the following values:
left
: the table is displayed on the left side of the document;center
: the table is displayed in the center of the document;right
: the table is displayed on the right side of the document.
Set
margin-left
andmargin-right
to achieve an effect that is similar to the align attribute:left
:margin-right: auto; margin-left: 0;
center
:margin-right: auto; margin-left: auto;
right
:margin-right: 0; margin-left: auto;
bgcolor
[Deprecated]{.visually-hidden}The background color of the table. It is a 6-digit hexadecimal RGB code, prefixed by a '
#
'. One of the predefined color keywords can also be used.To achieve a similar effect, use the CSS
background-color
property.border
[Deprecated]{.visually-hidden}This integer attribute defines, in pixels, the size of the frame surrounding the table. If set to 0, the
frame
attribute is set to void.To achieve a similar effect, use the CSS
border
shorthand property.cellpadding
[Deprecated]{.visually-hidden}This attribute defines the space between the content of a cell and its border, displayed or not. If the cellpadding's length is defined in pixels, this pixel-sized space will be applied to all four sides of the cell's content. If the length is defined using a percentage value, the content will be centered and the total vertical space (top and bottom) will represent this value. The same is true for the total horizontal space (left and right).
To achieve a similar effect, apply the
border-collapse
property to the<table>
element, with its value set to collapse, and thepadding
property to the<td>
elements.cellspacing
[Deprecated]{.visually-hidden}This attribute defines the size of the space between two cells in a percentage value or pixels. The attribute is applied both horizontally and vertically, to the space between the top of the table and the cells of the first row, the left of the table and the first column, the right of the table and the last column and the bottom of the table and the last row.
To achieve a similar effect, apply the
border-spacing
property to the<table>
element.border-spacing
does not have any effect ifborder-collapse
is set to collapse.frame
[Deprecated]{.visually-hidden}This enumerated attribute defines which side of the frame surrounding the table must be displayed.
To achieve a similar effect, use the
border-style
andborder-width
properties.rules
[Deprecated]{.visually-hidden}This enumerated attribute defines where rules, i.e. lines, should appear in a table. It can have the following values:
none
, which indicates that no rules will be displayed; it is the default value;groups
, which will cause the rules to be displayed between row groups (defined by the<thead>
,<tbody>
and<tfoot>
elements) and between column groups (defined by the<col>
and<colgroup>
elements) only;rows
, which will cause the rules to be displayed between rows;cols
, which will cause the rules to be displayed between columns;all
, which will cause the rules to be displayed between rows and columns.
To achieve a similar effect, apply the
border
property to the appropriate<thead>
,<tbody>
,<tfoot>
,<col>
, or<colgroup>
elements.summary
[Deprecated]{.visually-hidden}This attribute defines an alternative text that summarizes the content of the table. Use the
<caption>
element instead.width
[Deprecated]{.visually-hidden}This attribute defines the width of the table. Use the CSS
width
property instead.
::: {#sect1 .notecard .note}
Note: While no HTML specification includes height
as a <table>
attribute, some browsers support a non-standard interpretation of
height
. The unitless value sets a minimum absolute height in pixels.
If set as a percent value, the minimum table height will be relative to
the height of the parent container.
:::
:::
Examples #
Simple table #
::: section-content ::: code-example [html]{.language-name}
<table>
<tr>
<td>John</td>
<td>Doe</td>
</tr>
<tr>
<td>Jane</td>
<td>Doe</td>
</tr>
</table>
:::
Result #
::: {#sect2 .code-example} ::: iframe ::: ::: :::
Further simple examples #
::: section-content ::: code-example [html]{.language-name}
<p>Simple table with header</p>
<table>
<tr>
<th>First name</th>
<th>Last name</th>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
</tr>
<tr>
<td>Jane</td>
<td>Doe</td>
</tr>
</table>
<p>Table with thead, tfoot, and tbody</p>
<table>
<thead>
<tr>
<th>Header content 1</th>
<th>Header content 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Body content 1</td>
<td>Body content 2</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Footer content 1</td>
<td>Footer content 2</td>
</tr>
</tfoot>
</table>
<p>Table with colgroup</p>
<table>
<colgroup span="4"></colgroup>
<tr>
<th>Countries</th>
<th>Capitals</th>
<th>Population</th>
<th>Language</th>
</tr>
<tr>
<td>USA</td>
<td>Washington, D.C.</td>
<td>309 million</td>
<td>English</td>
</tr>
<tr>
<td>Sweden</td>
<td>Stockholm</td>
<td>9 million</td>
<td>Swedish</td>
</tr>
</table>
<p>Table with colgroup and col</p>
<table>
<colgroup>
<col style="background-color: #0f0" />
<col span="2" />
</colgroup>
<tr>
<th>Lime</th>
<th>Lemon</th>
<th>Orange</th>
</tr>
<tr>
<td>Green</td>
<td>Yellow</td>
<td>Orange</td>
</tr>
</table>
<p>Simple table with caption</p>
<table>
<caption>
Awesome caption
</caption>
<tr>
<td>Awesome data</td>
</tr>
</table>
:::
Result #
::: {#sect3 .code-example} ::: iframe ::: ::: :::
Table sorting #
::: section-content
Sorting table rows #
There are no native methods for sorting the rows (
<tr>
elements)
of an HTML table. But using
Array.prototype.slice()
,
Array.prototype.sort()
,
Node.removeChild()
,
and
Node.appendChild()
,
you can implement your own sort()
function to sort an
HTMLCollection
of <tr>
elements.
In the below example, you can see such an example. We are attaching it to the <tbody> element so that it sorts the table cells in order of increasing value, and updates the display to suit.
HTML #
::: code-example [html]{.language-name}
<table>
<tbody>
<tr>
<td>3</td>
</tr>
<tr>
<td>2</td>
</tr>
<tr>
<td>1</td>
</tr>
</tbody>
</table>
:::
JavaScript #
::: code-example [js]{.language-name}
HTMLTableSectionElement.prototype.sort = function (cb) {
Array.from(this.rows)
.sort(cb)
.forEach((e) => this.appendChild(this.removeChild(e)));
};
document
.querySelector("table")
.tBodies[0].sort((a, b) => a.textContent.localeCompare(b.textContent));
:::
Result #
::: {#sect4 .code-example} ::: iframe ::: :::
Sorting rows with a click on the th element #
The following example adds an event handler to every <th>
element of
every <table>
in the document
; it sorts all the <tbody>
's rows,
basing the sorting on the td
cells contained in the rows.
::: {#sect5 .notecard .note}
Note: This solution assumes that the <td>
elements are populated
by raw text with no descendant elements.
:::
HTML #
::: code-example [html]{.language-name}
<table>
<thead>
<tr>
<th>Numbers</th>
<th>Letters</th>
</tr>
</thead>
<tbody>
<tr>
<td>3</td>
<td>A</td>
</tr>
<tr>
<td>2</td>
<td>B</td>
</tr>
<tr>
<td>1</td>
<td>C</td>
</tr>
</tbody>
</table>
:::
JavaScript #
::: code-example [js]{.language-name}
const allTables = document.querySelectorAll("table");
for (const table of allTables) {
const tBody = table.tBodies[0];
const rows = Array.from(tBody.rows);
const headerCells = table.tHead.rows[0].cells;
for (const th of headerCells) {
const cellIndex = th.cellIndex;
th.addEventListener("click", () => {
rows.sort((tr1, tr2) => {
const tr1Text = tr1.cells[cellIndex].textContent;
const tr2Text = tr2.cells[cellIndex].textContent;
return tr1Text.localeCompare(tr2Text);
});
tBody.append(...rows);
});
}
}
:::
Result #
::: {#sect6 .code-example} ::: iframe ::: ::: :::
Displaying large tables in small spaces #
::: section-content A common issue with tables on the web is that they don't natively work very well on small screens when the amount of content is large, and the way to make them scrollable isn't obvious, especially when the markup may come from a CMS and cannot be modified to have a wrapper.
This example provides one way to display tables in small spaces. We've hidden the HTML content as it is very large, and there is nothing remarkable about it. The CSS is more useful to inspect in this example.
When looking at these styles you'll notice that table's
display
property has been set to block
. While this allows scrolling, the table
loses some of its integrity, and table cells try to become as small as
possible. To mitigate this issue we've set
white-space
to nowrap
on the <tbody>
. However, we don't do this for the
<thead>
to avoid long titles forcing columns to be wider than they
need to be to display the data.
To keep the table headers on the page while scrolling down we've set
position
to sticky on the <th>
elements. Note that we have not set
border-collapse
to collapse
, as if we do the header cannot be separated correctly from
the rest of the table.
::: code-example [css]{.language-name}
table,
th,
td {
border: 1px solid;
}
table {
width: 100%;
max-width: 400px;
height: 240px;
margin: 0 auto;
display: block;
overflow-x: auto;
border-spacing: 0;
}
tbody {
white-space: nowrap;
}
th,
td {
padding: 5px 10px;
border-top-width: 0;
border-left-width: 0;
}
th {
position: sticky;
top: 0;
background: #fff;
vertical-align: bottom;
}
th:last-child,
td:last-child {
border-right-width: 0;
}
tr:last-child td {
border-bottom-width: 0;
}
:::
Result #
::: {#sect7 .code-example} ::: iframe ::: ::: :::
Accessibility concerns #
Captions #
::: section-content
By supplying a
<caption>
element whose value clearly and
concisely describes the table's purpose, it helps the people decide if
they need to read the rest of the table content or skip over it.
This helps people navigating with the aid of assistive technology such as a screen reader, people experiencing low vision conditions, and people with cognitive concerns.
- MDN Adding a caption to your table with <caption>
- Caption & Summary • Tables • W3C WAI Web Accessibility Tutorials{target="_blank"} :::
Scoping rows and columns #
::: section-content
The
scope
attribute on header elements is redundant in
simple contexts, because scope is inferred. However, some assistive
technologies may fail to draw correct inferences, so specifying header
scope may improve user experiences. In complex tables, scope can be
specified to provide necessary information about the cells related to a
header.
Examples #
::: code-example [html]{.language-name}
<table>
<caption>
Color names and values
</caption>
<tbody>
<tr>
<th scope="col">Name</th>
<th scope="col">HEX</th>
<th scope="col">HSLa</th>
<th scope="col">RGBa</th>
</tr>
<tr>
<th scope="row">Teal</th>
<td><code>#51F6F6</code></td>
<td><code>hsl(180 90% 64% / 1)</code></td>
<td><code>rgb(81 246 246 / 1)</code></td>
</tr>
<tr>
<th scope="row">Goldenrod</th>
<td><code>#F6BC57</code></td>
<td><code>hsl(38 90% 65% / 1)</code></td>
<td><code>rgba(246 188 87 / 1)</code></td>
</tr>
</tbody>
</table>
:::
Result #
::: {#sect8 .code-example} ::: iframe ::: :::
Providing a declaration of scope="col"
on a
<th>
element will
help describe that the cell is at the top of a column. Providing a
declaration of scope="row"
on a
<th>
element will help
describe that the cell is the first in a row.
- MDN Tables for visually impaired users
- Tables with two headers • Tables • W3C WAI Web Accessibility Tutorials{target="_blank"}
- Tables with irregular headers • Tables • W3C WAI Web Accessibility Tutorials{target="_blank"}
- H63: Using the scope attribute to associate header cells and data cells in data tables | W3C Techniques for WCAG 2.0{target="_blank"} :::
Complicated tables #
::: section-content
Assistive technology such as screen readers may have difficulty parsing
tables that are so complex that header cells can't be associated in a
strictly horizontal or vertical way. This is typically indicated by the
presence of the
colspan
and
rowspan
attributes.
Ideally, consider alternate ways to present the table's content,
including breaking it apart into a collection of smaller, related tables
that don't have to rely on using the colspan
and rowspan
attributes. In addition to helping people who use assistive technology
understand the table's content, this may also benefit people with
cognitive concerns who may have difficulty understanding the
associations the table layout is describing.
If the table cannot be broken apart, use a combination of the
id
and
headers
attributes
to programmatically associate each table cell with the header(s) the
cell is associated with.
- MDN Tables for visually impaired users
- Tables with multi-level headers • Tables • W3C WAI Web Accessibility Tutorials{target="_blank"}
- H43: Using id and headers attributes to associate data cells with header cells in data tables | Techniques for W3C WCAG 2.0{target="_blank"} :::
Specifications #
::: _table #
Specification #
HTML Standard
[#
the-table-element]{.small}
:::
Browser compatibility #
::: _table Desktop Mobile
Chrome Edge Firefox Internet Explorer Opera Safari WebView Android Chrome Android Firefox for Android Opera Android Safari on IOS Samsung Internet
table
1 12 1 Yes ≤12.1 1 4.4 18 4 ≤12.1 1 1.0
align
1 12 1 Yes ≤12.1 1 4.4 18 4 ≤12.1 1 1.0
bgcolor
1 12 1 Yes ≤12.1 1 4.4 18 4 ≤12.1 1 1.0
border
1 12 1 Yes ≤12.1 1 4.4 18 4 ≤12.1 1 1.0
cellpadding
1 12 1 Yes ≤12.1 1 4.4 18 4 ≤12.1 1 1.0
cellspacing
1 12 1 Yes ≤12.1 1 4.4 18 4 ≤12.1 1 1.0
frame
1 12 1 Yes ≤12.1 1 4.4 18 4 ≤12.1 1 1.0
rules
1 12 1 Yes ≤12.1 1 4.4 18 4 ≤12.1 1 1.0
summary
1 12 1 Yes ≤12.1 1 4.4 18 4 ≤12.1 1 1.0
width
1 12 1 Yes ≤12.1 1 4.4 18 4 ≤12.1 1 1.0
:::
See also #
::: section-content
- HTML data table tutorial
- CSS properties that may be especially useful to style the
<table>
element:width
to control the width of the table;border
,border-style
,border-color
,border-width
,border-collapse
,border-spacing
to control the aspect of cell borders, rules, and frame;margin
andpadding
to style the individual cell content;text-align
andvertical-align
to define the alignment of text and cell content. :::
::: _attribution
© 2005–2023 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5
or later.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table{._attribution-link}
:::