15 de septiembre de 2026·11 min de lectura
Accesibilidad de encabezados de tabla: la regla WCAG que la mayoría de los sitios pasa por alto
Una tabla de datos sin marcado de encabezados reales se lee en un lector de pantalla como números sin sentido. Vea la corrección de la WCAG 1.3.1 y qué puede y qué no puede corregir Axeazy automáticamente.
Una tabla de datos sin marcado de encabezados reales se lee en un lector de pantalla como una sucesión de números sueltos, sin saber a qué fila o columna pertenece cada uno. Corregirlo significa usar <th> en lugar de <td> para las celdas de encabezado y agregar un atributo scope, lo que cumple la WCAG 1.3.1 (Información y relaciones) y convierte una tabla que es solo una disposición visual en algo que un lector de pantalla realmente puede recorrer.

Puntos clave
<th>y<td>se ven idénticos si les da el mismo estilo, pero solo<th>le dice a un lector de pantalla "esto es un encabezado". El texto en negrita y centrado dentro de un<td>es invisible como encabezado para la tecnología de asistencia, sin importar cómo se vea.- El atributo
scopele dice a un lector de pantalla en qué dirección se aplica un encabezado. Los valores válidos soncol,row,colgroupyrowgroup, ningún otro. - Es un requisito de la WCAG 1.3.1 (Información y relaciones), Nivel A. También corresponde al 1194.22(g) de la Sección 508 y al 9.1.3.1 de la EN 301 549, así que no es una regla exclusiva de Estados Unidos.
- axe-core detecta siete problemas distintos en tablas, y solo uno de ellos, un valor de
scopemal escrito, tiene hoy alguna corrección automática. El resto necesita a una persona que entienda qué significa realmente la tabla. - Las tablas simples (encabezados solo en la primera fila o la primera columna) necesitan menos marcado de lo que sugieren la mayoría de las guías. Allí bastan elementos
<th>simples;scopese vuelve necesario cuando una tabla tiene encabezados en más de una dirección.
Por qué <th> frente a <td> lo es todo

Un visitante que ve lee una tabla recorriendo una fila y subiendo hasta el título de la columna, sin pensarlo. Un lector de pantalla no tiene una forma equivalente de "echar un vistazo hacia arriba". Lee celda por celda, y la única manera de saber que una celda es un encabezado, y no solo otro dato, es el elemento HTML subyacente.
<th> es una celda de encabezado. Los navegadores la ponen en negrita y centrada de forma predeterminada, y los lectores de pantalla la anuncian como encabezado cuando el usuario navega por la tabla. <td> es una celda de datos simple. No lleva ese anuncio, sin importar qué CSS se le aplique.
Aquí es donde casi toda tabla del mundo real falla. Un desarrollador construye una tabla, quiere que la fila de encabezado se vea en negrita y recurre a <td style="font-weight: bold"> en lugar de <th>. Visualmente es indistinguible de un encabezado real. Para un lector de pantalla es solo otra celda de datos que resulta estar en negrita, sin ninguna relación con las celdas de debajo.
<!-- Falla: parece una fila de encabezado, se anuncia como datos simples -->
<table>
<tr>
<td><strong>Day</strong></td>
<td><strong>Open</strong></td>
<td><strong>Close</strong></td>
</tr>
<tr>
<td>Monday</td>
<td>9:00 AM</td>
<td>6:00 PM</td>
</tr>
</table>
<!-- Pasa: celdas de encabezado reales, anunciadas como encabezados, más un título -->
<table>
<caption>Store hours</caption>
<tr>
<th scope="col">Day</th>
<th scope="col">Open</th>
<th scope="col">Close</th>
</tr>
<tr>
<td>Monday</td>
<td>9:00 AM</td>
<td>6:00 PM</td>
</tr>
</table>
Ambas se muestran igual para un visitante que ve. Solo la segunda le dice a un usuario de lector de pantalla que "9:00 AM" pertenece a "Open" en "Monday".
El atributo scope y cuándo realmente lo necesita

Para una tabla simple, una que tiene encabezados solo en la primera fila o solo en la primera columna, no en ambas, basta con <th>. Un lector de pantalla puede inferir correctamente la dirección. Es un caso en el que el requisito estricto de la WCAG es realmente más ligero de lo que sugiere mucho contenido sobre accesibilidad.
Cuando una tabla tiene encabezados en dos direcciones a la vez, un horario con los días arriba y las franjas horarias a un lado, por ejemplo, scope deja de ser opcional en la práctica. Sin él, un lector de pantalla no tiene una forma fiable de saber si un <th> determinado rotula la fila o la columna en la que se encuentra.
<table>
<caption>Weekly class schedule</caption>
<tr>
<th scope="col"></th>
<th scope="col">Monday</th>
<th scope="col">Wednesday</th>
</tr>
<tr>
<th scope="row">9:00 AM</th>
<td>Yoga</td>
<td>Pilates</td>
</tr>
<tr>
<th scope="row">6:00 PM</th>
<td>Spin</td>
<td>Yoga</td>
</tr>
</table>
Aquí, scope="col" marca los encabezados de los días y scope="row" marca los encabezados de las horas. Un usuario de lector de pantalla que llega a la celda "Pilates" escucha ambos: Wednesday, 9:00 AM, Pilates.
Para una tabla realmente irregular, con celdas combinadas o encabezados que no están limpiamente en una sola fila o columna, scope no basta por sí solo. Para eso sirven los atributos headers e id: cada celda de datos enumera explícitamente los id de cada celda de encabezado que le corresponde.
<th id="q3">Q3</th>
...
<td headers="q3">42</td>
Es más trabajo de escribir y de mantener, que es exactamente la razón por la que se reserva para las tablas que scope realmente no puede describir, y no se usa por defecto.
Qué verifica realmente axe-core en una tabla
axe-core, el mismo motor detrás del panel de accesibilidad de Chrome DevTools y del escáner de Axeazy, ejecuta siete verificaciones distintas sobre el marcado de tablas. Solo una tiene hoy una corrección automática.
| Regla | Qué verifica | Vía de corrección |
|---|---|---|
scope-attr-valid |
El valor de scope no es una palabra real: un error de escritura o plural de col/row/colgroup/rowgroup |
Corregida automáticamente mediante pull request en GitHub, de forma acotada: solo errores reconocibles |
empty-table-header |
Existe un <th> pero no tiene texto dentro |
Manual |
th-has-data-cells |
Existe un <th> pero ninguna celda de datos lo usa |
Manual |
td-has-header |
Una celda de datos no tiene ningún encabezado asociado | Manual |
td-headers-attr |
Un atributo headers apunta a un id que no es una celda de encabezado real |
Manual |
table-duplicate-name |
Dos tablas de la misma página comparten el mismo nombre accesible | Manual |
table-fake-caption |
Texto con estilo para parecer un título en lugar de un elemento <caption> real |
Manual |
Esa tabla deja clara la imagen honesta. La estructura de tablas es una categoría abrumadoramente de corrección manual. La única parte que se escribe automáticamente es corregir un valor de scope que ya existe pero está mal escrito, algo como "cols" o "ROW " que se normaliza a "col" o "row". Agregar un encabezado faltante, escribir un título o determinar qué id de headers corresponde a cada celda requiere entender qué significa realmente la tabla, y eso sigue siendo trabajo de una persona.
Cómo revisar sus propias tablas
No necesita tener instalado un lector de pantalla para detectar la versión más común de este error.
- Vea el código fuente de la página. Haga clic derecho en cualquier tabla de su sitio y elija Ver código fuente de la página, o abra DevTools y vaya al panel Elements. Busque
<th. Si la fila que parece un encabezado está hecha de elementos<td>, esa tabla falla. - Compruebe el valor de
scopeen tablas con varias direcciones. Si una tabla tiene encabezados tanto arriba como a un lado, confirme que cada<th>llevescope="col"oscope="row", y no solo estilo en negrita. - Escúchela. En NVDA, moverse por una tabla correctamente marcada con la navegación de tablas (
Ctrl+Alt+teclas de flecha) anuncia el encabezado correspondiente junto al valor de cada celda. Si solo escucha números en bruto sin que se pronuncie antes un encabezado, la tabla no está asociada correctamente. - O ejecute un escaneo en lugar de revisar tabla por tabla. El escaneo gratuito de Axeazy verifica cada tabla de su página de inicio con las siete reglas anteriores en unos 60 segundos, junto con las demás categorías de corrección que cubre.
Errores comunes
- Celdas
<td>en negrita que hacen las veces de<th>. El fallo más común, y el más difícil de detectar a simple vista, porque se ve completamente correcto. - Un título que es solo una línea de texto en negrita sobre la tabla, en lugar de un elemento
<caption>real. Los visitantes que ven no notan la diferencia; un lector de pantalla sí. - Varias tablas en una página sin un título que las distinga, de modo que un usuario de lector de pantalla no puede saber cuál es cuál al saltar entre ellas.
- Usar una tabla solo para la disposición visual, no para datos tabulares. Un lector de pantalla igualmente intenta anunciar relaciones de fila y columna que nunca debieron existir, lo cual confunde más que no tener estructura. El CSS moderno (Grid o Flexbox) resuelve la disposición sin este efecto secundario.
- Recurrir a
scopecuando una tabla en realidad necesitaheaders/id.scopesolo describe una relación simple de fila o columna. Una tabla con celdas combinadas o con encabezados que no están limpiamente en una fila o columna necesita en cambio el emparejamiento más explícito deheaders/id.
Qué puede corregir Axeazy aquí

De esta categoría es más honesto hablar que de la mayoría, porque la parte automática es realmente pequeña.
El escaneo de Axeazy marca las siete reglas de tabla anteriores en cuanto las encuentra, la misma detección sea Axeazy, Chrome DevTools o cualquier otra herramienta construida sobre axe-core. Escribir la corrección es donde pasa a ser manual. La única corrección relacionada con tablas que llega hoy a un pull request real de GitHub es la de un valor de scope ya presente que es un error de escritura o un plural reconocible; nada más en esta categoría tiene aún una vía automatizada.
Tampoco existe hoy ninguna vía del plugin de WordPress para las correcciones de tablas. Las tres correcciones instantáneas del plugin gratuito cubren la navegación de salto, el atributo de idioma y el texto alternativo de respaldo, ninguna de las cuales toca el marcado de tablas, y los niveles de pago tampoco se extienden hoy a la estructura de tablas.
No es una laguna que alguien olvidó. Decidir si un <td> debió ser un <th>, o a qué encabezado pertenece realmente una celda irregular, requiere entender lo que la tabla intenta comunicar. Un script que adivine mal aquí tergiversaría silenciosamente los datos justo ante las personas que dependen del marcado para entenderlos, lo cual es peor que dejarlo marcado para que una persona lo corrija bien. Vea el desglose completo de las categorías de corrección.
Preguntas frecuentes
¿Necesito un atributo scope en cada celda de encabezado?
No. Para una tabla simple con encabezados solo en la primera fila o solo en la primera columna, bastan por sí solos los elementos <th> simples. scope se vuelve necesario cuando una tabla tiene encabezados en dos direcciones a la vez, como un horario con los días arriba y las horas a un lado.
¿Cuál es la diferencia entre scope y headers/id?
scope describe una relación simple y en una sola dirección: un encabezado que se aplica a toda una fila, columna o grupo de filas o columnas. headers/id es más explícito: cada celda de datos enumera exactamente qué celdas de encabezado le corresponden por id. Use scope para tablas regulares en forma de cuadrícula y headers/id solo para tablas irregulares con celdas combinadas o con encabezados que no están limpiamente en una fila o columna.
¿Axeazy corrige automáticamente los encabezados de tabla ausentes?
En su mayoría no, y conviene ser directos. La única corrección relacionada con tablas que tiene hoy una vía automática funcional es la de un valor de scope ya presente pero mal escrito. Agregar un encabezado faltante, escribir un título real o asignar headers al id correcto requiere entender qué significa la tabla, así que siguen siendo elementos de revisión manual.
¿Necesito un título (caption) en cada tabla?
No es un requisito estricto de la WCAG 1.3.1 por sí solo, pero es realmente útil, sobre todo cuando una página tiene más de una tabla. Un título le da a la tabla su nombre accesible, para que un usuario de lector de pantalla que salta entre tablas pueda saber en cuál ha aterrizado.
¿Y las tablas usadas para el diseño de la página en lugar de datos?
Evítelas siempre que sea posible. Un lector de pantalla igualmente intenta anunciar las relaciones de fila y columna en una tabla de diseño, lo que genera una confusión que no existiría con un diseño en CSS simple. Si una tabla de diseño heredada no se puede eliminar de inmediato, marcarla con role="presentation" le indica a la tecnología de asistencia que omita por completo la semántica de tabla.
Fuentes
¿Quiere recibir esto en su correo?
The ADA Alert. Información semanal.
Cada martes: noticias de accesibilidad, problemas comunes de WCAG y correcciones a nivel de código. Gratis. Cancele con un clic. El boletín está escrito en inglés.
Alcance de cada informe que entregamos: LIMITACIÓN DEL ALCANCE: Este informe documenta las infracciones identificadas mediante un escaneo automatizado de WCAG 2.2 AA con axe-core v4.11.0. Las herramientas automatizadas no pueden evaluar todos los criterios de WCAG; muchos criterios requieren revisión manual. Este informe no constituye asesoría legal, no garantiza el cumplimiento de la ADA ni protege contra acciones legales. El cumplimiento de la ADA es una determinación legal que corresponde a los tribunales. Para una evaluación completa de conformidad con WCAG, contrate a un profesional de accesibilidad certificado por la IAAP.