Acerca de este problema HTML
El atributo scope indica a los navegadores y tecnologías de asistencia cómo se relaciona una celda de encabezado con las celdas de datos que la rodean. Sus valores válidos son col, row, colgroup, y rowgroup. En versiones anteriores de HTML, scope estaba permitido en elementos <td>, pero el HTML Living Standard actual lo restringe únicamente a elementos <th>. Cuando el validador de W3C encuentra scope en un <td>, lo marca como obsoleto.
Esto es importante por varias razones. Primero, si una celda actúa como encabezado para otras celdas, debería marcarse como <th>, no como <td>. Usar <td scope="row"> envía señales contradictorias — el elemento dice “soy una celda de datos” mientras que el atributo dice “soy un encabezado para esta fila.” Segundo, los lectores de pantalla dependen de elementos <th> apropiados con scope para anunciar las relaciones de la tabla. Un <td> con scope puede no interpretarse correctamente, haciendo que la tabla sea más difícil de navegar para usuarios de tecnología de asistencia. Tercero, usar atributos obsoletos significa que tu marcado no cumple con los estándares actuales, lo que podría llevar a comportamientos impredecibles en navegadores futuros.
La solución es sencilla: si una celda tiene un atributo scope, está actuando como encabezado y debería ser un elemento <th>. Cambia el <td> por <th> y mantén el atributo scope. Si la celda es genuinamente una celda de datos y no un encabezado, elimina el atributo scope completamente y déjala como <td>.
Ejemplos
Incorrecto: scope en un elemento <td>
<table>
<tr>
<td scope="col">Name</td>
<td scope="col">Role</td>
</tr>
<tr>
<td scope="row">Alice</td>
<td>Engineer</td>
</tr>
</table>
Esto activa el error de validación porque scope se usa en elementos <td>. La primera fila contiene encabezados de columna y la primera columna contiene encabezados de fila, pero todos están marcados como celdas de datos.
Correcto: scope en elementos <th>
<table>
<tr>
<th scope="col">Name</th>
<th scope="col">Role</th>
</tr>
<tr>
<th scope="row">Alice</th>
<td>Engineer</td>
</tr>
</table>
Ahora las celdas de encabezado están correctamente marcadas con <th>, y el atributo scope es válido en cada una. Los lectores de pantalla pueden asociar apropiadamente “Alice” con “Engineer” y anunciar el encabezado de columna “Role” al navegar a esa celda.
Un ejemplo de tabla más completo
<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>
Aquí, scope="col" en los encabezados de columna en <thead> indica a la tecnología de asistencia que “Day,” “Morning,” y “Afternoon” se aplican cada uno a las celdas debajo de ellos. scope="row" en “Monday” y “Tuesday” indica que se aplican a las celdas en sus respectivas filas. Cada atributo scope está en un <th>, por lo que el marcado es válido y accesible.
Cuándo eliminar scope en su lugar
Si la celda realmente contiene datos y no es un encabezado, simplemente elimina el atributo scope:
<!-- Antes (inválido) -->
<td scope="row">Some data</td>
<!-- Después (válido) -->
<td>Some data</td>
Solo agrega scope cuando una celda genuinamente sirve como encabezado. Si lo hace, hazla un <th>. Si no lo hace, déjala como un <td> simple sin scope.
Encuentra problemas como este automáticamente
Rocket Validator escanea miles de páginas en segundos, detectando problemas de HTML en todo tu sitio web.