<table>: The Table element

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

HTML Demo: <table>

<table>
    <thead>
        <tr>
            <th colspan="2">The table header</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>The table body</td>
            <td>with two columns</td>
        </tr>
    </tbody>
</table>
x
 
<table>
    <thead>
        <tr>
            <th colspan="2">The table header</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>The table body</td>
            <td>with two columns</td>
        </tr>
    </tbody>
</table>

Output

The table header
The table body with two columns
Content categories Flow content
Permitted content In this order:
  1. an optional <caption> element,
  2. zero or more <colgroup> elements,
  3. an optional <thead> element,
  4. either one of the following:
    • zero or more <tbody> elements
    • one or more <tr> elements
  5. an optional <tfoot> element
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

This element includes the global attributes.

Deprecated attributes

align Deprecated
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 and margin-right to auto or margin to 0 auto to achieve an effect that is similar to the align attribute.
bgcolor Deprecated
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
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
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 the padding property to the <td> elements.
cellspacing Deprecated
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 if border-collapse is set to collapse.
frame Deprecated
This enumerated attribute defines which side of the frame surrounding the table must be displayed.
To achieve a similar effect, use the border-style and border-width properties.
rules Deprecated
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;
  • columns, 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
This attribute defines an alternative text that summarizes the content of the table. Use the <caption> element instead.
width Deprecated
This attribute defines the width of the table. Use the CSS width property instead.

Examples

Simple table

<table>
  <tr>
    <td>John</td>
    <td>Doe</td>
  </tr>
  <tr>
    <td>Jane</td>
    <td>Doe</td>
  </tr>
</table>
John Doe
Jane Doe

Further simple examples

<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>
table
{
border-collapse: collapse;
border-spacing: 0px;
}
table, th, td
{
padding: 5px;
border: 1px solid black;
}
Simple table with header
First name Last name
John Doe
Jane Doe
Table with thead, tfoot, and tbody
Header content 1 Header content 2
Body content 1 Body content 2
Footer content 1 Footer content 2
Table with colgroup
Countries Capitals Population Language
USA Washington, D.C. 309 million English
Sweden Stockholm 9 million Swedish
Table with colgroup and col
Lime Lemon Orange
Green Yellow Orange
Simple table with caption
Awesome caption
Awesome data

Table sorting

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
<table>
  <tbody>
    <tr>
      <td>3</td>
    </tr>
    <tr>
      <td>2</td>
    </tr>
    <tr>
      <td>1</td>
    </tr>
  </tbody>
</table>
JavaScript
HTMLTableSectionElement.prototype.sort = function(cb){
  Array
    .prototype
    .slice
    .call(this.rows)
    .sort(cb)
    .forEach((e,i,a)=>{
      this.appendChild(this.removeChild(e));
    },this);
}

document.querySelector('table').tBodies[0].sort(function(a, b){
    return a.textContent.localeCompare(b.textContent);
});
Result
1
2
3

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.
Note: This solution assumes that the <td> elements are populated by raw text with no descendant elements.
HTML
<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
const allTables = document.querySelectorAll('table');

for (let table of allTables) {
  const tBody = table.tBodies[0];
  const rows = Array.from(tBody.rows);
  const headerCells = table.tHead.rows[0].cells;

  for (let 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
Numbers Letters
3 A
2 B
1 C

Displaying large tables in small spaces

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 CDN 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.
<table>
  <thead>
    <tr>
      <th>1<sup>3</sup> equals:
      <th>2<sup>3</sup> equals:
      <th>3<sup>3</sup> equals:
      <th>4<sup>3</sup> equals:
      <th>5<sup>3</sup> equals:
      <th>6<sup>3</sup> equals:
      <th>7<sup>3</sup> equals:
  <tbody>
    <tr>
      <td>row 1: 1
      <td>row 1: 8
      <td>row 1: 27
      <td>row 1: 64
      <td>row 1: 125
      <td>row 1: 216
      <td>row 1: 343
    <tr>
      <td>row 2: 1
      <td>row 2: 8
      <td>row 2: 27
      <td>row 2: 64
      <td>row 2: 125
      <td>row 2: 216
      <td>row 2: 343
    <tr>
      <td>row 3: 1
      <td>row 3: 8
      <td>row 3: 27
      <td>row 3: 64
      <td>row 3: 125
      <td>row 3: 216
      <td>row 3: 343
    <tr>
      <td>row 4: 1
      <td>row 4: 8
      <td>row 4: 27
      <td>row 4: 64
      <td>row 4: 125
      <td>row 4: 216
      <td>row 4: 343
    <tr>
      <td>row 5: 1
      <td>row 5: 8
      <td>row 5: 27
      <td>row 5: 64
      <td>row 5: 125
      <td>row 5: 216
      <td>row 5: 343
    <tr>
      <td>row 6: 1
      <td>row 6: 8
      <td>row 6: 27
      <td>row 6: 64
      <td>row 6: 125
      <td>row 6: 216
      <td>row 6: 343
    <tr>
      <td>row 7: 1
      <td>row 7: 8
      <td>row 7: 27
      <td>row 7: 64
      <td>row 7: 125
      <td>row 7: 216
      <td>row 7: 343
    <tr>
      <td>row 8: 1
      <td>row 8: 8
      <td>row 8: 27
      <td>row 8: 64
      <td>row 8: 125
      <td>row 8: 216
      <td>row 8: 343
    <tr>
      <td>row 9: 1
      <td>row 9: 8
      <td>row 9: 27
      <td>row 9: 64
      <td>row 9: 125
      <td>row 9: 216
      <td>row 9: 343
    <tr>
      <td>row 10: 1
      <td>row 10: 8
      <td>row 10: 27
      <td>row 10: 64
      <td>row 10: 125
      <td>row 10: 216
      <td>row 10: 343
    <tr>
      <td>row 11: 1
      <td>row 11: 8
      <td>row 11: 27
      <td>row 11: 64
      <td>row 11: 125
      <td>row 11: 216
      <td>row 11: 343
    <tr>
      <td>row 12: 1
      <td>row 12: 8
      <td>row 12: 27
      <td>row 12: 64
      <td>row 12: 125
      <td>row 12: 216
      <td>row 12: 343
    <tr>
      <td>row 13: 1
      <td>row 13: 8
      <td>row 13: 27
      <td>row 13: 64
      <td>row 13: 125
      <td>row 13: 216
      <td>row 13: 343
    <tr>
      <td>row 14: 1
      <td>row 14: 8
      <td>row 14: 27
      <td>row 14: 64
      <td>row 14: 125
      <td>row 14: 216
      <td>row 14: 343
    <tr>
      <td>row 15: 1
      <td>row 15: 8
      <td>row 15: 27
      <td>row 15: 64
      <td>row 15: 125
      <td>row 15: 216
      <td>row 15: 343
    <tr>
      <td>row 16: 1
      <td>row 16: 8
      <td>row 16: 27
      <td>row 16: 64
      <td>row 16: 125
      <td>row 16: 216
      <td>row 16: 343
    <tr>
      <td>row 17: 1
      <td>row 17: 8
      <td>row 17: 27
      <td>row 17: 64
      <td>row 17: 125
      <td>row 17: 216
      <td>row 17: 343
    <tr>
      <td>row 18: 1
      <td>row 18: 8
      <td>row 18: 27
      <td>row 18: 64
      <td>row 18: 125
      <td>row 18: 216
      <td>row 18: 343
    <tr>
      <td>row 19: 1
      <td>row 19: 8
      <td>row 19: 27
      <td>row 19: 64
      <td>row 19: 125
      <td>row 19: 216
      <td>row 19: 343
    <tr>
      <td>row 20: 1
      <td>row 20: 8
      <td>row 20: 27
      <td>row 20: 64
      <td>row 20: 125
      <td>row 20: 216
      <td>row 20: 343
</table>
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.
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

13 equals: 23 equals: 33 equals: 43 equals: 53 equals: 63 equals: 73 equals:
row 1: 1 row 1: 8 row 1: 27 row 1: 64 row 1: 125 row 1: 216 row 1: 343
row 2: 1 row 2: 8 row 2: 27 row 2: 64 row 2: 125 row 2: 216 row 2: 343
row 3: 1 row 3: 8 row 3: 27 row 3: 64 row 3: 125 row 3: 216 row 3: 343
row 4: 1 row 4: 8 row 4: 27 row 4: 64 row 4: 125 row 4: 216 row 4: 343
row 5: 1 row 5: 8 row 5: 27 row 5: 64 row 5: 125 row 5: 216 row 5: 343
row 6: 1 row 6: 8 row 6: 27 row 6: 64 row 6: 125 row 6: 216 row 6: 343
row 7: 1 row 7: 8 row 7: 27 row 7: 64 row 7: 125 row 7: 216 row 7: 343
row 8: 1 row 8: 8 row 8: 27 row 8: 64 row 8: 125 row 8: 216 row 8: 343
row 9: 1 row 9: 8 row 9: 27 row 9: 64 row 9: 125 row 9: 216 row 9: 343
row 10: 1 row 10: 8 row 10: 27 row 10: 64 row 10: 125 row 10: 216 row 10: 343
row 11: 1 row 11: 8 row 11: 27 row 11: 64 row 11: 125 row 11: 216 row 11: 343
row 12: 1 row 12: 8 row 12: 27 row 12: 64 row 12: 125 row 12: 216 row 12: 343
row 13: 1 row 13: 8 row 13: 27 row 13: 64 row 13: 125 row 13: 216 row 13: 343
row 14: 1 row 14: 8 row 14: 27 row 14: 64 row 14: 125 row 14: 216 row 14: 343
row 15: 1 row 15: 8 row 15: 27 row 15: 64 row 15: 125 row 15: 216 row 15: 343
row 16: 1 row 16: 8 row 16: 27 row 16: 64 row 16: 125 row 16: 216 row 16: 343
row 17: 1 row 17: 8 row 17: 27 row 17: 64 row 17: 125 row 17: 216 row 17: 343
row 18: 1 row 18: 8 row 18: 27 row 18: 64 row 18: 125 row 18: 216 row 18: 343
row 19: 1 row 19: 8 row 19: 27 row 19: 64 row 19: 125 row 19: 216 row 19: 343
row 20: 1 row 20: 8 row 20: 27 row 20: 64 row 20: 125 row 20: 216 row 20: 343

Accessibility concerns

Captions

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.

Scoping rows and columns

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 so as to provide necessary information about the cells related to a header.

Example

<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>hsla(180, 90%, 64%, 1)</code></td>
      <td><code>rgba(81, 246, 246, 1)</code></td>
    </tr>
    <tr>
      <th scope="row">Goldenrod</th>
      <td><code>#F6BC57</code></td>
      <td><code>hsla(38, 90%, 65%, 1)</code></td>
      <td><code>rgba(246, 188, 87, 1)</code></td>
    </tr>
  </tbody>
</table>
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.

Complicated tables

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.

Specifications

Specification
HTML Standard
# the-table-element

Browser compatibility

Report problems with this compatibility data on GitHub
desktopmobile
Chrome
Edge
Firefox
Internet Explorer
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
table
align
Deprecated
bgcolor
Deprecated
border
Deprecated
cellpadding
Deprecated
cellspacing
Deprecated
frame
Deprecated
rules
Deprecated
summary
Deprecated
width
Deprecated

Legend

Full supportFull support
Deprecated. Not for use in new websites.
The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.

See also