8 reglasW3C WAI Tables Tutorial · WCAG 2.1 SC 1.3.1 Info and Relationships (Nivel A)Pencil & Paper "UX Pattern Analysis: Enterprise Data Tables" · Sebastian De Deyne "Tabular Numbers" · Design with Figma "Designing Data Tables"Jessica Enders / A List Apart "Zebra Striping: Does it Really Help?" (244 participantes; sin mejora estadísticamente significativa en tablas simples) · Pencil & Paper Enterprise Data Tables · Adrian RoselliStanford UIT "Sticky Table Headers" · CSS-Tricks "A Table with a Sticky Header and First Column" · WCAG 2.1.1 Keyboard
75
Tables (web)
8 reglas
648
HTML semántico de tabla: thead, th scope y caption, nunca divs
Las tablas de datos deben construirse con los elementos nativos: <table>, <thead>, <tbody>, <th>, <td> y <caption>. El atributo scope en cada <th> declara si el encabezado aplica a una columna (col) o a una fila (row), permitiendo que el lector de pantalla anuncie el contexto correcto al navegar celda por celda. El <caption> identifica el tema de la tabla y es útil en casi cualquier situación. Una rejilla de <div> con apariencia de tabla pierde por completo la relación programática entre encabezados y datos, lo que viola WCAG 1.3.1 (Info and Relationships) y deja la tabla inutilizable para tecnología asistiva.
W3C WAI Tables Tutorial · WCAG 2.1 SC 1.3.1 Info and Relationships (Nivel A)
Preferir
Ventas por región, Q2 2026
Región
Estado
Norte
Activa
Sur
En revisión
Bajío
Activa
Evitar
Región
Estado
Norte
Activa
Sur
En revisión
Sin th, sin scope, sin caption, WCAG 1.3.1 falla
649
Alinea por tipo de dato: texto a la izquierda, números a la derecha con tabular-nums
Cada columna se alinea según la naturaleza de su contenido. El texto y los identificadores (nombres, fechas, códigos, teléfonos) van a la izquierda, porque el ojo occidental está habituado a leer desde ese borde. Las cantidades y porcentajes comparables van a la derecha para que el dígito de mayor peso quede alineado entre filas y la magnitud se compare de un vistazo. El encabezado sigue la alineación de su columna. Además, las columnas numéricas requieren font-variant-numeric: tabular-nums para que cada dígito ocupe el mismo ancho: sin él, una cifra proporcional desplaza los decimales al actualizar y rompe la rejilla vertical de la comparación.
Pencil & Paper "UX Pattern Analysis: Enterprise Data Tables" · Sebastian De Deyne "Tabular Numbers" · Design with Figma "Designing Data Tables"
Preferir
Producto
Importe
Suscripción Pro
$1,249.00
Almacenamiento
$89.50
Soporte 24/7
$2,400.00
Dominio
$12.99
Evitar
Producto
Importe
Suscripción Pro
$1,249.00
Almacenamiento
$89.50
Soporte 24/7
$2,400.00
Dominio
$12.99
650
Separadores según densidad: líneas por defecto, zebra en datasets largos, no apiles estados
No existe un separador universalmente óptimo: la elección responde al tamaño del dataset y al número de estados interactivos. Las líneas horizontales de 1px gris claro son el patrón más versátil y funcionan para cualquier tamaño. El zebra striping aporta a lo sumo una mejora marginal de precisión en datasets muy largos, pero introduce ruido cuando la tabla ya tiene varios estados (hover, seleccionado, deshabilitado): apilar zebra sobre tres estados semánticos crea hasta cinco fondos en conflicto y rompe la continuidad visual. Sin separador solo en datasets pequeños donde el espaciado tipográfico ya orienta la lectura. Importante: cambiar display en filas o celdas para lograr el efecto rompe la semántica de tabla en la mayoría de navegadores; el zebra debe lograrse con background, nunca con cambios de display.
Jessica Enders / A List Apart "Zebra Striping: Does it Really Help?" (244 participantes; sin mejora estadísticamente significativa en tablas simples) · Pencil & Paper Enterprise Data Tables · Adrian Roselli
Preferir
Cliente
Plan
MRR
Acme Corp
Enterprise
$4,200
Globex
Pro
$890
Initech
Pro
$890
Umbrella
Enterprise
$3,750
Soylent
Starter
$120
Hooli
Enterprise
$5,100
Un único fondo alterno (~4% de tinta). Sin hover ni selección compitiendo: la zebra solo organiza la lectura.
Evitar
Cliente
Plan
MRR
Acme Corp
Enterprise
$4,200
Globex
Pro
$890
Initech
Pro
$890
Umbrella
Enterprise
$3,750
Soylent
Starter
$120
Hooli
Enterprise
$5,100
Cinco fondos distintos: zebra par + seleccionado + hover + deshabilitado + base. ¿Cuál fila está activa?
651
Fija el thead con position:sticky al hacer scroll; tabindex="0" en el contenedor
En tablas que superan la altura del viewport, el encabezado debe permanecer visible durante el scroll vertical para que el usuario nunca pierda el contexto de cada columna. El patrón accesible coloca position: sticky; top: 0 en los thead th dentro de un contenedor con overflow-y: auto y altura fija. Es obligatorio añadir tabindex="0" al contenedor para que usuarios de teclado puedan recorrer el área scrollable, con un indicador de foco visible. El antipatrón a evitar es partir el contenido en dos tablas separadas (una para el header fijo, otra para el body con scroll): eso rompe el enlace programático entre encabezado y datos y deja la tabla inservible para lectores de pantalla.
Stanford UIT "Sticky Table Headers" · CSS-Tricks "A Table with a Sticky Header and First Column" · WCAG 2.1.1 Keyboard
Preferir
Haz scroll: el encabezado permanece fijo arriba
Transacciones recientes
Fecha
Concepto
Monto
01 jun
Nómina
$48,200
03 jun
Proveedor AWS
$3,410
05 jun
Reembolso
$120
08 jun
Suscripción Figma
$540
11 jun
Cliente Acme
$12,000
14 jun
Renta oficina
$9,800
17 jun
Proveedor AWS
$3,410
20 jun
Cliente Globex
$6,750
22 jun
Marketing Ads
$2,200
25 jun
Cliente Hooli
$15,300
28 jun
Nómina
$48,200
30 jun
Impuestos
$21,400
652
Orden activo con aria-sort en el th, button para la acción, indicador no solo por color
Las columnas ordenables usan un <button> dentro del <th> para que la acción sea activable por teclado, y el <th> lleva aria-sort con el valor activo (ascending, descending o none). Solo un encabezado puede tener aria-sort distinto de none al mismo tiempo; tener dos columnas marcadas como ordenadas confunde a la tecnología asistiva. El indicador visual (flecha o chevron) debe cambiar de forma o relleno, no solo de color: una flecha que pasa de contorno hueco a triángulo relleno comunica el orden a usuarios con daltonismo, cumpliendo WCAG 1.4.1 (Use of Color). Una columna ordenada sin señal programática falla WCAG 4.1.2 (Name, Role, Value).
MDN / WAI-ARIA aria-sort · Adrian Roselli "Sortable Table Columns" · WCAG 1.4.1 Use of Color · WCAG 4.1.2 Name, Role, Value
Preferir
Hooli
$5,100
Acme Corp
$4,200
Umbrella
$3,750
Globex
$890
Evitar
Cliente
MRR
Hooli
$5,100
Acme Corp
$4,200
Umbrella
$3,750
Globex
$890
Sin aria-sort, sin button, orden señalado solo por color
653
Densidad de fila según contexto: compact 32, medium 40, default 48, tall 64px
La altura de fila y el padding determinan cuántos datos caben en pantalla y qué tan cómoda es la lectura. El sistema de IBM Carbon define una escala de densidades confirmada: compact 32px, medium 40px, default 48px y tall 64px (más un nivel condensed de 24px para datos extremos). Compact y medium sirven a herramientas internas con mucha información; default es el uso general; tall facilita lecturas prolongadas o audiencias no técnicas. El padding horizontal mínimo es de 16px por lado, de modo que el espacio entre columnas sume al menos 32px y las celdas nunca se toquen. Ofrecer un selector de densidad y persistir la elección del usuario es práctica recomendada en herramientas enterprise.
IBM Carbon Design System "Data Table" (row heights 24/32/40/48/64px) · Design with Figma "Designing Data Tables" · Pencil & Paper Enterprise Data Tables
Preferir
Compact 32px
SKU
Stock
Precio
BX-104
Disponible
$24.00
BX-219
Bajo
$18.50
Medium 40px
SKU
Stock
Precio
BX-104
Disponible
$24.00
BX-219
Bajo
$18.50
Default 48px
SKU
Stock
Precio
BX-104
Disponible
$24.00
BX-219
Bajo
$18.50
Tall 64px
SKU
Stock
Precio
BX-104
Disponible
$24.00
BX-219
Bajo
$18.50
Evitar
SKU
Stock
Precio
BX-104
Disponible
$24.00
BX-219
Bajo
$18.50
BX-330
Agotado
$31.20
BX-401
Disponible
$9.90
24px de alto, 4px de padding: texto y borde casi se tocan
654
Responsive: scroll horizontal con role="region" y primera columna sticky, nunca display:block
En viewports estrechos la estrategia preferida es el scroll horizontal, porque mantiene intacta la semántica de tabla. Se envuelve la <table> en un <div role="region" aria-labelledby="..." tabindex="0"> para que el área scrollable sea anunciada y navegable por teclado, y la primera columna (el identificador) se fija con position: sticky; left: 0 con el background aplicado a nivel de celda. El antipatrón crítico es cambiar el display de la tabla o de las celdas a block o flex para apilarlas: en cuanto se hace eso, la mayoría de los lectores de pantalla dejan de tratarlo como tabla y se pierde toda la asociación encabezado-dato. Si se colapsa a tarjetas, hay que reponer las etiquetas con td::before { content: attr(data-label) }.
Adrian Roselli "A Responsive Accessible Table" · CSS-Tricks "Sticky Header and First Column" · WCAG 1.3.1 Info and Relationships
Preferir
Desliza horizontal: la columna "Cliente" queda fija
Pipeline de cuentas
Cliente
Industria
Etapa
Owner
Valor
Acme Corp
Manufactura
Negociación
L. Ortiz
$48,000
Globex
Logística
Propuesta
M. Díaz
$22,500
Initech
Software
Cierre
R. Páez
$31,000
Umbrella
Salud
Descubrimiento
L. Ortiz
$67,200
Evitar
ClienteAcme Corp
IndustriaManufactura
EtapaNegociación
Valor$48,000
table { display:block }, ya no es una tabla para NVDA ni VoiceOver
655
Celdas con múltiples encabezados: id + headers; scope rowgroup/colgroup en agrupaciones
Cuando una celda de datos se relaciona con más de un encabezado (encabezados de fila y de columna que se cruzan, o subgrupos con un segundo nivel), el atributo scope bidireccional no basta. En ese caso cada <th> recibe un id único y cada <td> lista los ids de todos sus encabezados en headers="id1 id2 id3", separados por espacios. Para tablas con subgrupos de filas o columnas, los encabezados de grupo usan scope="rowgroup" o scope="colgroup". La recomendación de la W3C es que, si la tabla es genuinamente compleja, conviene a todos dividirla en tablas simples separadas con un encabezado descriptivo: es más fácil de entender y de codificar. Sin id+headers en tablas multinivel, la relación encabezado-celda no es determinable programáticamente y WCAG 1.3.1 falla.
W3C WAI Tables Tutorial, Multi-level Headers · W3C WAI Two Headers · WCAG 2.1 SC 1.3.1 Info and Relationships
Preferir
Ventas por región y trimestre
Q1
Q2
Región Norte
Monterrey
$120k
$138k
Saltillo
$74k
$81k
Región Sur
Mérida
$96k
$102k
headers="r1135-norte r1135-mty r1135-q1"
region · ciudad · trimestre, los tres ejes asociados
Evitar
Q1
Q2
Región Norte
Monterrey
$120k
$138k
Saltillo
$74k
$81k
Región Sur
Mérida
$96k
$102k
Sin scope="rowgroup", sin id/headers, WCAG 1.3.1 falla