Tablas en HTML
En esta lección
Las tablas sirven para mostrar datos en filas y columnas: horarios, precios, resultados, comparativas. En esta lección aprenderás a construirlas desde cero, a agruparlas en encabezado, cuerpo y pie, a unir celdas, a hacerlas accesibles para los lectores de pantalla y a saber cuándo no debes usarlas.
Una buena pista para saber si algo es una tabla: si tiene sentido leerlo por filas y por columnas a la vez (qué precio tiene el café, qué productos cuestan menos de 2 €), es una tabla.
Las etiquetas básicas
<table>
<tr>
<th>Lenguaje</th>
<th>Año</th>
</tr>
<tr>
<td>HTML</td>
<td>1993</td>
</tr>
<tr>
<td>JavaScript</td>
<td>1995</td>
</tr>
</table>
<table>envuelve toda la tabla.<tr>(table row) es una fila.<th>(table header) es una celda de encabezado. Por defecto sale en negrita y centrada.<td>(table data) es una celda normal.
Las tablas se construyen fila a fila: dentro de cada <tr> van sus celdas, de izquierda a derecha. No existe una etiqueta para “columna”: las columnas aparecen solas porque cada fila tiene el mismo número de celdas.
Agrupar las filas
Para tablas más grandes, separa el encabezado del cuerpo:
<table>
<caption>Precios de la cafetería</caption>
<thead>
<tr><th>Producto</th><th>Precio</th></tr>
</thead>
<tbody>
<tr><td>Café</td><td>1,50 €</td></tr>
<tr><td>Tostada</td><td>2,20 €</td></tr>
</tbody>
<tfoot>
<tr><td>Total</td><td>3,70 €</td></tr>
</tfoot>
</table>
<caption>es el título de la tabla. Ayuda mucho a los lectores de pantalla.<thead>,<tbody>y<tfoot>agrupan las filas de encabezado, contenido y pie.
¿Para qué sirve agruparlas si no cambia nada a la vista?
- Estilos. Puedes dar un fondo al
theado poner en negrita eltfootcon selectores sencillos. - Impresión. Si una tabla larga ocupa varias hojas, el navegador puede repetir el
<thead>en cada una. - Tablas largas. Con CSS puedes dejar fijo el encabezado mientras el cuerpo se desplaza.
- Claridad. Quien lea tu código ve al instante qué es cada parte.
El <caption> debe ser el primer hijo de <table>. Una tabla puede tener varios <tbody> para separar bloques de filas, por ejemplo un bloque por trimestre.
Encabezados con scope
Un <th> puede ser encabezado de una columna o de una fila. El atributo scope lo deja claro:
<table>
<caption>Asistencia al gimnasio por turno</caption>
<thead>
<tr>
<th scope="col">Día</th>
<th scope="col">Mañana</th>
<th scope="col">Tarde</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Lunes</th>
<td>34</td>
<td>58</td>
</tr>
<tr>
<th scope="row">Martes</th>
<td>29</td>
<td>61</td>
</tr>
</tbody>
</table>
Aquí “Lunes” no es un dato más: es el encabezado de su fila. Gracias a scope, cuando alguien con lector de pantalla llega a la celda 58, oye algo como “Lunes, Tarde, 58”. Sin encabezados, solo oiría “58” y tendría que adivinar a qué se refiere.
Valor de scope | El <th> es encabezado de… |
|---|---|
col | Su columna |
row | Su fila |
colgroup | Un grupo de columnas |
rowgroup | Un grupo de filas |
Unir celdas
colspan="2"hace que una celda ocupe dos columnas.rowspan="2"hace que ocupe dos filas.
<tr>
<td colspan="2">Esta celda ocupa dos columnas</td>
</tr>
Cuando una celda ocupa dos columnas, esa fila tiene una celda menos. Si no cuadran, la tabla se descoloca.
rowspan paso a paso
Con rowspan hay que tener más cuidado, porque la celda “baja” a las filas siguientes. Mira este horario de una academia:
<table>
<caption>Clases del lunes</caption>
<tr>
<th scope="col">Hora</th>
<th scope="col">Aula 1</th>
<th scope="col">Aula 2</th>
</tr>
<tr>
<th scope="row">16:00</th>
<td rowspan="2">Taller de robótica (2 horas)</td>
<td>Inglés</td>
</tr>
<tr>
<th scope="row">17:00</th>
<td>Francés</td>
</tr>
</table>
El resultado se ve así:
| Hora | Aula 1 | Aula 2 |
|-------|---------------------|---------|
| 16:00 | Taller de robótica | Inglés |
| 17:00 | (2 horas) | Francés |
La fila de las 17:00 solo tiene dos celdas (la hora y Francés), porque el hueco del Aula 1 ya lo ocupa el taller. Un truco para no equivocarte: dibuja la tabla en papel y tacha las casillas que ya ocupan las celdas unidas.
Columnas con <colgroup> y <col>
Aunque no haya etiqueta de columna para el contenido, sí puedes agrupar columnas para darles estilo. <colgroup> va justo después del <caption>:
<table>
<caption>Notas de la evaluación</caption>
<colgroup>
<col>
<col span="3" class="notas">
<col class="media">
</colgroup>
<tr>
<th scope="col">Alumno</th>
<th scope="col">Examen 1</th>
<th scope="col">Examen 2</th>
<th scope="col">Examen 3</th>
<th scope="col">Media</th>
</tr>
<tr>
<th scope="row">Lucía</th>
<td>7</td><td>8</td><td>9</td><td>8</td>
</tr>
</table>
span="3" hace que un <col> represente tres columnas. Con CSS puedes darles fondo o ancho:
.notas { background: #f5f5f5; }
.media { background: #e0f2fe; width: 6rem; }
Cuidado: sobre un
<col>solo funcionan unas pocas propiedades CSS:background,border,widthyvisibility. No puedes cambiar el color del texto ni la alineación de una columna desde ahí.
Los bordes se ponen con CSS
Una tabla sin estilos no tiene bordes. Este CSS le da un aspecto limpio:
table { border-collapse: collapse; }
th, td { border: 1px solid #ccc; padding: 8px; }
border-collapse: collapse junta los bordes de las celdas para que no salgan dobles.
Los atributos antiguos border, cellpadding, bgcolor o align en <table> están obsoletos. Todo el aspecto va en CSS; lo verás en listas y tablas con CSS.
Tablas anchas en el móvil
Una tabla con muchas columnas no cabe en una pantalla de 360 px. La solución más sencilla es envolverla en un contenedor con desplazamiento horizontal:
<div class="tabla-scroll" role="region" aria-labelledby="cap-tarifas" tabindex="0">
<table>
<caption id="cap-tarifas">Tarifas 2026</caption>
...
</table>
</div>
.tabla-scroll { overflow-x: auto; }
El tabindex="0" permite desplazar la tabla también con el teclado, y role="region" con su nombre le dice al lector de pantalla qué es esa zona.
Accesibilidad de las tablas
Resumiendo lo que hace que una tabla sea accesible:
- Un
<caption>que diga de qué trata. - Encabezados
<th>en vez de celdas<td>en negrita. scopeen los encabezados para indicar si son de fila o de columna.- Tablas sencillas. Si necesitas muchas celdas unidas y encabezados a varios niveles, plantéate dividirla en dos tablas más simples.
- Sin celdas vacías sin motivo. Si un dato no existe, escribe ”—” o “No disponible”.
Para tablas muy complejas existe el atributo headers, que en cada celda enumera los id de sus encabezados, pero en la práctica casi siempre es mejor simplificar la tabla.
Cuándo NO usar tablas
Hace años las páginas se maquetaban con tablas para colocar columnas y menús. Ya no se hace. Las tablas son solo para datos tabulares. Para colocar elementos en la página se usa CSS (Flexbox y Grid).
Los motivos son muy concretos:
- Accesibilidad. Un lector de pantalla anuncia “tabla, 3 columnas, 5 filas” y lee la página celda a celda. Si la tabla solo servía para colocar cosas, la experiencia es un caos.
- Responsive. Una tabla no se puede reorganizar en el móvil: las columnas siguen una al lado de la otra. Con Grid o Flexbox, pasar de tres columnas a una es una línea de CSS.
- Mantenimiento. Cambiar el diseño obliga a reescribir el HTML entero, porque estructura y aspecto están mezclados.
- Semántica. Una tabla dice “esto son datos relacionados por filas y columnas”. Si no lo son, estás mintiendo al navegador.
Aprenderás a hacer esas maquetaciones en Flexbox y Grid.
Errores frecuentes
- Filas con distinto número de celdas por no descontar las que ocupan un
colspanorowspan. - Poner texto o elementos directamente en
<table>o<tr>, fuera de un<td>o<th>. El navegador los saca de la tabla. - Usar
<td><strong>en lugar de<th>para los encabezados. - Olvidar el
<caption>o poner el título en un párrafo aparte. - Poner el
<caption>en otro sitio que no sea el primer hijo de<table>. - Usar tablas para maquetar la página.
Resumen
| Etiqueta o atributo | Para qué sirve |
|---|---|
<table> | Envuelve la tabla |
<caption> | Título de la tabla (primer hijo) |
<thead>, <tbody>, <tfoot> | Agrupan filas de encabezado, cuerpo y pie |
<tr> | Una fila |
<th> + scope | Celda de encabezado de columna (col) o fila (row) |
<td> | Celda de datos |
colspan / rowspan | Une celdas en horizontal / en vertical |
<colgroup> y <col> | Agrupan columnas para darles estilo |
Pruébalo tú
Cambia el código y pulsa Ejecutar (o Ctrl + Enter).
Pon a prueba lo que has aprendido
¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.