Tables & Responsive Times: scroll en Tbody y Thead fixed puro Css 20.10.14
Tabla reponsive con encabezado fijo y scroll al cuerpo (tbody) sin necesidad de añadir elementos extras en el marcado Html o de tener que descomponer la tabla. Sólo con Css
Tables & Responsive Times: scroll en Tbody y Thead fixed puro Css
Hace ya un tiempo publiqué un artículo recopilatorio de técnicas para hacer nuestras tablas con el encabezado Thead
fijo y el cuerpo Tbody
con scroll o desplazamiento en caso de superar cierto número de filas: tablas con scroll y encabezado fijo en puro Css
Métodos que requieren de ajustes complejos y finos para adaptarlos a las necesidades de cada caso. Adaptaciones que a muchos usuarios hacen desistir de lograrlo.
A la vez, estos últimos días me han llegado algunas consultas relativas a cómo hacer responsive tables
. Esto es, que además de adaptarse al viewport se mantengan visibles los valores del encabezado thead
de la tabla en tamaños pequeños para saber qué es cada dato.
Esto último, responsive table
, es el tema que desarrolla en octuweb.com Martín Iglesias en su artículo. Y fue este post el que me hizo recordar que tenía pendiente la resolución de lo primero (encabezado fijo con scroll al tbody) para evitar tablas con altura infinita y ya puestos introducir lo segundo: RWD.

Consideraciones de base
El elemento table
y sus hijos,
- encabezados
- filas y grupos de filas
- columnas y grupos de columnas
- celdas
tienen asociado por defecto valores específicos para la propiedad display
. Y dichos valores llevan aparejadas una serie de particularidades que los dotan de su comportamiento característico.
- table
- inline-table
- table-row-group
- table-column
- table-column-group
- table-header-group
- table-footer-group
- table-row
- table-cell
- table-caption
Encabezado fijo y scroll al cuerpo
Por el mismo motivo, el algoritmo usado para su composición hace que una serie de propiedades y/o valores css no surtan efecto en ellos. O que no sea el deseado al esperar que fuese el mismo que en otros elementos.
Por lo tanto, para lograr lo primero (encabezado fijo y cuerpo con scroll) hay que cambiar el valor asociado al display
del Tbody
y sus filas.
Al hacerlo así no es necesario ni descomponer la tabla ni añadir otros elementos.

Mi primera aproximación fue usar el modelo de caja del flexbox
. Pero me encontré con cierto bug en Firefox. A la espera de poder dedicarle una segunda mirada terminé por replantearlo y recurrir a otras más "tradicionales".
tbody { display: block; height: 40vh; min-height: 200px; overflow-Y: scroll; } tr { display: block; overflow: hidden; }
La parte "responsive"
Por tabla responsive
se suele entender aquella que al llegar a un tamaño tal del viewport pasa de mostrar el encabezado y debajo todas las celdas en una misma fila a colocar una celda por fila y a su lado indicar de alguna manera el tipo de valor que es (su valor en el th) ocultando el Thead
.
Las dos acciones, como es lógico, deben ir en su @media query
correspondiente. El valor de la misma dependerá de las particularidades de cada tabla y el punto de ruptura.
Nota del Editor: Tanto este pen como el siguiente que se incluyen en el artículo están en un elemento con la declaración
resize:horizontal;
. Sim embargo en Chrome no podrás hacer uso de ello ya que no permite redimensionar al elemento a un tamaño menor.
Lo primero, una celda por fila, es relativamente sencillo. Sólo es cuestión de cambiar, una vez más, el valor de su display: table-cell
por otro que evite que nada más se posicione en su misma línea: block
.
La segunda parte, mostrar junto a cada celda el tipo de dato que es se puede lograr de dos formas. Todo depende de cómo se genere la tabla.
- Tabla generada por programación
Si la tabla va a ser generada a demanda mediante algún lenguaje de programación y de caso a caso variará, todo se reduce a añadir un atributo de autor a todas y cada una de las celdastd
, en mi demodata-campo
y cuyo valor coincida con el asignado en el thead. - Tabla "manual", escrita "a mano"
En este caso, y para evitar lo tedioso y propenso a errores que resultaría repetir para cadatd
dicho atributo de autor con su valor correspondiente se lo encomendamos a Css.
En el primer caso del marcado html generado por programación sería algo como el siguiente código:
<tr>
<td data-campo='Nick'>Fulano</td>
<td data-campo='Mail'>Fulano@gmail.com</td>
<td data-campo='Web'>fulano.es</td>
<td data-campo='Twitter'>@Fulano</td>
<td data-campo='Id'>1</td>
</tr>
Y para mostrarlo sólo se necesita de una regla Css:
td:before { content: attr(data-campo); /* resto de declaraciones */ }
En el segundo caso, evitar tener que añadir a mano el valor del falso Thead, le encomendamos a Css todo, generación y presentación:
td:nth-child(1):before {content: 'Nick';} td:nth-child(2):before {content: 'Mail';} td:nth-child(3):before {content: 'Web';} td:nth-child(4):before {content: 'Twitter';} td:nth-child(5):before {content: 'Id';} /* regla con las declaraciones comunes */
Sin demo... dragones en el garaje
Todo lo anterior, y un poco más de estilos por aquello de adornarlo algo, en especial contemplar el caso de necesitar que cada encabezado th
necesite de distintas anchuras lo puedes ver en el siguiente pen. Juega con la anchura y altura de la ventana para ver las transformaciones que conllevan.
Disclaimer

De los navegadores actuales, sólo he podido probar su correcto funcionamiento en Firefox y Chrome en su última versión estable.
Así que si pruebas y notas alguna cosilla que no acabe de funcionar, abajo, en los comentarios, puedes comentarla. Y si aportas alguna solución, mejor que mejor.
Alpiste para el ego: esta demo fue mostrada en portada de Codepen.io (picks) :-))
También en la misma página de la demo me avisan de un bug en IE9 y menores en un comentario.
Bug en IE9 y menores. Fixed
ACTUALIZACIÓN y BUG FIXED

Por diversos medios me comentan que en IE9 y menores presenta un malfuncionamiento la demo: los td presentan una altura desorbitada que la hacen inutilizable.
Ahora que lo he podido ver, creo que el problema estriba en que tanto las filas como celdas heredan la altura declarada en tbody
.
Así que identificado el origen, la solución es sencilla: hacer que en esos navegadores antiguos no existan dichas alturas:
table * {height: auto; min-height: none;} tbody { height: calc(50vh - 1px); min-height: calc(200px + 1 px); /*resto declaraciones*/ }
En los IE9 y menores no tenemos scroll en el tbody pero la tabla ahora ya es usable. Actualización incluida en la demo.
Más sobre tablas y diseño "responsive"
Con el paso del del tiempo en el blog han ido apareciendo una serie de artículos dedicados a las tablas y diversos aspectos de ellas.
Algunos son demos puro CSS más o menos "extremas" pero usables y otros, obra de Furoya, dedicados a su manejo y tratamiento javascript mediante. Estos son algunos de ellos:
- Tablas Css. Display: table y asociadas. Su oportunidad en el responsive design
- Layouts Css. Pasado, presente y futuro
- Tablas con encabezado fijo de filas, 1ª columna fija y desplazamiento por datos
- Permutar el orden de elementos con display: table y asociadas
- Javascript con Furoya: filtrar filas por palabra clave contenida en sus celdas
- From table to tabs pure Css

Kseso
the obCSServer ᛯ Ramajero Argonauta, Enredique Amanuense de CSS.#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Kseso
¿Cómo podría hacer lo mismo pero dejando fija la primera columna por las izquierda? Gracias.
ResponderEliminarPosíblemente, Mario
EliminarPero sin más información...
Quizás si hubieses sido un poco más generoso en tu exposición con una demo de tu tabla (i.e. en codepen).
Lo digo porque no alcanzo a comprender qué sentido tendría mantener fija una columna de la tabla ya que se supone que aunque sus valores cambien su naturaleza (y ordenamiento) es la misma en todas.
Un saludo
Yo necesito hacer lo mismo que quiere Mario ya que tengo una tabla con muchas columnas entonces quiero dejar la columna que posee el ID del registro fija. Agredecere su ayuda.
EliminarNo es CSS, pero quizá esto te sirva.
EliminarTablas con encabezado fijo de filas, 1ª columna fija y desplazamiento por datos.
Hola Carlos
EliminarTe comento lo mismo que a Mario. Ya lo siento, pero sin una demo con tu planteamiento y explicación detallada sólo caben suposiciones y jugar a las adivinanzas.
Lo único que se me ocurre es que juegues con table-caption y los modos de escritura CSS (writing-mode).
Un saludo