HTML Guides for th
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.
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 you write a <table> without explicitly using <thead> and <tbody>, the HTML parser automatically wraps your <tr> elements in an implicit <tbody>. If any of those rows contain <th> elements intended as column headers, the validator flags them because <th> cells in <tbody> are unexpected — the parser sees header cells appearing in what should be the data body of the table.
While <th> elements are technically valid inside <tbody> (for example, as row headers), this warning usually indicates a structural problem: your column headers aren’t properly separated from your data rows. Properly structuring your table with <thead> and <tbody> matters for several reasons:
- Accessibility: Screen readers use table structure to help users navigate. A <thead> section clearly identifies column headers, making it easier for assistive technology to announce what each data cell represents.
- Styling and behavior: CSS selectors like thead th and tbody td let you target headers and data cells independently. Browsers can also use <thead> and <tbody> to enable scrollable table bodies while keeping headers fixed.
- Standards compliance: Explicitly defining table sections removes ambiguity and ensures consistent parsing across all browsers.
To fix this issue, wrap the row containing your <th> column headers in a <thead> element, and wrap your data rows in a <tbody> element.
Examples
❌ Incorrect: <th> in implicit table body
Here, the parser wraps all rows in an implicit <tbody>, so the <th> elements end up inside the table body:
<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td>Liza</td>
<td>49</td>
</tr>
<tr>
<td>Joe</td>
<td>47</td>
</tr>
</table>
✅ Correct: <th> in explicit <thead>
Wrapping the header row in <thead> and data rows in <tbody> resolves the issue:
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr>
<td>Liza</td>
<td>49</td>
</tr>
<tr>
<td>Joe</td>
<td>47</td>
</tr>
</tbody>
</table>
✅ Correct: <th> as row headers inside <tbody>
If you intentionally use <th> elements inside <tbody> as row headers, add the scope attribute to clarify their purpose. This is valid and won’t trigger the warning when the table also has a proper <thead>:
<table>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Age</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Liza</th>
<td>49</td>
</tr>
<tr>
<th scope="row">Joe</th>
<td>47</td>
</tr>
</tbody>
</table>
The scope="row" attribute tells assistive technology that these <th> cells are headers for their respective rows, while scope="col" identifies column headers. This combination provides the best accessibility for table data.
The th element has a specific role in HTML: it defines a header cell within a table. It already carries implicit heading semantics through its association with the rows or columns it describes. When you place an h1–h6 element inside a th, you’re nesting one type of heading structure inside another, which violates the HTML content model. The HTML specification explicitly excludes heading elements from the allowed content of th.
This causes several problems:
- Document outline confusion: Heading elements contribute to the document’s outline and sectioning structure. Placing them inside table headers injects unexpected entries into the outline that don’t represent actual document sections, making navigation unpredictable.
- Accessibility issues: Screen readers treat headings and table headers differently. A heading inside a th creates conflicting signals—assistive technology may announce the content as both a table header and a document heading, confusing users who rely on either navigation method.
- Standards compliance: Browsers may handle this invalid nesting inconsistently, leading to unpredictable rendering or behavior across different environments.
If your goal is to make the text inside a th visually larger or bolder, use CSS instead. The th element is already rendered bold by default in most browsers, and you can further style it with font-size, font-weight, or any other CSS property.
Examples
Incorrect: heading inside a th element
<table>
<tr>
<th><h1>Product</h1></th>
<th><h1>Price</h1></th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
This triggers the validation error because h1 elements are nested inside th elements.
Fixed: plain text in th, heading moved outside the table
<h1>Product Pricing</h1>
<table>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
The heading now introduces the table as a whole, and the th elements contain plain text.
Fixed: styling th with CSS instead of using headings
If you want the table headers to have a specific visual appearance, apply CSS directly to the th elements:
<style>
.styled-table th {
font-size: 1.5rem;
font-weight: bold;
text-transform: uppercase;
}
</style>
<table class="styled-table">
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
Fixed: using caption for a table title
If the heading was meant to serve as a title for the table, the caption element is the semantically correct choice:
<table>
<caption>Product Pricing</caption>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
The caption element is specifically designed to label a table and is properly associated with it for assistive technology. You can style it with CSS to achieve any visual appearance you need.
The HTML specification defines a strict content model for the th element: it accepts flow content, but specifically excludes header, footer, sectioning content, and heading content (h1–h6). This restriction exists because th elements are themselves headers — they describe the data in their corresponding row or column. Placing a heading element inside a th creates a conflict in the document outline and semantic structure.
This matters for several reasons:
- Accessibility: Screen readers use headings to build a navigable document outline. Headings buried inside table header cells can confuse assistive technology, making it harder for users to understand the page structure and navigate between sections.
- Document outline: Heading elements define the hierarchical structure of a document’s content. When headings appear inside table cells, they disrupt this hierarchy and create unexpected, often meaningless, sections in the outline.
- Standards compliance: Browsers may handle this invalid nesting inconsistently, and the W3C validator will flag it as an error.
A common reason developers place headings in th cells is to achieve a specific visual style — larger or bolder text. The correct approach is to use CSS to style the th content directly, keeping the markup clean and valid.
How to Fix It
- Remove the heading element from inside the th.
- Move the heading above the table if you need a title or section heading for the table.
- Use CSS to style the th text if you need a particular visual appearance.
- Use the caption element if you want to provide a visible title that is semantically associated with the table.
Examples
❌ Incorrect: Heading inside a th element
<table>
<tr>
<th><h2>Product</h2></th>
<th><h2>Price</h2></th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
This triggers the validation error because h2 elements are not permitted as descendants of th.
✅ Correct: Plain text inside th, heading moved outside
<h2>Product Pricing</h2>
<table>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
✅ Correct: Using caption for the table title
<table>
<caption>Product Pricing</caption>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
The caption element is the semantically appropriate way to give a table a title. It is announced by screen readers in context with the table, providing a better experience than a heading placed before the table.
✅ Correct: Styling th with CSS for visual emphasis
If the heading was added purely for visual effect, use CSS instead:
<style>
.prominent-header th {
font-size: 1.5em;
font-weight: bold;
color: #333;
}
</style>
<table class="prominent-header">
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
This gives you full control over the appearance of header cells without breaking the document structure or introducing validation errors. Remember: th elements are already semantically headers, so there’s no need to wrap their content in heading elements.
The th element is specifically designed to represent a header cell in a table. It inherently conveys header semantics to browsers, screen readers, and other assistive technologies. When you place a heading element like h3 inside a th, you’re creating a structural conflict — the content is simultaneously acting as a table header and a document section heading. The HTML specification restricts the content model of th to “flow content, but with no header, footer, sectioning content, or heading content descendants.”
This matters for several reasons:
- Accessibility: Screen readers use heading elements to build a document outline and allow users to navigate between sections. A heading buried inside a table header cell disrupts this navigation, creating confusion about the page structure. The th element already communicates its role as a header through the table’s own semantics.
- Document structure: Headings define the hierarchical structure of a document. Placing them inside table cells implies that a new document section begins within the table, which is almost never the intended meaning.
- Standards compliance: Browsers may handle this invalid nesting inconsistently, leading to unpredictable rendering or accessibility tree representations.
The fix is straightforward: remove the heading element from inside the th. If the text inside the th needs to be visually larger or bolder, apply CSS styles directly to the th element or use a span with a class. If the heading was meant to title the entire table, move it outside the table or use the caption element.
Examples
❌ Incorrect: heading inside th
<table>
<tr>
<th>Month</th>
<th><h3>Revenue</h3></th>
</tr>
<tr>
<td>January</td>
<td>$500</td>
</tr>
</table>
The h3 inside the second th triggers the validation error.
✅ Fixed: remove the heading, use plain text
<table>
<tr>
<th>Month</th>
<th>Revenue</th>
</tr>
<tr>
<td>January</td>
<td>$500</td>
</tr>
</table>
The th element already communicates that “Revenue” is a header. No heading element is needed.
✅ Fixed: use CSS for visual styling
If the heading was used to make the text look bigger or styled differently, apply CSS to the th instead:
<table>
<tr>
<th>Month</th>
<th class="prominent">Revenue</th>
</tr>
<tr>
<td>January</td>
<td>$500</td>
</tr>
</table>
<style>
.prominent {
font-size: 1.2em;
font-weight: bold;
}
</style>
✅ Fixed: use caption for a table title
If the heading was meant to describe the entire table, use the caption element:
<table>
<caption>Monthly Revenue</caption>
<tr>
<th>Month</th>
<th>Revenue</th>
</tr>
<tr>
<td>January</td>
<td>$500</td>
</tr>
</table>
The caption element is the semantically correct way to provide a title or description for a table. You can style it with CSS to match the appearance of a heading. If you still need a heading in the document outline to precede the table, place it before the table element:
<h3>Revenue Report</h3>
<table>
<tr>
<th>Month</th>
<th>Revenue</th>
</tr>
<tr>
<td>January</td>
<td>$500</td>
</tr>
</table>
This approach keeps the document structure clean while maintaining proper table semantics. The same rule applies to all heading levels — h1, h2, h3, h4, h5, and h6 are all equally invalid inside th (and td) elements.
The th element already carries semantic meaning as a table header cell. Nesting a heading element like h4 inside it creates a conflict in the document’s outline and semantic structure. Screen readers and other assistive technologies treat headings and table headers as distinct navigational landmarks, so combining them can confuse users who rely on these tools to understand page structure. A heading buried inside a table cell may break the expected heading hierarchy, making it harder for users to navigate by headings.
According to the HTML specification, the content model of th is “flow content, but with no header, footer, sectioning content, or heading content descendants.” This means h1, h2, h3, h4, h5, and h6 are all explicitly disallowed inside th.
The reason developers often place headings inside th is to achieve a specific visual style — larger, bolder text. But th elements are already rendered bold by default in most browsers, and any additional styling should be handled with CSS rather than repurposing heading elements.
How to Fix It
- Remove the heading element from inside the th and use the text directly.
- Style with CSS if you need the th content to look different from default styling.
- Move the heading outside the table if it serves as a title or caption for the table. Consider using the <caption> element for table titles.
Examples
❌ Incorrect: Heading inside th
<table>
<tr>
<th><h4>Product</h4></th>
<th><h4>Price</h4></th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
This triggers the validation error because h4 elements are not allowed as descendants of th.
✅ Fixed: Plain text in th
<table>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
The simplest fix — just remove the heading tags. The th element already conveys that these cells are headers.
✅ Fixed: Using CSS for custom styling
If you need the header cells to have a specific visual appearance, use CSS:
<table>
<tr>
<th class="styled-header">Product</th>
<th class="styled-header">Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
<style>
.styled-header {
font-size: 1.2em;
text-transform: uppercase;
}
</style>
✅ Fixed: Moving the heading outside and using caption
If the heading was meant to serve as a title for the table, use the <caption> element instead:
<table>
<caption>Product Pricing</caption>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
The <caption> element is purpose-built for labeling tables and is well-supported by assistive technologies. You can also place a heading before the table if it fits your document’s heading hierarchy:
<h4>Product Pricing</h4>
<table>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$25</td>
</tr>
</table>
Both approaches keep your HTML valid while preserving clear semantics for both visual users and assistive technology.
The th element is specifically designed to act as a header cell within a table. It already carries implicit heading semantics — screen readers announce th content as a header when navigating table cells. When you place an h5 (or any h1–h6) inside a th, you’re creating a conflict: the content is simultaneously a table header and a document section heading. This breaks the document’s outline structure and creates confusing behavior for assistive technologies, which may announce the content as both a table header and a section heading.
The HTML specification restricts the content model of th to “flow content, but with no header, footer, sectioning content, or heading content descendants.” Heading elements (h1 through h6) fall under heading content, so placing any of them inside a th is invalid.
This issue typically arises when developers want the text inside a th to look like a heading — larger, bolder, or styled differently. The correct approach is to use CSS to style the th content directly, rather than wrapping it in a heading element.
How to Fix It
- Remove the heading element from inside the th.
- Keep the text content directly inside the th.
- Use CSS to apply any desired visual styling to the th element.
- If the heading is meant to describe the entire table (not just a column), move it outside the table or use the <caption> element.
Examples
❌ Incorrect: Heading inside a th
<table>
<tr>
<th><h5>Product</h5></th>
<th><h5>Price</h5></th>
</tr>
<tr>
<td>Widget</td>
<td>$9.99</td>
</tr>
</table>
This triggers the validation error because h5 elements are nested inside th elements.
✅ Correct: Plain text inside th, styled with CSS
<table>
<tr>
<th class="table-heading">Product</th>
<th class="table-heading">Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$9.99</td>
</tr>
</table>
<style>
.table-heading {
font-size: 1.1em;
font-weight: bold;
text-transform: uppercase;
}
</style>
The th elements already convey header semantics. CSS handles the visual presentation without introducing invalid markup.
✅ Correct: Using <caption> for a table title
If the heading was meant to describe the table as a whole, use <caption> instead:
<table>
<caption>Monthly Revenue</caption>
<tr>
<th>Month</th>
<th>Revenue</th>
</tr>
<tr>
<td>January</td>
<td>$500</td>
</tr>
</table>
✅ Correct: Heading placed before the table
If you need a document-level heading that introduces the table, place it outside:
<h5>Revenue per Month</h5>
<table>
<tr>
<th>Month</th>
<th>Revenue</th>
</tr>
<tr>
<td>January</td>
<td>$500</td>
</tr>
</table>
This keeps the document outline clean and avoids nesting headings inside table cells. The same rule applies to all heading levels — h1, h2, h3, h4, h5, and h6 are all equally invalid inside th (and td) elements.
The <th> element already carries semantic meaning as a table header cell. Placing a heading element like <h6> inside it creates a conflict in the document’s semantic structure. Screen readers and other assistive technologies use headings to build a navigable outline of the page, and they also interpret <th> elements as table headers. Nesting one inside the other produces a confusing, redundant structure that can mislead assistive technologies about the page’s organization and the table’s meaning.
According to the WHATWG HTML living standard, the content model for <th> is “flow content, but with no header, footer, sectioning content, or heading content descendants.” This means <h1>, <h2>, <h3>, <h4>, <h5>, and <h6> are all explicitly disallowed inside <th>.
People commonly make this mistake when trying to visually style table header text to look bolder or larger. Since <th> cells are already rendered bold by default in most browsers, and CSS gives you full control over font size, weight, and appearance, there’s no need to use heading elements for visual styling inside table headers.
How to Fix It
- Remove the heading element from inside the <th> and place the text directly inside the <th>.
- Use CSS if you need the table header text to appear larger or styled differently.
- Use a <caption> element if the heading was meant to serve as a title for the table, or place a heading element before the <table>.
Examples
❌ Incorrect: Heading inside <th>
<table>
<tr>
<th><h6>Product</h6></th>
<th><h6>Price</h6></th>
</tr>
<tr>
<td>Widget</td>
<td>$19.99</td>
</tr>
</table>
This triggers the validation error because <h6> elements are descendants of <th> elements.
✅ Correct: Plain text inside <th>
<table>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$19.99</td>
</tr>
</table>
The <th> element is already semantically a header, so no additional heading tag is needed.
✅ Correct: Styled <th> with CSS
If you need the header cells to have a specific visual appearance, use CSS:
<style>
.table-header {
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
</style>
<table>
<tr>
<th class="table-header">Product</th>
<th class="table-header">Price</th>
</tr>
<tr>
<td>Widget</td>
<td>$19.99</td>
</tr>
</table>
✅ Correct: Using <caption> for a table title
If the heading was intended as a title for the entire table, use the <caption> element instead:
<table>
<caption>Monthly Revenue</caption>
<tr>
<th>Month</th>
<th>Revenue</th>
</tr>
<tr>
<td>January</td>
<td>$500</td>
</tr>
</table>
The <caption> element is the semantically correct way to provide a title for a table. It is announced by screen readers and associated directly with the table, giving users proper context. You can also place a heading before the <table> element if a <caption> doesn’t suit your layout needs.
A td element’s headers attribute must reference the ID of a th element within the same table.
The headers attribute is used to define explicit associations between data cells (td) and header cells (th) by referencing header cell IDs. For valid markup, every ID referenced in the headers attribute must exist as a th element’s id within the same table. This helps users—especially those using assistive technology—understand which header(s) apply to each data cell.
For example, if a td references headers="table_header_1", there must be a th id="table_header_1" present. If it’s missing or mistyped, you’ll get the validator error you described.
Correct pattern:
<table>
<tr>
<th id="table_header_1">Header 1</th>
<th id="table_header_2">Header 2</th>
</tr>
<tr>
<td headers="table_header_1">Row 2, Column 1</td>
<td headers="table_header_2">Row 2, Column 2</td>
</tr>
</table>
Incorrect pattern (missing th ID):
<table>
<tr>
<th>Header 1</th>
<th id="table_header_2">Header 2</th>
</tr>
<tr>
<td headers="table_header_1">Row 2, Column 1</td>
<td headers="table_header_2">Row 2, Column 2</td>
</tr>
</table>
To resolve the error, ensure every value in a td‘s headers attribute matches the id of a th element in the same table.
The scope attribute tells browsers and assistive technologies how a header cell relates to the data cells around it. Its valid values are col, row, colgroup, and rowgroup. In older versions of HTML, scope was permitted on <td> elements, but the current HTML Living Standard restricts it to <th> elements only. When the W3C validator encounters scope on a <td>, it flags it as obsolete.
This matters for several reasons. First, if a cell acts as a header for other cells, it should be marked up as a <th>, not a <td>. Using <td scope="row"> sends conflicting signals — the element says “I’m a data cell” while the attribute says “I’m a header for this row.” Second, screen readers rely on proper <th> elements with scope to announce table relationships. A <td> with scope may not be interpreted correctly, making the table harder to navigate for users of assistive technology. Third, using obsolete attributes means your markup doesn’t conform to current standards, which could lead to unpredictable behavior in future browsers.
The fix is straightforward: if a cell has a scope attribute, it’s acting as a header and should be a <th> element. Change the <td> to <th> and keep the scope attribute. If the cell is genuinely a data cell and not a header, remove the scope attribute entirely and leave it as a <td>.
Examples
Incorrect: scope on a <td> element
<table>
<tr>
<td scope="col">Name</td>
<td scope="col">Role</td>
</tr>
<tr>
<td scope="row">Alice</td>
<td>Engineer</td>
</tr>
</table>
This triggers the validation error because scope is used on <td> elements. The first row contains column headers and the first column contains row headers, yet they are all marked as data cells.
Correct: scope on <th> elements
<table>
<tr>
<th scope="col">Name</th>
<th scope="col">Role</th>
</tr>
<tr>
<th scope="row">Alice</th>
<td>Engineer</td>
</tr>
</table>
Now the header cells are correctly marked with <th>, and the scope attribute is valid on each one. Screen readers can properly associate “Alice” with “Engineer” and announce the column header “Role” when navigating to that cell.
A more complete table example
<table>
<thead>
<tr>
<th scope="col">Day</th>
<th scope="col">Morning</th>
<th scope="col">Afternoon</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Monday</th>
<td>Meeting</td>
<td>Code review</td>
</tr>
<tr>
<th scope="row">Tuesday</th>
<td>Workshop</td>
<td>Planning</td>
</tr>
</tbody>
</table>
Here, scope="col" on the column headers in <thead> tells assistive technology that “Day,” “Morning,” and “Afternoon” each apply to the cells below them. scope="row" on “Monday” and “Tuesday” indicates they apply to the cells in their respective rows. Every scope attribute sits on a <th>, so the markup is valid and accessible.
When to remove scope instead
If the cell truly contains data and isn’t a header, simply remove the scope attribute:
<!-- Before (invalid) -->
<td scope="row">Some data</td>
<!-- After (valid) -->
<td>Some data</td>
Only add scope when a cell genuinely serves as a header. If it does, make it a <th>. If it doesn’t, leave it as a plain <td> without scope.
Ready to validate your sites?
Start your free trial today.