HTML Spanning Cells: colspan and rowspan

Published Updated

When one cell needs to cover more than a single grid slot, colspan stretches it across columns and rowspan stretches it down across rows.

This builds on HTML table basics. If tags and nesting are new to you, start with the HTML guide.

Syntax

Spans extend the normal table grid. A positive value counts the occupied columns or rows. The special value rowspan="0" spans the remaining rows in the current row group.

<td colspan="2">covers two columns</td>
<td rowspan="2">covers two rows</td>

Both attributes take a whole number, the count of slots the cell should cover. A value of 2 means the cell takes its own slot plus the next one, 3 means three slots, and the default of 1 is just a normal cell. They work on td and th alike.

How Does HTML colspan Work?

HTML colspan makes one table cell occupy several columns. A header with colspan="2" covers two column positions, so that row needs one fewer separate cell than an unspanned row of the same width.

<table>
  <tr>
    <th colspan="2">Morning menu</th>
  </tr>
  <tr>
    <td>Espresso</td>
    <td>3.00</td>
  </tr>
</table>

The heading row has a single th because that one cell covers both columns. The data row below it still has two cells, so the table stays two columns wide and the heading stretches the full width.

How Does HTML rowspan Work?

HTML rowspan makes one table cell occupy several rows. A cell with rowspan="2" fills its position in the current row and the next. Omit the corresponding cell from the lower row, because the spanning cell already occupies that position.

<table>
  <tr>
    <th rowspan="2">Coffee</th>
    <td>Espresso</td>
  </tr>
  <tr>
    <td>Cold brew</td>
  </tr>
</table>

The "Coffee" header spans both rows, so it appears once on the left and reaches down past both drinks. The second row writes only its drink cell, because the spanned header already occupies that row's first column.

How Do You Count Spanned Table Cells?

Count every grid position occupied by a cell, including positions covered by a span from an earlier row. A cell with colspan="2" fills two columns. A cell with rowspan="2" also occupies a position in the next row, so that row needs one fewer cell there.

<table>
  <tr>
    <th colspan="2">Drinks</th>
    <th>Price</th>
  </tr>
  <tr>
    <td>Espresso</td>
    <td>Hot</td>
    <td>3.00</td>
  </tr>
</table>

The header row has two cells but they account for three columns, because the first th spans two. The data row writes three plain cells to match, so the grid stays three columns wide and everything lines up.

When Should HTML Table Cells Span?

Reach for colspan or rowspan when one label describes a whole group of columns or rows, the way "Shift" labels both time columns in the schedule example below. That is different from using a span to patch over data that does not fit the grid cleanly, which is usually a sign that two separate tables, one for each shape, would serve the reader better than one table stretched to cover both.

How Do You Label Spanning Table Headers?

Label a spanning HTML table header with a scope value that matches its row, column, or group. Use explicit headers associations for more complex relationships, as explained in the table accessibility guide.

The scope="colgroup" value labels a column group defined with <colgroup>. The scope="rowgroup" value labels a row group such as <tbody>. A span alone does not require either group value; choose the scope that describes the actual header relationship.

Use the plain values for a header that labels one column or row, and reach for the group values when a header heads a group, which is often what a colspan or rowspan on a header means. A spanning header in a simple table can still carry a plain scope="col" or scope="row", so match the value to what the header labels rather than applying the group values to every span.

Example

<table>
  <caption>Weekly schedule</caption>
  <colgroup></colgroup>
  <colgroup span="2"></colgroup>
  <thead>
    <tr>
      <th scope="col">Day</th>
      <th colspan="2" scope="colgroup">Shift</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th rowspan="2" scope="rowgroup">Monday</th>
      <td>Open</td>
      <td>9 to 1</td>
    </tr>
    <tr>
      <td>Close</td>
      <td>1 to 5</td>
    </tr>
  </tbody>
</table>

This renders as a table that is three columns wide. The "Shift" header spans the two right columns, and the "Monday" header runs down both data rows on the left. Each data row carries the cells it still owns, so the columns stay aligned even though two cells cover extra ground.

The two <colgroup> elements are what make scope="colgroup" mean something. That value only anchors a header to a real column group, so without a <colgroup> defining the two-column "Shift" group, assistive technology has nothing to tie the header to. The scope="rowgroup" header needs no extra markup, because the <tbody> already forms its row group.

Frequently Asked Questions

Can an HTML table cell span both rows and columns?

An HTML table cell can use colspan and rowspan together to cover a rectangle. Count the positions it occupies in every affected row before adding other cells.

Do colspan and rowspan work on HTML th and td cells?

HTML th and td cells both support colspan and rowspan. For a spanning header, choose scope or explicit headers associations that match the data it labels.

What happens when HTML colspan exceeds the intended column count?

A large HTML colspan can expand the table grid beyond the columns you intended, leaving gaps in other rows. The browser does not simply clamp it to the number of cells in another row. Check the total occupied columns across the table.

Can CSS replace colspan and rowspan in an HTML table?

CSS Grid can span visual tracks, but it does not replace colspan and rowspan in an HTML table. Use the HTML attributes for cell spans in tabular data.

What happens to spanning HTML table cells on narrow screens?

Spanning HTML table cells keep their spans on narrow screens. A horizontal scrolling container can keep the data readable without squeezing every column. Simplify the table if its header relationships are difficult to follow.

Sources

  1. [1]
  2. [2]
    The Table Data Cell element
    (developer.mozilla.org)
  3. [3]
    The Table Header element
    (developer.mozilla.org)
  4. [4]
  5. [5]