HTML Guides for columns
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
In HTML, the structure of a <table> is implicitly defined by its rows and columns. The first <tr> in a table (or table section like <thead>, <tbody>, or <tfoot>) establishes the expected column count for the entire table. When a subsequent row contains more cells than the first row, the validator raises this error because the table’s column grid becomes inconsistent.
Browsers will still attempt to render mismatched tables, but the results can be unpredictable and problematic. Screen readers and other assistive technologies rely on a well-formed table grid to correctly associate data cells with their headers. An inconsistent column count can cause these tools to misread or skip content, making the table inaccessible to users who depend on them. Additionally, inconsistent tables are harder to style with CSS and can lead to unexpected layout shifts.
There are several common causes for this issue:
- Missing cells in the first row — The first row has fewer <td> or <th> elements than subsequent rows.
- Forgotten colspan — A cell in the first row should span multiple columns but is missing a colspan attribute.
- Extra cells in later rows — A row further down the table has more cells than intended.
- Mismatched colspan arithmetic — The sum of cells and their colspan values doesn’t add up consistently across rows.
To fix this, review every row in the table and ensure the total column count (accounting for colspan and rowspan attributes) is the same for each row.
Examples
Incorrect: second row has more columns than the first
The first row defines 1 column, but the second row has 2 columns.
<table>
<tr>
<td>Liza</td>
</tr>
<tr>
<td>Jimmy</td>
<td>14</td>
</tr>
</table>
Fixed: add missing cells to the first row
Make both rows have 2 columns by adding a header or data cell to the first row.
<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td>Jimmy</td>
<td>14</td>
</tr>
</table>
Fixed: use colspan if the first row intentionally spans the full width
If the first row is meant to be a single spanning header, use colspan to match the total column count.
<table>
<tr>
<th colspan="2">Student Info</th>
</tr>
<tr>
<td>Jimmy</td>
<td>14</td>
</tr>
</table>
Incorrect: later row exceeds column count with extra cells
<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td>Liza</td>
<td>12</td>
<td>Extra cell</td>
</tr>
</table>
Fixed: remove the extra cell or expand the header row
<table>
<tr>
<th>Name</th>
<th>Age</th>
<th>Notes</th>
</tr>
<tr>
<td>Liza</td>
<td>12</td>
<td>Extra cell</td>
</tr>
</table>
Incorrect: colspan mismatch causes inconsistent totals
The first row spans 3 columns total (1 + colspan="2"), but the second row has 4 cells.
<table>
<tr>
<th>Name</th>
<th colspan="2">Contact</th>
</tr>
<tr>
<td>Liza</td>
<td>liza@example.com</td>
<td>555-0100</td>
<td>Room 4</td>
</tr>
</table>
Fixed: adjust colspan or cell count so all rows match
<table>
<tr>
<th>Name</th>
<th colspan="3">Contact & Location</th>
</tr>
<tr>
<td>Liza</td>
<td>liza@example.com</td>
<td>555-0100</td>
<td>Room 4</td>
</tr>
</table>
When debugging this issue, count the effective columns for each row by adding up the number of cells plus any additional columns contributed by colspan values (a colspan="3" cell counts as 3 columns). Every row in the table must produce the same total.
HTML tables establish their column count based on the first row. When subsequent rows have fewer <td> or <th> cells than that initial row defines, the table structure becomes invalid. Browsers will typically render these tables by leaving blank space where the missing cells should be, but the underlying markup is malformed.
This matters for several important reasons. Screen readers and other assistive technologies rely on a consistent table structure to navigate cells and associate data with the correct headers. When cells are missing, users who depend on these tools may receive confusing or incorrect information. Additionally, inconsistent row widths can lead to unpredictable layout behavior across different browsers and make your table markup harder to maintain.
When counting columns, remember that the colspan attribute contributes to the total. A single <td colspan="3"> counts as three columns, not one. So if your first row has two <td> elements and one of them has colspan="2", the table is three columns wide, and every other row must also account for three columns.
How to Fix
There are several approaches depending on your intent:
- Add the missing cells — If data was accidentally omitted, add the appropriate <td> or <th> elements to complete the row.
- Use colspan — If a cell should intentionally span multiple columns, use the colspan attribute so the total column count matches.
- Add empty cells — If a cell simply has no content, include an empty <td></td> to maintain the structure.
Examples
❌ Row with fewer columns than the first row
The first row establishes a 3-column table, but the second row only has 2 cells:
<table>
<tr>
<td>Name</td>
<td>Role</td>
<td>Department</td>
</tr>
<tr>
<td>Alice</td>
<td>Engineer</td>
</tr>
</table>
✅ Fix by adding the missing cell
<table>
<tr>
<td>Name</td>
<td>Role</td>
<td>Department</td>
</tr>
<tr>
<td>Alice</td>
<td>Engineer</td>
<td>Product</td>
</tr>
</table>
✅ Fix by using colspan to span remaining columns
If the second row intentionally has fewer logical cells, use colspan so the total still matches:
<table>
<tr>
<td>Name</td>
<td>Role</td>
<td>Department</td>
</tr>
<tr>
<td>Alice</td>
<td colspan="2">Engineer — General</td>
</tr>
</table>
✅ Fix by adding an empty cell
If there’s simply no data for that column, include an empty cell:
<table>
<tr>
<td>Name</td>
<td>Role</td>
<td>Department</td>
</tr>
<tr>
<td>Alice</td>
<td>Engineer</td>
<td></td>
</tr>
</table>
❌ Mismatch caused by colspan in the first row
Be careful when the first row uses colspan, as it increases the effective column count:
<table>
<tr>
<td colspan="2">Full Name</td>
<td>Role</td>
</tr>
<tr>
<td>Alice</td>
<td>Engineer</td>
</tr>
</table>
Here the first row spans 3 columns (2 + 1), but the second row only has 2 cells.
✅ Fix by matching the full column count
<table>
<tr>
<td colspan="2">Full Name</td>
<td>Role</td>
</tr>
<tr>
<td>Alice</td>
<td>Smith</td>
<td>Engineer</td>
</tr>
</table>
When browsers build a table’s internal grid, each cell occupies one or more column slots. A cell with colspan="3" occupies three column slots, and columns are established based on the maximum number of slots any row uses. The validator checks that every column position in this grid has at least one cell whose starting position is in that column. If a column exists only because other cells span across it — but no cell ever begins there — the validator raises this warning.
This is a problem for several reasons:
- Accessibility: Screen readers use the table grid model to navigate cells and announce column headers. An empty or orphaned column confuses this navigation, making the table harder to understand for assistive technology users.
- Standards compliance: The HTML specification defines a precise table model. A column with no originating cell suggests a structural error in the table’s markup.
- Rendering inconsistencies: Different browsers may handle these orphaned columns differently, leading to unpredictable layouts.
The most common causes are:
- Excessive colspan values — a cell spans more columns than intended, creating extra columns that other rows don’t fill.
- Missing cells in a row — a row has fewer cells than the table’s column count, leaving trailing columns empty.
- Incorrect rowspan calculations — a cell spans rows, but subsequent rows still include cells for that column position, pushing other cells into non-existent columns or leaving gaps.
To fix the issue, count the total number of columns your table should have, then verify that every row’s cells (accounting for colspan and active rowspan from previous rows) add up to exactly that number. Ensure each column position has at least one cell starting in it across all rows.
Examples
Incorrect: colspan creates a column no cell begins in
In this example, the first row establishes 3 columns. The second row spans all 3 with colspan="3". The third row only has 2 cells, so column 3 has no cell beginning in it.
<table>
<tr>
<th>Name</th>
<th>Role</th>
<th>Status</th>
</tr>
<tr>
<td colspan="3">Team Alpha</td>
</tr>
<tr>
<td>Alice</td>
<td>Developer</td>
<!-- Column 3 has no cell beginning here -->
</tr>
</table>
Fixed: every row accounts for all columns
<table>
<tr>
<th>Name</th>
<th>Role</th>
<th>Status</th>
</tr>
<tr>
<td colspan="3">Team Alpha</td>
</tr>
<tr>
<td>Alice</td>
<td>Developer</td>
<td>Active</td>
</tr>
</table>
Incorrect: excessive colspan creates extra columns
Here, the second row’s colspan="4" establishes 4 columns, but no other row has a cell starting in column 4.
<table>
<tr>
<th>Q1</th>
<th>Q2</th>
<th>Q3</th>
</tr>
<tr>
<td colspan="4">Full year summary</td>
</tr>
<tr>
<td>100</td>
<td>200</td>
<td>300</td>
</tr>
</table>
Fixed: colspan matches the actual column count
<table>
<tr>
<th>Q1</th>
<th>Q2</th>
<th>Q3</th>
</tr>
<tr>
<td colspan="3">Full year summary</td>
</tr>
<tr>
<td>100</td>
<td>200</td>
<td>300</td>
</tr>
</table>
Incorrect: rowspan causes a missing cell origin
The rowspan="2" on “Alice” means the second row already has column 1 occupied. But the second row only provides one cell, leaving column 3 without a beginning cell in any row except the header.
<table>
<tr>
<th>Name</th>
<th>Task</th>
<th>Hours</th>
</tr>
<tr>
<td rowspan="2">Alice</td>
<td>Design</td>
<td>8</td>
</tr>
<tr>
<td>Code</td>
<!-- Column 1 is occupied by rowspan; column 3 has no cell -->
</tr>
</table>
Fixed: the spanned row includes the right number of cells
Since rowspan="2" on column 1 carries into the next row, that row only needs cells for columns 2 and 3.
<table>
<tr>
<th>Name</th>
<th>Task</th>
<th>Hours</th>
</tr>
<tr>
<td rowspan="2">Alice</td>
<td>Design</td>
<td>8</td>
</tr>
<tr>
<td>Code</td>
<td>6</td>
</tr>
</table>
A good practice is to sketch out your table grid on paper or in a spreadsheet before writing the HTML. Label each column slot and verify that every row fills all slots — either with a new cell or with a rowspan carry-over from a previous row. This makes it much easier to catch mismatched colspan and rowspan values before they cause validation errors.
The HTML specification requires that table structures be coherent — every column in a table must be “used” by at least one cell that starts in it. When you declare a <th> with colspan="2", you’re telling the browser that the table has (at least) two columns. If the body rows don’t provide cells to fill those columns, the table’s structure becomes inconsistent.
This matters for several reasons. Screen readers and other assistive technologies rely on a well-formed table grid to navigate and announce cell contents. An inconsistent column structure can confuse these tools, leading to a poor experience for users who depend on them. Browsers may also render such tables unpredictably, since they have to guess how to handle the mismatch.
Common causes of this error include:
- A colspan value on a header cell that exceeds the actual number of cells in body rows.
- Empty <tbody>, <thead>, or <tfoot> sections that leave declared columns without any cells.
- Rows with fewer cells than other rows define, leaving some columns unoccupied.
- Copy-paste errors or template issues where rows were deleted but headers were left unchanged.
To fix this, examine your table’s column structure. Count the total number of columns implied by each row (accounting for colspan and rowspan attributes) and make sure every row agrees on the total column count. Every column should have at least one cell beginning in it somewhere in the table.
Examples
Incorrect: colspan creates columns with no matching body cells
Here, the header declares two columns, but the body is empty, so column 2 has no cells beginning in it:
<table>
<thead>
<tr>
<th colspan="2">The table header</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Incorrect: Body rows have fewer cells than the header defines
The header spans three columns, but the body rows only have two cells each. Column 3 has no cells beginning in it:
<table>
<thead>
<tr>
<th colspan="3">Wide header</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
</tbody>
</table>
Correct: Body cells match the columns defined by the header
The header spans two columns, and the body row provides exactly two cells:
<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>
Correct: Three-column header with matching body cells
<table>
<thead>
<tr>
<th>Name</th>
<th>Role</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>Developer</td>
<td>Active</td>
</tr>
</tbody>
</table>
Correct: Using colspan in body rows to fill all columns
If you need fewer visible cells in a body row, use colspan to span the remaining columns rather than leaving them empty:
<table>
<thead>
<tr>
<th>Name</th>
<th>Role</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td colspan="2">Info unavailable</td>
</tr>
</tbody>
</table>
Correct: Reducing colspan to match actual content
If the header doesn’t truly need to span multiple columns, simply remove the colspan:
<table>
<thead>
<tr>
<th>The table header</th>
</tr>
</thead>
<tbody>
<tr>
<td>The table body</td>
</tr>
</tbody>
</table>
When a table cell uses colspan to span multiple columns, the HTML specification requires that the columns being spanned actually exist and are accounted for in the table’s column structure. If a cell’s colspan creates columns that no other row has cells beginning in, the validator flags those empty columns. For example, if your widest row has 3 columns but another row contains a cell with colspan="6", columns 4 through 6 are established by that cell but are essentially phantom columns — no cell in any other row starts in them.
This matters for several reasons. Screen readers and assistive technologies rely on a coherent table structure to navigate cells and announce column/row relationships. An inconsistent column count can confuse these tools, leading to a poor experience for users who depend on them. Browsers may render the table without visible errors, but the underlying structure is invalid, which can cause unpredictable layout behavior across different rendering engines.
How to Fix
- Identify the offending row. Look for <td> or <th> elements whose colspan value creates more columns than the rest of the table defines.
- Reduce the colspan value so it matches the actual number of columns in the table.
- Alternatively, add cells to other rows if you genuinely need more columns — make sure every column has at least one cell that begins in it.
A good rule of thumb: the colspan of any cell, combined with its starting column position, should never exceed the total column count of the table.
Examples
Incorrect: colspan exceeds the table’s column count
This table has 2 columns (established by the first row), but the second row’s colspan="5" tries to span 5 columns. Columns 3 through 5 have no cells beginning in them in any row.
<table>
<tr>
<td>First</td>
<td>Second</td>
</tr>
<tr>
<td colspan="5">Spans too many columns</td>
</tr>
</table>
Correct: colspan matches the table’s column count
Set the colspan to 2 so the cell spans exactly the columns that exist.
<table>
<tr>
<td>First</td>
<td>Second</td>
</tr>
<tr>
<td colspan="2">Spans both columns</td>
</tr>
</table>
Incorrect: mixed rows with mismatched column counts
Here the first row establishes 3 columns, but the second row creates a cell starting at column 1 that spans 5 columns, leaving columns 4 and 5 with no cells beginning in them.
<table>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
<tr>
<td colspan="5">Too wide</td>
</tr>
</table>
Correct: expand the table or reduce the span
Option A: Reduce the colspan to match the existing 3 columns.
<table>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
</tr>
<tr>
<td colspan="3">Spans all three columns</td>
</tr>
</table>
Option B: If you truly need 5 columns, add cells to the other rows so every column has a cell beginning in it.
<table>
<tr>
<td>A</td>
<td>B</td>
<td>C</td>
<td>D</td>
<td>E</td>
</tr>
<tr>
<td colspan="5">Spans all five columns</td>
</tr>
</table>
Ready to validate your sites?
Start your free trial today.