Skip to content
This page has been auto-translated and may contain errors.View in English

Tablas

docs.scrimba.com

Algunos datos forman una cuadrícula. Un horario de trenes, un plan de precios, una tabla de posiciones, una lista de información nutricional: cada uno tiene filas y columnas, y el significado está en cómo se alinean. HTML tiene un conjunto dedicado de elementos para exactamente este tipo de contenido, y usarlos mantiene la cuadrícula legible tanto en pantalla como para software que lee la página en voz alta.

Conceptos básicos de tablas

Una tabla es una cuadrícula de filas y columnas, con la misma forma que una hoja de cálculo. La construyes con cuatro elementos. <table> envuelve toda la cuadrícula. Cada <tr> es una fila (tr es abreviatura de table row). Dentro de una fila, cada <td> es una celda de datos (td es table data). Cuando una celda etiqueta su columna o fila, usas <th> en su lugar (th es table header), y el navegador la muestra en negrita y centrada para que destaque de los datos.

Construyes una fila de tabla de fila en fila, nunca de columna en columna. <table> es el contenedor, cada <tr> es una fila, y las celdas se sientan dentro de la fila en el orden en que aparecen en la página. Una celda de datos es <td>; una celda de encabezado es <th>. No hay elemento de columna. Las columnas son un efecto emergente de cada fila manteniendo sus celdas en el mismo orden, así que si una fila se desalinea la cuadrícula deja de alinearse.

La diferencia entre <th> y <td> no es cosmética. <th> marca una celda como encabezado de la fila o columna en que se encuentra. El estilo predeterminado del navegador, negrita y centrada, es solo la mitad visible de eso. La otra mitad es significado que otro software puede leer.

El código fuente de una tabla es row-major: la escribes de fila en fila, y la columna de cada celda se decide puramente por su posición dentro de la fila. El navegador lee ese código fuente fila a fila y construye una cuadrícula bidimensional, haciendo coincidir celdas en columnas contando a través. Nada en el marcado nombra una columna, así que la cuadrícula solo está tan alineada como tus filas sean consistentes.

<th> versus <td> es una distinción semántica, no de estilo. <th> (una celda de encabezado) le dice al navegador, y a cualquier tecnología de asistencia que lee la página (software como un lector de pantalla, que habla la página en voz alta para personas que no pueden verla), que esta celda es una etiqueta para los datos que la rodean. El aspecto en negrita y centrado es incidental: quítalo con CSS y el encabezado sigue significando "encabezado", porque el significado vive en el elemento, no en su apariencia. Esa es toda la razón para usar una tabla real en lugar de dibujar una cuadrícula de otra forma.

html
<table>
  <tr>
    <th>Día</th>
    <th>Horario de apertura</th>
  </tr>
  <tr>
    <td>Lunes</td>
    <td>8:00 a 18:00</td>
  </tr>
  <tr>
    <td>Sábado</td>
    <td>9:00 a 14:00</td>
  </tr>
</table>

Dos celdas de encabezado en la parte superior, luego dos filas de datos. El navegador dibuja la cuadrícula, dimensiona cada columna para que se ajuste a su contenido, y representa las dos celdas <th> en negrita.

JunoConceptos básicos de tablas Cuatro elementos hacen una cuadrícula: <table> alrededor de todo, <tr> para cada fila, <td> para una celda, y <th> para una celda de encabezado. Las celdas de encabezado salen en negrita y centradas para que destaquen de los datos. Construye fila a fila y las columnas se alinean solas.
JunoConceptos básicos de tablas Diseñas una tabla fila a fila con <tr>, y las columnas surgen de cada fila manteniendo sus celdas en el mismo orden. <th> para encabezados, <td> para datos, y esa elección es significado, no solo la apariencia en negrita. Cuenta mal las celdas en una fila y toda la cuadrícula se tuerce.
JunoConceptos básicos de tablas El marcado es row-major, así que una columna solo existe porque cada fila mantiene sus celdas en sincronía. Cuenta cuidadosamente. <th> gana su lugar al decirle a un lector de pantalla que la celda es una etiqueta, algo que ninguna cantidad de negrita CSS puede hacer. Esa división semántica es la razón para usar una tabla real en primer lugar.

Estructuración de una tabla

El orden de tus filas es el orden en que las personas las leen, así que pon la fila de encabezado, la que se construye con celdas <th>, en la parte superior. Luego mantén cada fila con la misma longitud: si la fila de encabezado tiene tres celdas, cada <tr> debajo de ella necesita tres celdas <td> también. Una fila con una celda faltante deja un hueco en la cuadrícula y las columnas dejan de alinearse. No hay nada nuevo que aprender aquí, solo cuidado con las filas que ya conoces.

Una vez que una tabla crece, agrupa sus filas en grupos de filas para que la estructura sea explícita. Envuelve la fila de encabezado en <thead>, las filas de datos en <tbody>, y cualquier fila de resumen como una línea de totales en <tfoot>. Estos grupos no cambian mucho el diseño por sí solos, pero etiquetan las partes de la tabla para estilos, para impresión, y para software de asistencia.

Dale a la tabla un título con <caption>, colocado como el primer hijo de <table>. Se representa encima de la cuadrícula y, a diferencia de un encabezado que pones junto a la tabla, está ligado a la tabla en el marcado.

Cuando una celda necesita cubrir más de una columna o fila, usa colspan o rowspan. colspan="2" hace que una celda sea tan ancha como dos columnas; rowspan="2" la hace tan alta como dos filas. Las posiciones que cubre se dejan fuera de esas filas, porque ese espacio ya está ocupado:

html
<thead>
  <tr>
    <th rowspan="2">Región</th>
    <th colspan="2">2024</th>
  </tr>
  <tr>
    <th>T1</th>
    <th>T2</th>
  </tr>
</thead>

"Región" llena dos filas de encabezado, "2024" llena dos columnas, y T1 y T2 se sientan debajo en la segunda fila.

Los grupos de filas no son decoración. <thead> y <tfoot> están definidos para repetirse en cada página cuando se imprime una tabla larga, por lo que un encabezado permanece visible al cruzar un salto de página, y te permiten mantener un encabezado o pie de página fijo mientras <tbody> se desplaza. Una tabla puede contener varios grupos <tbody>, que es una forma limpia de dividir un conjunto de datos largo en secciones etiquetadas sin romper la cuadrícula única.

colspan y rowspan controlan el span de celdas (una celda que cubre más de una columna o fila), y este es el lugar donde las tablas más a menudo se rompen silenciosamente. Cada fila aún debe contabilizar el ancho completo de la cuadrícula. Una celda con colspan="2" llena dos columnas, por lo que las filas que superpone deben dejar esas posiciones vacías en lugar de proporcionar su propia celda. Cuenta mal, y el navegador aún representará algo, pero no la cuadrícula que pretendías. <caption> es el nombre accesible para la tabla: el software de asistencia (herramientas como lectores de pantalla que leen la página en voz alta) la anuncia cuando el lector llega a la tabla, haciendo el trabajo que un encabezado cercano no puede.

html
<table>
  <caption>Ingresos trimestrales por región</caption>
  <thead>
    <tr>
      <th>Región</th>
      <th>T1</th>
      <th>T2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>Norte</th>
      <td>£12.000</td>
      <td>£15.400</td>
    </tr>
    <tr>
      <th>Sur</th>
      <td>£9.800</td>
      <td>£11.200</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th>Total</th>
      <td>£21.800</td>
      <td>£26.600</td>
    </tr>
  </tfoot>
</table>
JunoEstructuración de una tabla Las filas se leen de arriba a abajo, así que comienza con tu fila de encabezado de celdas <th>. Luego mantén cada fila con la misma longitud: tres encabezados arriba significa tres celdas <td> en cada fila de abajo. Una celda faltante es un hueco en la cuadrícula, y eso es lo que desconcierta a la gente al principio.
JunoEstructuración de una tabla Agrupa las partes una vez que una tabla crece: <thead> para la fila de encabezado, <tbody> para los datos, <tfoot> para una línea de totales, y una <caption> como primer hijo para el título. colspan y rowspan estiran una celda a través de columnas o filas, pero recuerda que las posiciones cubiertas se dejan fuera de esas filas. Consigue los conteos correctos y la cuadrícula se mantiene.
JunoEstructuración de una tabla Los grupos tienen un peso real: <thead> y <tfoot> se repiten cuando se imprime la tabla y pueden anclar un cuerpo desplazable, y <caption> es el nombre que lee un lector de pantalla. El spanning es la trampa silenciosa, ya que cada fila aún tiene que llenar el ancho completo de la cuadrícula, así que una posición cubierta no obtiene celda. El navegador representa un conteo incorrecto felizmente, que es exactamente por qué es difícil de detectar.

Tablas accesibles

Una tabla accesible es una que tiene sentido para todos, incluidas las personas que escuchan la página con un lector de pantalla (software que lee la página en voz alta) en lugar de verla. Lo más útil que puedes hacer ya está en tu kit de herramientas: usa <th> para cada celda de encabezado, no <td>. Un lector de pantalla puede entonces decirle a su oyente qué celdas son etiquetas y cuáles son datos, por lo que un valor como "£15" se anuncia junto con la columna a la que pertenece. Una tabla donde cada celda es un <td> simple se lee como una pared plana de números sin nada para anclarlos.

<th> marca una celda como encabezado, pero en una tabla con encabezados de columna y encabezados de fila no dice cuál es. El atributo scope lo hace explícito. scope="col" dice que un encabezado etiqueta toda su columna; scope="row" dice que etiqueta toda su fila. Agrégalo a cada <th> y un lector de pantalla puede emparejar cualquier celda de datos con el encabezado de columna correcto y el encabezado de fila correcto a la vez.

html
<th scope="col">Mes</th>
<th scope="row">Precipitación</th>

Para una cuadrícula simple el navegador a menudo puede adivinar estas asociaciones, pero establecerlas con scope elimina las conjeturas y es barato de agregar.

scope cubre tablas con un nivel de encabezados de fila y columna. Las tablas complejas, las que tienen un encabezado que abarca varias columnas o dos niveles de encabezados de columna, permanecen ambiguas incluso con scope, porque una celda de datos ya no tiene exactamente un encabezado de columna y un encabezado de fila encima. Para esos, asocia celdas explícitamente con id y headers. Dale a cada celda de encabezado una id (un nombre único para ese elemento), luego lista las ids relevantes en el atributo headers de cada celda de datos:

html
<th id="t1">T1</th>
<th id="norte">Norte</th>
<td headers="norte t1">£12.000</td>

La celda de datos ahora nombra exactamente qué encabezados la describen, en el orden en que deben leerse, y ningún algoritmo tiene que inferir la relación. Es verboso, así que guárdalo para las tablas que realmente lo necesitan. Busca scope primero y solo escala a id y headers cuando la estructura de encabezado sea demasiado irregular para que scope la exprese.

La accesibilidad es más amplia que las tablas solas; el capítulo Accesibilidad cubre el resto del cuadro.

JunoTablas accesibles La mayor ganancia no cuesta nada extra: usa <th> para encabezados y <td> para datos. Un lector de pantalla se apoya en esa división para leer cada valor con el encabezado al que pertenece, así que £15 llega con su columna en lugar de solo. Omítelo y toda la tabla llega como una pared de números sueltos.
JunoTablas accesibles Pon scope en tus celdas de encabezado: scope="col" para un encabezado de columna, scope="row" para un encabezado de fila. Eso permite que un lector de pantalla vincule cada celda de datos con el encabezado correcto en ambos ejes. El navegador puede adivinar para cuadrículas simples, pero establecerlo es barato y elimina las conjeturas.
JunoTablas accesiblesscope maneja la cuadrícula ordinaria de un encabezado en cada vía. Cuando los encabezados se extienden o apilan y una celda tiene más de uno en un eje, cambia a id en los encabezados y headers en las celdas de datos para conectarlos a mano. Es verboso, así que guárdalo para las tablas que realmente lo necesitan y deja que scope lleve el resto.

Las tablas son para datos, no para diseño

Hubo un tiempo, antes de que CSS pudiera manejar el diseño, cuando la gente construía diseños de página completos con tablas: una <table> para poner el menú a la izquierda y el contenido a la derecha. Funciona visualmente, así que aún lo ves en páginas antiguas y algunas plantillas de correo. No lo copies. Una tabla es para datos tabulares, información que pertenece a una cuadrícula de filas y columnas. Organizar las piezas de una página es trabajo de CSS. Usar una tabla para posicionar cosas en lugar de para contener datos hace que la página sea más difícil de leer para cualquiera que use un lector de pantalla, y más difícil de ajustar después.

La regla es simple: una <table> significa "este contenido es una cuadrícula de datos relacionados". Úsala cuando la información realmente tiene filas y columnas: un horario, una comparación, un conjunto de resultados. No la uses para diseñar una página, y no la uses para alinear cosas que no son datos. CSS grid y flexbox hacen el diseño correctamente, se adaptan al tamaño de la pantalla, y mantienen tu HTML describiendo contenido en lugar de describir una disposición.

Buscar una tabla para obtener columnas es el mal uso clásico. Si el contenido es una barra de navegación o un formulario extendido por la página, no son datos tabulares, y una tabla es la herramienta incorrecta incluso aunque pueda parecer correcta.

Cuando usas una tabla para el diseño, le entregas a software de asistencia (herramientas como lectores de pantalla que hablan la página) una estructura de datos que no es datos. Un lector de pantalla anuncia una tabla por sus dimensiones y permite al usuario moverse celda por celda, tratando el andamiaje de diseño como si cada región fuera un valor relacionado en una cuadrícula. El resultado son anuncios como "tabla, cuatro columnas, diez filas" para lo que realmente es un encabezado, una barra lateral, y un artículo.

También hay un problema de orden de lectura. El software de asistencia y los motores de búsqueda leen la página en orden de código fuente, el orden en que aparecen los elementos en tu HTML, no el orden en que suceden estar en pantalla. Una tabla de diseño obliga tu orden de código fuente a coincidir con la cuadrícula visual, así que el contenido que debería venir primero para un oyente, el artículo principal, puede terminar después de una columna de navegación porque eso es donde la columna visual lo necesitaba. El diseño CSS rompe ese acoplamiento: puedes mantener el contenido importante temprano en el código fuente y aún colocarlo en cualquier lugar de la pantalla. Mantén las tablas para datos, y el orden de lectura sigue siendo tuyo para controlar.

La única área gris es el correo HTML, donde los clientes de correo más antiguos aún carecen de un diseño CSS confiable y la estructura basada en tablas sigue siendo común. Esa es una limitación de ese medio, no un patrón que traer de vuelta a la web.

html
<!-- Incorrecto: una tabla usada para poner una barra lateral junto a un artículo -->
<table>
  <tr>
    <td><nav>...</nav></td>
    <td><article>...</article></td>
  </tr>
</table>

<!-- Correcto: elementos reales, con CSS manejando las columnas -->
<nav>...</nav>
<article>...</article>

Esta es la misma separación de estructura y presentación establecida en Qué es HTML: estructura en HTML, diseño en CSS. Para elegir elementos por su significado, ver HTML Semántico.

JunoLas tablas son para datos, no para diseño Una tabla es para datos que pertenecen a una cuadrícula, filas y columnas de valores relacionados. No es para organizar una página, aunque sitios antiguos la usaran así. Posicionar las partes de una página es trabajo de CSS, y doblar eso en una tabla hace que la página sea más difícil de leer en voz alta y más difícil de cambiar.
JunoLas tablas son para datos, no para diseño Usa <table> solo cuando el contenido realmente sea una cuadrícula de datos: un horario, una comparación, una lista de resultados. Para diseñar una página o alinear no-datos, busca CSS grid o flexbox, que se adapten a la pantalla y mantengan tu HTML sobre contenido. Una tabla forzada en trabajo de diseño es la herramienta clásica incorrecta.
JunoLas tablas son para datos, no para diseño Una tabla de diseño engaña a un lector de pantalla: escucha una cuadrícula de datos y lee filas y columnas que no significan nada. También fija tu orden de código fuente a la cuadrícula visual, cuando el orden de código fuente es lo que la tecnología de asistencia y los motores de búsqueda realmente leen. Mantén las tablas para datos, deja que CSS coloque cosas, y el orden de lectura sigue siendo bajo tu control. El correo HTML es la única excepción, y solo porque sus clientes están atrapados en el pasado.