Skip to content

Tables

HTML tables allow you to structure data into a grid of rows and columns, making complex information easier to read and compare. Use tables when you have data that logically belongs in this format, like spreadsheets, statistical data, or product comparison charts.

Important Note: In the past, tables were sometimes misused for creating page layouts. This is now considered bad practice. Use modern CSS techniques like Flexbox and Grid for page layout. Use HTML tables only for presenting tabular data.

Basic Table Structure: <table>, <tr>, <th>, <td>

The fundamental elements for creating a table are:

  • <table>: The main container element that wraps the entire table structure.
  • <tr> (Table Row): Defines a horizontal row within the table. Contains table header or data cells.
  • <th> (Table Header): Defines a header cell. Use this for column titles or row titles. Content inside <th> is semantically marked as a header, and browsers typically render it as bold and centered by default. Header cells help users understand the data's meaning.
  • <td> (Table Data): Defines a standard data cell containing the actual information.

These elements nest within each other: <table> contains <tr> elements, and each <tr> contains <th> or <td> elements.

Simple Example:

html
<table>
    <tr> 
        <th>Service</th>
        <th>Description</th>
        <th>Cost</th>
    </tr>
    <tr> 
        <td>Web Development</td>
        <td>Building responsive websites</td>
        <td>$1000</td>
    </tr>
    <tr> 
        <td>SEO Optimization</td>
        <td>Improving search engine ranking</td>
        <td>$500</td>
    </tr>
</table>

Structuring Tables Semantically: <thead>, <tbody>, <tfoot>, <caption>

For more complex tables, and to improve semantics and accessibility, you can use additional structural elements:

  • <caption>: Provides a title or description for the entire table. It should be the first child immediately inside the <table> tag. Crucial for accessibility, as it gives context to screen reader users about the table's content.
  • <thead> (Table Head): Groups the header row(s) (<tr> containing primarily <th> elements) of the table.
  • <tbody> (Table Body): Groups the main data rows (<tr> containing <td> elements, possibly <th> for row headers) of the table. A table can have multiple <tbody> elements to group related rows. This is the only required structural element besides <table> itself (browsers implicitly create a <tbody> if omitted, but explicit definition is better).
  • <tfoot> (Table Foot): Groups the footer row(s) of the table, often used for summaries or totals.

Benefits of using these elements:

  • Semantics: Clearly defines the different parts of the table.
  • Accessibility: Helps assistive technologies interpret the table structure.
  • Styling: Allows you to apply specific CSS styles to the header, body, or footer.
  • Functionality: Browsers may enable scrolling of the <tbody> independently while keeping the <thead> and <tfoot> visible (though this often requires CSS).

Structure Order: <caption> (first, optional), <thead> (optional), <tbody> (required, can be multiple), <tfoot> (optional, must appear after <thead> and <tbody> in the HTML source, but visually rendered at the bottom).

Example with Structure:

html
<table>
    <caption>Monthly Expenses Summary</caption>
    <thead>
        <tr>
            <th>Category</th>
            <th>Amount</th>
            <th>Notes</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Hosting</td>
            <td>$50</td>
            <td>Web server costs</td>
        </tr>
        <tr>
            <td>Software</td>
            <td>$120</td>
            <td>Subscriptions</td>
        </tr>
        <tr>
            <td>Utilities</td>
            <td>$80</td>
            <td>Office power & internet</td>
        </tr>
    </tbody>
    <tfoot>
        <tr>
            <th>Total</th>
            <td>$250</td>
            <td></td> 
        </tr>
    </tfoot>
</table>

Spanning Rows and Columns: rowspan and colspan

Sometimes, a single cell needs to extend across multiple rows or columns. This is achieved using the rowspan and colspan attributes on <th> or <td> elements.

  • colspan="number": Makes the cell span horizontally across the specified number of columns.
  • rowspan="number": Makes the cell span vertically down the specified number of rows.

When using these attributes, remember to adjust the number of cells in the subsequent affected rows/columns accordingly.

Example with colspan and rowspan:

html
<table>
    <caption>Developer Availability</caption>
    <thead>
        <tr>
            <th>Name</th>
            <th>Project</th>
            <th colspan="2">Availability (AM/PM)</th> 
        </tr>
    </thead>
    <tbody>
        <tr>
            <td rowspan="2">Alice</td> 
            <td>Project X</td>
            <td>Yes</td>
            <td>No</td>
        </tr>
        <tr>
            <td>Project Y</td>
            <td>Yes</td>
            <td>Yes</td>
        </tr>
        <tr>
            <td>Bob</td>
            <td>Project Z</td>
            <td>No</td>
            <td>Yes</td>
        </tr>
    </tbody>
</table>

Accessibility: The scope Attribute

To explicitly define the relationship between header cells (<th>) and the data cells (<td>) they relate to, use the scope attribute on <th> elements. This significantly improves table accessibility for screen reader users, especially in complex tables.

  • scope="col": Indicates the header applies to all cells in that column below it. Use for column headers (typically in <thead>).
  • scope="row": Indicates the header applies to all cells in that row to its right. Use for row headers (typically the first <th> in a <tbody> row).

Example with scope:

html
<table>
    <caption>Quarterly Sales Figures</caption>
    <thead>
        <tr>
            <th scope="col">Quarter</th>
            <th scope="col">Region North</th>
            <th scope="col">Region South</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th scope="row">Q1</th> 
            <td>$15,000</td>
            <td>$18,000</td>
        </tr>
        <tr>
            <th scope="row">Q2</th> 
            <td>$17,500</td>
            <td>$19,500</td>
        </tr>
    </tbody>
</table>

Styling Tables

While HTML structures the table, its visual appearance (borders, cell padding, background colors, text alignment, width, etc.) should be controlled using CSS.

Avoid using outdated presentational HTML attributes like border="1", cellpadding, cellspacing, width, bgcolor, or align. These attributes are deprecated in HTML5 and mix presentation with structure, making code harder to maintain and less flexible. Always use CSS for styling your tables.

css
/* Example CSS (place in a separate .css file or <style> tag) */
table {
    border-collapse: collapse; /* Merges cell borders */
    width: 100%;             /* Make table take full width */
    margin-bottom: 1em;       /* Space below table */
}

caption {
    font-weight: bold;
    font-size: 1.2em;
    padding-bottom: 0.5em;
    caption-side: top; /* Or bottom */
    text-align: left;
}

th, td {
    border: 1px solid #ccc;  /* Add borders */
    padding: 8px;             /* Add padding inside cells */
    text-align: left;         /* Align text left */
}

thead th {
    background-color: #f2f2f2; /* Light grey background for headers */
    text-align: center;
}

tbody th {
    background-color: #f9f9f9;
}

tfoot td {
    font-weight: bold;
}

/* Zebra striping for better readability */
tbody tr:nth-child(even) {
    background-color: #f9f9f9;
}