Saltar al contenido
tablas.html · devschool

Tablas en HTML

Lección 14 de 23 · 8 min de lectura · Actualizado el

En esta lección
  1. Las etiquetas básicas
  2. Agrupar las filas
  3. Encabezados con scope
  4. Unir celdas
  5. Columnas con <colgroup> y <col>
  6. Los bordes se ponen con CSS
  7. Accesibilidad de las tablas
  8. Cuándo NO usar tablas
  9. Errores frecuentes
  10. Resumen

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 thead o poner en negrita el tfoot con 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 scopeEl <th> es encabezado de…
colSu columna
rowSu fila
colgroupUn grupo de columnas
rowgroupUn 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, width y visibility. 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:

  1. Un <caption> que diga de qué trata.
  2. Encabezados <th> en vez de celdas <td> en negrita.
  3. scope en los encabezados para indicar si son de fila o de columna.
  4. Tablas sencillas. Si necesitas muchas celdas unidas y encabezados a varios niveles, plantéate dividirla en dos tablas más simples.
  5. 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 colspan o rowspan.
  • 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 atributoPara 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> + scopeCelda de encabezado de columna (col) o fila (row)
<td>Celda de datos
colspan / rowspanUne 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).

tablas.html
Resultado

Pon a prueba lo que has aprendido

[HTML] ¿Qué etiqueta crea una celda de encabezado en una tabla?

[HTML] ¿Qué hace colspan="2" en una celda?

[HTML] ¿Para qué NO deben usarse las tablas hoy?

[HTML] En la primera fila de datos, la celda del Aula 1 tiene rowspan="2". ¿Cuántas celdas debe tener la fila siguiente?
<tr><th>Hora</th><th>Aula 1</th><th>Aula 2</th></tr>
<tr><th>16:00</th><td rowspan="2">Robótica</td><td>Inglés</td></tr>
<tr><!-- ¿cuántas celdas aquí? --></tr>

[HTML] ¿Para qué sirve scope="row" en este encabezado?
<tr>
  <th scope="row">Lunes</th>
  <td>34</td>
  <td>58</td>
</tr>

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.