Spanning Cells with colspan and rowspan
One cell covering several columns or rows. Simple to write, easy to get wrong, and the arithmetic has to balance or the whole grid tears.
-
HTML Basics
- What is HTML: The Structure Layer of Every Web Page
- HTML Document Structure: DOCTYPE, html, head and body
- Elements, Tags and Attributes: The Vocabulary of HTML
- HTML Comments: Notes That Ship With Your Code
- Block Level and Inline Elements
- Writing and Running Your First HTML Page
- How a Browser Turns Markup Into a Page
- Text and Formatting
- Links and Navigation
- Images and Media
- Lists
- Tables
-
Forms
- Form Structure: form, action and method
- Input Types: Text, Email, Number, Date and the Rest
- Labels: The Most Important Element in a Form
- Checkboxes, Radio Buttons and Grouping
- select, option, optgroup and datalist
- textarea, File Uploads and Hidden Fields
- Buttons: submit, reset and button
- Built In Form Validation
- GET or POST: What Happens When a Form Is Submitted
- Semantic HTML
- HTML5 Features
- Head and Metadata
- HTML with CSS
- HTML with JavaScript
- Accessibility
-
HTML SEO
- How Google Works: Crawling, Indexing and Ranking
- SEO Friendly HTML Structure
- Titles and Descriptions That Earn Clicks
- Headings and Content Structure for Search
- Internal Linking and Anchor Text
- robots.txt and XML Sitemaps
- Canonical URLs and Duplicate Content
- Structured Data and JSON-LD
- Image SEO
- Core Web Vitals and Mobile Friendliness
- DevTools and Debugging
- Editor Productivity
- HTML Best Practices
- HTML Projects
- Advanced Projects
- Practice and Exams
Concept
colspan makes a cell stretch across several columns; rowspan makes it stretch down several rows. Both take a positive integer and both can be used on th or td.
<td colspan="3">This cell covers three columns</td>
<td rowspan="2">This cell covers two rows</td>
<td colspan="2" rowspan="2">A two by two block</td>The arithmetic
Every row must account for the same number of columns, and a spanned cell counts once for each column it covers. This is where most broken tables come from.
<!-- a four column table -->
<table>
<tr>
<td colspan="2">A</td> <!-- 2 -->
<td>B</td> <!-- 1 -->
<td>C</td> <!-- 1 --> total 4, correct
</tr>
<tr>
<td>D</td><td>E</td><td>F</td><td>G</td> <!-- 4, correct -->
</tr>
</table>A rowspan takes a slot in the rows below it. Those rows must therefore be written with fewer cells, because the spanning cell has already filled one of their positions.
<table>
<tr>
<td rowspan="2">Monday</td> <!-- occupies row 1 and row 2, column 1 -->
<td>09:00</td>
<td>Design studio</td>
</tr>
<tr>
<!-- no cell for column 1: Monday is still there -->
<td>11:00</td>
<td>Typography</td>
</tr>
</table>Add a cell to that second row and everything after it shifts right, leaving a table one column wider than the header. The browser will not warn you; it will simply draw the wrong grid.
Example: a timetable
<table>
<caption>Studio timetable, semester one</caption>
<thead>
<tr>
<th scope="col">Day</th>
<th scope="col">Time</th>
<th scope="col">Session</th>
<th scope="col">Room</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="rowgroup" rowspan="2">Monday</th>
<td>09:00</td><td>Design studio</td><td>B12</td>
</tr>
<tr>
<td>11:00</td><td>Typography</td><td>B14</td>
</tr>
<tr>
<th scope="row">Tuesday</th>
<td>10:00</td><td>Workshop</td><td>Ground floor</td>
</tr>
<tr>
<td colspan="4">Wednesday: no scheduled sessions</td>
</tr>
</tbody>
</table>Explanation
Monday spans two rows, so the second Monday row omits its first cell. Its scope is rowgroup rather than row, because it labels both rows rather than one. The Wednesday note spans all four columns, which is the standard way to write a full width message inside a table.
Grouped column headers
A two row header is the most common use of colspan:
<thead>
<tr>
<th rowspan="2" scope="col">Course</th>
<th colspan="2" scope="colgroup">Semester 1</th>
<th colspan="2" scope="colgroup">Semester 2</th>
</tr>
<tr>
<th scope="col">Theory</th>
<th scope="col">Practical</th>
<th scope="col">Theory</th>
<th scope="col">Practical</th>
</tr>
</thead>Read the arithmetic: row one is 1 + 2 + 2 = 5; row two is 4 cells plus the one still occupied by the rowspan above = 5. Balanced.
Accessibility warning
Spanned cells make a table harder for assistive technology to interpret, and the more complex the spanning, the less reliable the automatic header association becomes. Two consequences:
- Use
scope="colgroup"andscope="rowgroup"on spanning headers so their reach is explicit. - When the structure is genuinely complex, drop
scopeand use explicitidandheadersattributes instead. That is covered in the next note.
The better answer is usually to simplify. Two straightforward tables almost always beat one clever one.
Important rules
- Values must be positive integers.
colspan="0"is invalid androwspan="0"- meaning to the end of the row group - is unreliable. - Every row must total the same column count once spans are included.
- A
rowspanconsumes a position in each row it reaches into. - Spans must not overlap. Overlapping spans produce undefined layout.
colspanis capped at 1000 by the specification.
Common mistakes
- Writing a full set of cells in a row that a
rowspanalready reaches into. - Miscounting a
colspanand shifting everything after it. - Using spans to build a layout rather than to express real structure.
- Leaving
scope="col"on a header that spans several columns. - Nesting a table inside a spanned cell to avoid doing the arithmetic.
- Assuming the browser will flag the error. It will not.
Best practices
- Sketch the grid on paper before writing a spanned table.
- Comment the column count at the top of a complex table.
- Prefer two simple tables over one heavily spanned one.
- Use
colgroupandrowgroupscopes on spanning headers. - Validate. The validator catches mismatched column counts immediately.
- Test with a screen reader whenever a table has more than one header row.
Practice
- Build a five column table with a two row header where the first column spans both header rows. Check the arithmetic on both rows.
- Write a timetable where a day label spans three rows, then validate it.
- Deliberately add one extra cell to a row under a
rowspan. Describe what happens and how the validator reports it. - Take a complex spanned table and split it into two simple ones. Which is easier to read aloud?