Etiqueta th en HTML: encabezados, scope y asociaciones
La etiqueta <th> representa una celda de encabezado que identifica datos de una tabla. Sirve para que un valor como «12» pueda entenderse como las horas del curso HTML, gracias a sus encabezados de columna y fila. Úsala para nombres de categorías o registros que orientan la lectura; los valores que describen esos registros van en <td>.
Ejemplo mínimo: encabezados de columna y fila
Pega este fragmento en el cuerpo de un documento HTML:
<table>
<caption>Duración del curso</caption>
<tr><th scope="col">Curso</th><th scope="col">Horas</th></tr>
<tr><th scope="row">HTML</th><td>12</td></tr>
</table>
«Curso» y «Horas» identifican las columnas; «HTML» identifica la fila de la duración. Así, el dato 12 tiene dos referencias: HTML y Horas. Sin CSS, los navegadores suelen mostrar <th> en negrita y centrado, pero los bordes no aparecen necesariamente.
| Curso | Horas |
|---|---|
| HTML | 12 |
Si cambias 12 por 14, cambia la duración. Si sustituyes <th scope="row">HTML</th> por <td>HTML</td>, el nombre sigue visible, pero deja de ser un encabezado de fila. Darle font-weight: bold o centrarlo con CSS no recupera esa asociación.
Sintaxis y contexto válido
Escribe <th>…</th> como hija de <tr>, nunca directamente dentro de <table> o <thead>. Puede estar en filas de <thead>, <tbody> y <tfoot>: su función depende de qué datos encabeza, no de ocupar la parte superior.
Admite contenido de flujo, por ejemplo texto, enlaces o párrafos, con restricciones para todos sus descendientes: no puede contener <header>, <footer>, contenido de sección como <section>, <article>, <aside> o <nav>, ni contenido de encabezado como <h1> a <h6> o <hgroup>. Un encabezado de celda no es un título de sección de la página.
Los ejemplos conservan el cierre explícito. En HTML se permite omitir </th> cuando sigue inmediatamente otra celda <th> o <td>, o cuando no queda contenido en la fila. Estas reglas están en el modelo de contenido de th del estándar HTML.
Scope: qué datos identifica cada encabezado
Para una tabla sencilla, declara scope="col" en los encabezados de columna y scope="row" en los de fila. La guía de WAI sobre tablas con dos direcciones de encabezados desarrolla este patrón.
También existen ámbitos de grupo:
colgroupidentifica las celdas restantes de un grupo de columnas. El encabezado debe estar situado en un grupo declarado con<colgroup>; combinar dos columnas concolspanno declara ese grupo.rowgroupidentifica las celdas restantes de un grupo de filas. Por ejemplo, un encabezado que abarca dos cursos de una categoría dentro del mismo<tbody>puede usarrowspan="2"yscope="rowgroup".
Usa esos valores solo cuando la relación realmente sea de grupo. WAI muestra cómo declarar los grupos y sus encabezados. Si omites scope, el navegador determina las asociaciones según el contexto; un valor inventado, como scope="column", es inválido y tampoco declara un ámbito de columna.
Caso práctico: oferta de cursos y plazas por turno
La primera tabla relaciona cada curso con sus horas y plazas. La segunda conserva la duración y divide las plazas en mañana y tarde. Para hacer explícitas las relaciones de sus dos niveles de cabecera, asignamos un id único a cada encabezado y enumeramos los correspondientes en headers.
Guarda este documento como cursos-th.html en UTF-8 y ábrelo en el navegador. Incluye las dos tablas y todo el CSS; no requiere JavaScript, servidor ni archivos externos.
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Encabezados de la oferta de cursos</title>
<style>
body {
max-width: 48rem;
margin: 2rem auto;
padding: 0 1rem;
font-family: sans-serif;
line-height: 1.5;
color: #222;
background: #fff;
}
.cursos-scroll { max-width: 100%; overflow-x: auto; }
.cursos-scroll:focus-visible {
outline: 3px solid #1554ad;
outline-offset: 3px;
}
.cursos { width: 100%; border-collapse: collapse; }
.cursos-turnos { min-width: 32rem; }
.cursos caption { padding: 0.75rem; text-align: left; }
.cursos th, .cursos td {
border: 1px solid #666;
padding: 0.75rem;
text-align: left;
}
.cursos th { background: #eaf2ff; }
</style>
</head>
<body>
<h1>Oferta de cursos</h1>
<h2>Duración y plazas</h2>
<div class="cursos-scroll" tabindex="0" role="region"
aria-label="Cursos: duración y plazas">
<table class="cursos">
<caption>Duración en horas y plazas disponibles</caption>
<thead>
<tr>
<th scope="col">Curso</th>
<th scope="col">Horas</th>
<th scope="col">Plazas</th>
</tr>
</thead>
<tbody>
<tr><th scope="row">HTML básico</th><td>12</td><td>20</td></tr>
<tr><th scope="row">CSS</th><td>16</td><td>15</td></tr>
<tr><th scope="row">JavaScript</th><td>20</td><td>12</td></tr>
</tbody>
</table>
</div>
<h2>Distribución por turno</h2>
<p>Si la tabla no cabe, enfoca su región con Tab y
desplázate con las flechas izquierda y derecha.</p>
<div class="cursos-scroll" tabindex="0" role="region"
aria-label="Plazas de los cursos por turno">
<table class="cursos cursos-turnos">
<caption>Horas del curso y plazas disponibles por turno</caption>
<thead>
<tr>
<th id="th-curso" rowspan="2">Curso</th>
<th id="th-horas" rowspan="2">Horas</th>
<th id="th-plazas" colspan="2">Plazas</th>
</tr>
<tr>
<th id="th-manana" headers="th-plazas">Mañana</th>
<th id="th-tarde" headers="th-plazas">Tarde</th>
</tr>
</thead>
<tbody>
<tr>
<th id="th-html" headers="th-curso">HTML básico</th>
<td headers="th-html th-horas">12</td>
<td headers="th-html th-plazas th-manana">12</td>
<td headers="th-html th-plazas th-tarde">8</td>
</tr>
<tr>
<th id="th-css" headers="th-curso">CSS</th>
<td headers="th-css th-horas">16</td>
<td headers="th-css th-plazas th-manana">9</td>
<td headers="th-css th-plazas th-tarde">6</td>
</tr>
<tr>
<th id="th-js" headers="th-curso">JavaScript</th>
<td headers="th-js th-horas">20</td>
<td headers="th-js th-plazas th-manana">7</td>
<td headers="th-js th-plazas th-tarde">5</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Primero comprueba las cuatro columnas de la tabla ampliada: Curso, Horas, Mañana y Tarde. rowspan="2" ocupa las dos filas de cabecera para Curso y Horas; colspan="2" sitúa Plazas sobre los dos turnos. No añadas otras celdas bajo Curso y Horas: esas posiciones ya están ocupadas.
En pantallas pequeñas, enfoca la región con Tab y usa las flechas para ver el turno de tarde.
| Curso | Horas | Plazas | |
|---|---|---|---|
| Mañana | Tarde | ||
| HTML básico | 12 | 12 | 8 |
| CSS | 16 | 9 | 6 |
| JavaScript | 20 | 7 | 5 |
El 6 se relaciona con «CSS», «Plazas» y «Tarde» mediante headers="th-css th-plazas th-tarde". Las plazas de los turnos suman las de la tabla sencilla: 12 + 8 = 20, 9 + 6 = 15 y 7 + 5 = 12. Las horas siguen siendo la duración del curso, no una suma de turnos.
Headers, id y otros atributos
headers admite IDs separados por espacios, sin repeticiones, que apuntan a elementos <th> de la misma tabla. Puede utilizarse tanto en <td> como en <th>, como muestra Mañana relacionada con Plazas. No incluyas el propio ID ni construyas referencias circulares. WAI explica esta técnica en tablas con encabezados de varios niveles.
id es global y debe ser único en todo el documento; también son globales class y lang. scope y abbr son específicos de <th>; headers, colspan y rowspan son atributos de celda compartidos con <td>.
colspan admite enteros de 1 a 1000; rowspan, de 0 a 65534. Ambos ocupan una posición si faltan. rowspan="0" abarca las filas restantes del mismo grupo. No permitas solapamientos ni extiendas una celda entre grupos de filas. Consulta los atributos comunes de las celdas en HTML.
abbr ofrece una etiqueta alternativa para referirse al encabezado. Por ejemplo, <th scope="col" abbr="Horas">Duración en horas</th> conserva el texto visible completo. Su uso por tecnologías de asistencia depende de la implementación; no garantiza un anuncio concreto. MDN detalla los atributos de th.
text-align, font-weight y background son propiedades CSS. En JavaScript, celda.colSpan sería una propiedad DOM; ninguno de estos ejemplos necesita scripts.
Cómo comprobar la lectura y los cambios
Prueba el documento a 375 y 1280 px. En móvil, usa Tab para enfocar la región de turnos, confirma que el foco sea visible y desplázate con las flechas hasta Tarde. Tab y Shift+Tab permiten salir. La página completa debe conservar su anchura; el desplazamiento corresponde a la región de la tabla.
Repite con JavaScript desactivado y retirando el CSS: los datos y encabezados siguen presentes. Los estilos del sitio dan a la demo una presentación distinta de la del archivo, sin cambiar sus relaciones. Con un lector de pantalla, recorre la celda 6 y comprueba su contexto; la manera de anunciar los encabezados varía entre combinaciones de navegador y lector.
Cambia «Tarde» por «Turno vespertino» conservando id="th-tarde": la relación permanece. Si retiras ese encabezado, actualiza las referencias headers y reorganiza la cuadrícula. Eliminarlo sin esos cambios deja una referencia inexistente y una cabecera incompleta.
Errores frecuentes y preguntas
¿Th solo va en thead? No. Los encabezados de fila pueden aparecer en <tbody> o <tfoot>. <thead> agrupa filas; no convierte cualquier <td> en encabezado.
¿Cuándo necesito headers? Cuando las relaciones complejas no quedan suficientemente expresadas por asociaciones simples. La tabla inicial de tres columnas puede conservar scope. Dos niveles regulares también pueden resolverse con grupos y scope; el caso ampliado enseña la alternativa explícita. Si la tabla resulta difícil de entender, considera dividirla antes de añadir asociaciones.
¿Por qué no se relaciona una celda con su encabezado? Comprueba que el encabezado sea <th>, que scope tenga un valor permitido y que cada token de headers coincida exactamente con un ID existente de esa tabla. Revisa IDs duplicados y la cuadrícula. Después comprueba la lectura con tu combinación de navegador y tecnología de asistencia; el texto en negrita no prueba una asociación.
Compatibilidad y etiquetas relacionadas
Consulta del 4 de octubre de 2026: MDN registra <th> como ampliamente disponible en los navegadores. La existencia del elemento no garantiza la misma lectura de headers o abbr en todas las tecnologías de asistencia.
La guía de td explica las celdas de datos; la guía de table, la estructura del conjunto. <tr> forma las filas y <thead> agrupa las de cabecera: sus guías se enlazarán cuando estén integradas.