HTML5 - Key Insights into Tables
Tags: webdev, beginners, html
Published: 2023-09-25 19:11:13

In this article, we will learn about **tables** in HTML.

Tables serve a crucial role in effectively presenting structured **tabular data**, where information is logically organized into rows and columns. However, it's imperative to emphasize that tables should never be employed to dictate the layout or structure of a webpage. Modern web design relies on more versatile and responsive techniques, such as **CSS grid**, **flexbox**, and semantic HTML elements. These methods enable the creation of visually appealing and adaptable page layouts, ensuring a seamless user experience. Utilizing tables for layout purposes can introduce issues related to accessibility, responsiveness, and the maintainability of web designs. Therefore, while tables excel at organizing data, they are not suited for defining the broader structure of a web page.

Remember that a table is like this one:

| Movie              | IMDB Rating |
| ------------------- | ----------- |
| Interstellar       | 8.4         |
| The Prestige        | 8.5         |
| The Butterfly Effect | 7.6         |

Notice that we have a **table header** and three lines (rows), each row has two cells.

In HTML we have:
- an element to table, called `table`;
- an element to table header, the group of cells that form the head, called `thead`;
- an element to table header cell, called `th`;
- an element to table body, the group of rows and cells that form the body of the table, called `tbody`;
- an element to table footer, the group of cells that form the footer, called `tfoot`. This element is absolutely optional.
- an element to each row, called `tr`;
- an element to cell (table data), called `td`;

See the below code:

```html
<table>
    <tr>
        <td>Movie</td>
        <td>IMDB Rating</td>
    </tr>
    <tr>
        <td>Interstellar</td>
        <td>8.4</td>
    </tr>
    <tr>
        <td>The Prestige</td>
        <td>8.5</td>
    </tr>
    <tr>
        <td>The Butterfly Effect</td>
        <td>7.6</td>
    </tr>
</table>
```

This code looks like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cpen9vpmesnohqcrkkwb.png)

## Table Header

The first line doesn't appear like a table head, do you agree?

To fix this, we need to use `thead` and `th` elements, like this new example:

```html
<table>
    <thead>
        <th>Movie</th>
        <th>IMDB Rating</th>
    </thead>
    <tbody>
        <tr>
            <td>Interstellar</td>
            <td>8.4</td>
        </tr>
        <tr>
            <td>The Prestige</td>
            <td>8.5</td>
        </tr>
        <tr>
            <td>The Butterfly Effect</td>
            <td>7.6</td>
        </tr>
    </tbody>
</table>
```

Notice that we also add the `tbody` element. This code looks like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ma9h7z85gg5eenxmguz.png)

## Table Border

Notice that there isn't a border; to add a border, we use an attribute called `border` or, if you desire to do the right thing, use **CSS**.

```html
<table border="1">
    <thead>
        <th>Movie</th>
        <th>IMDB Rating</th>
    </thead>
    <tbody>
        <tr>
            <td>Interstellar</td>
            <td>8.4</td>
        </tr>
        <tr>
            <td>The Prestige</td>
            <td>8.5</td>
        </tr>
        <tr>
            <td>The Butterfly Effect</td>
            <td>7.6</td>
        </tr>
    </tbody>
</table>
```

This code looks like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gckr7xj61h0k78osiejm.png)

## Styling Tables

Now we have borders, but the border looks bad. For a good look, we can use `cellspacing` and `cellpadding` attributes. `Cellspacing` controls the space between the cell and the rest of the table, and `cellpadding` controls the space between the cell data and cell border.

```html
<table border="1" cellspacing="0" cellpadding="8">
    <thead>
        <th>Movie</th>
        <th>IMDB Rating</th>
    </thead>
    <tbody>
        <tr>
            <td>Interstellar</td>
            <td>8.4</td>
        </tr>
        <tr>
            <td>The Prestige</td>
            <td>8.5</td>
        </tr>
        <tr>
            <td>The Butterfly Effect</td>
            <td>7.6</td>
        </tr>
    </tbody>
</table>
```

Now, the table looks like this, much better, do you know?:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v6f0fbsmd1k0rr15dw1c.png)

> Remember: styling is made with CSS.

## Table Cell Merging

Sometimes, we need to merge cells in a table, like we do in Excel (or another Spreadsheet editor). So, if you need to merge cells, you can use `colspan` or `rowspan` for this. See the below example. Notice that I add `colspan` attribute in `th` element, but it's possible to add `colspan` in `td` element, because `colspan` is added in cell element and merges cells horizontally, cell next to each other. So, the first and second header cell are combined as one unique cell.

```html
<table border="1" cellspacing="0" cellpadding="8">
    <thead>
        <th colspan="2">Movie Info</th>
        <th>IMDB Rating</th>
    </thead>
    <tbody>
        <tr>
            <td>Interstellar</td>
            <td>Sci-fi</td>
            <td>8.4</td>
        </tr>
        <tr>
            <td>The Prestige</td>
            <td>Drama</td>
            <td>8.5</td>
        </tr>
        <tr>
            <td>The Butterfly Effect</td>
            <td>Sci-fi</td>
            <td>7.6</td>
        </tr>
    </tbody>
</table>
```

This code looks like the below image.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g4i89q6movl68uy6kn9b.png)

As I mentioned, it's possible to merge cells one on top of the other with `rowspan` attribute.

## Table Column and Row Head

Until here, we had only a header in the first row, but it's possible there is a header in the first column using `th` cell. See the below example:

```html
<table border="1" cellspacing="0" cellpadding="8">
    <thead>
        <th>Movie</th>
        <th>Genre</th>
        <th>IMDB Rating</th>
    </thead>
    <tbody>
        <tr>
            <td>Interstellar</td>
            <td>Sci-fi</td>
            <td>8.4</td>
        </tr>
        <tr>
            <td>The Prestige</td>
            <td>Drama</td>
            <td>8.5</td>
        </tr>
        <tr>
            <td>The Butterfly Effect</td>
            <td>Sci-fi</td>
            <td>7.6</td>
        </tr>
    </tbody>
</table>
```

This example looks like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lgw9yzdz1ueqcvp1mlrf.png)

## Other Table Considerations

There are `colgroup` and `col` elements, but I don't recommend using them because they are for styling, and as we know, styling is done with **CSS**. It's more common to style tables with CSS rather than using `colgroup`.

## Tables with div and span

Yes, you read correct. It's possible create tables using divs or other block element, but the div will behave as a table for accessibility, but with less semantic. In this case, it's essential to organize the table layout with CSS. 

For this, you should use `role` attribute and [Aria Role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/table_role)

See the below example:
```html
<div role="table" aria-label="Movie Information">
    <div role="rowgroup">
        <div role="row">
            <span role="columnheader" aria-colspan="2">Movie Info</div>
            <span role="columnheader">IMDB Rating</div>
        </div>
    </div>
    <div role="rowgroup">
        <div role="row">
            <span role="cell">Interstellar</span>
            <span role="cell">Sci-fi</span>
            <span role="cell">8.4</span>
        </div>
        <div role="row">
            <span role="cell">The Prestige</span>
            <span role="cell">Drama</span>
            <span role="cell">8.5</span>
        </div>
        <div role="row">
            <span role="cell">The Butterfly Effect</span>
            <span role="cell">Sci-fi</span>
            <span role="cell">7.6</span>
        </div>
    </div>
</div>
```

This code will be rendered like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vsdhopklzz5uq5yct0xm.png)

Notice, that we use `div` and `span` with `role` attribute and its values:
- `table`: for the whole table;
- `rowgroup`: for row group, header row group or data row group;
- `columnheader`: for column header;
- `row`: for rows;
- `cell`: for cells;

In detail:
- `<div role="table" aria-label="Movie Information">` represents the entire table with an aria-label attribute for accessibility.
- `<div role="rowgroup">` groups the rows, similar to the thead and tbody elements.
- `<div role="row">` represents each row.
- `<div role="columnheader" aria-colspan="2">` represents the table header with aria-colspan indicating the colspan of 2.
- `<div role="cell">` represents the table data.

### When use this form?

Both forms, `table` element or `role` attribute, work almost equally, mainly we need to use CSS to improve layout and appearance of the table. But `table` element is more semantic, then you should prefer table. And, the better is creating a table with role attribute for more accessibility.

> Remember, the role attribute is essential for accessibility.

## What Lies Ahead

In upcoming articles, you will delve into forms in HTML. Stay tuned!

## References

- [Mozilla Developer Network. HTML tables - Learn web development | MDN](https://developer.mozilla.org/en-US/docs/Learn/HTML/Tables/Basics) (Accessed on 25/09/2023)
- [Stack Overflow. HTML tables <thead> vs. <th> - Stack Overflow](https://stackoverflow.com/questions/5395228/html-tables-thead-vs-th) (Accessed on 25/09/2023)