# The “scope” attribute on the “td” element is obsolete. Use the “scope” attribute on a “th” element instead.

> Canonical HTML version: https://rocketvalidator.com/html-validation/the-scope-attribute-on-the-td-element-is-obsolete-use-the-scope-attribute-on-a-th-element-instead
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

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

```html
<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

```html
<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

```html
<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:

```html
<!-- 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`.
