4 puntos por GN⁺ 2024-02-25 | 1 comentarios | Compartir por WhatsApp
  • En las tablas con muchas filas, a medida que se hace scroll es fácil olvidar qué significa cada columna, lo que dificulta leer los datos
  • Basta con agregar position: sticky; y top: 0; a thead para implementar un encabezado fijo
  • sticky tiene alrededor de 96% de compatibilidad en navegadores a nivel mundial, así que no es una función experimental
  • Incluso al ver filas más abajo, como el elemento número 300, los títulos de las columnas permanecen visibles, lo que mejora la experiencia de exploración de la tabla
  • La implementación es pequeña pero el efecto es grande, por lo que vale la pena aplicarla como una mejora básica de usabilidad en páginas web que ofrecen tablas largas

El problema de que el encabezado desaparezca en tablas largas

  • En conjuntos de datos grandes o tablas de cientos de filas, después de hacer scroll el encabezado de la tabla desaparece fuera de la pantalla
  • Si bajas hasta el elemento número 300, puede ser difícil volver a verificar qué significa el dato de cada columna
  • Cuanto menos familiar sea la tabla, mayor será la carga de exploración, porque hay que leer recordando el significado de las columnas

Aplicar sticky a thead

  • La solución es agregar dos propiedades CSS a thead
position: sticky;
top: 0;
  • Al usar position: sticky junto con top: 0, el encabezado puede quedar fijo en la parte superior de la pantalla mientras se hace scroll
  • sticky cuenta con alrededor de 96% de compatibilidad global, por lo que puede usarse en muchos navegadores
  • Puedes comprobar el funcionamiento real en el ejemplo de CodePen

1 comentarios

 
GN⁺ 2024-02-25
Opiniones en Hacker News
  • Puedo aceptar un encabezado fijo en un eje, pero sigo esperando el día en que CSS lo soporte en ambos ejes: https://github.com/w3c/csswg-drafts/issues/8286

    • Uno de los trabajos por contrato más difíciles que tuve fue uno en el que había que fijar tanto columnas como encabezados. Con una tabla estándar habría sido fácil, pero esto era una tabla dinámica de terceros en VueJS compleja que usaba CSS-as-JS generado, así que me tomó mucho tiempo solo entender de dónde venían el CSS y el JS, y al final tuve que sobrescribir funciones de clases JS y CSS generado. Me dio pena con el cliente por tardarme tanto, y me volvió mucho más cuidadoso al elegir librerías en codebases de Vue/React. Las tablas son elementos básicos de HTML; no entiendo por qué para una tarea sencilla hacen falta tres capas de clases JS y hasta CSS importado como JSON.
    • Probablemente llevo 8 años siguiendo el issue original que dio origen a este, y es una de las partes más irritantes de la especificación de CSS. A veces necesitas una tabla de datos enorme, y quieres que la parte superior quede fija mientras también usas overflow-x: auto, pero te obligan a elegir solo una de las dos cosas.
  • Confieso que sé muy poco de CSS, pero igual hago aplicaciones web que funcionan más o menos. Hace poco intenté fijar el encabezado en una tabla monstruosa de unas 20 mil filas: https://www.datasciencemeta.com/rpackages Al principio esperaba que las clases de tablas de Bootstrap tuvieran algo como class="table table-header-sticky", pero no existía, y después de unos 20 minutos probando sugerencias de Stack Overflow, GPT y CodePen aparecían efectos secundarios raros. En cambio, con el CodePen de este artículo lo tuve funcionando en 2 minutos, y ahora lo estoy desplegando en producción.

  • Fijar encabezados de tabla parece fácil con solo position: sticky;, pero en cuanto empiezas a agregar cosas al contenido de la tabla se complica de inmediato. En una tabla con encabezado fijo agregué una función que, cuando el usuario hacía scroll en el cuerpo y salía de la página, guardaba el índice de la primera fila visible y lo restauraba al volver, pero siempre se restauraba más o menos una fila abajo. Resultó que la fila 5 sí estaba realmente en la parte superior de la tabla, pero el thead se superponía, haciendo que la fila 6 pareciera la primera. Así que ajusté la posición de scroll tomando en cuenta la altura del thead, pero a veces se desfasaba por unos píxeles; como era una tabla grande, hacía carga diferida en el evento de scroll y usaba el layout automático de tablas por defecto, lo que hacía que las celdas del encabezado hicieran salto de línea y cambiara la altura total del encabezado. Al final puse un ResizeObserver en el thead para ajustar dinámicamente la posición de scroll cuando cambiara su altura. [1] https://developer.mozilla.org/en-US/docs/Web/API/ResizeObser...

  • Al implementar esto, si quieres que también se fijen los bordes del encabezado, puedes hacerlo con position: absolute, width: 100%, top: 0/bottom: 0 y border-top/border-bottom en table thead:before y table thead:after.

  • Ojalá los encabezados de tabla funcionaran así automáticamente. Si un desarrollador se tomó la molestia de usar las etiquetas relacionadas, normalmente es bastante probable que este sea el comportamiento que ya quería.

    • Puedes instalar un plugin de navegador que cargue hojas de estilo personalizadas en todas las páginas. Aunque últimamente cada vez más sitios construyen tablas con 500 en lugar de, y con 45 niveles de anidados dentro de cada, así que supongo que ahí no funcionaría.
    • Un cambio así parece muy propenso a romper cosas de formas inesperadas. La razón principal probablemente sea que, antes de CSS Grid, muchos sitios web usaban tablas para layouts en cuadrícula. Si los encabezados se vuelven fijos, esos layouts podrían romperse. El gran fracaso de la semántica de HTML fue que las tablas se entendieron no como “una forma de mostrar datos tabulares”, sino como “una cuadrícula de elementos arbitrarios”.
  • En la línea de comandos, basta con mandar el encabezado a stderr y el cuerpo a stdout. Si no lo haces, el resultado de heights | sort -k2 -nr queda en el orden George 186, Wally 173, NAME HEIGHT, pero si el encabezado evita stdout, queda en el orden NAME HEIGHT, George 186, Wally 173.

    • heights | (sed -u 1q; sort -k2 -nr) funciona correctamente. Fuente: https://stackoverflow.com/a/56151840
    • Si vas a escribir a un archivo, necesitas intentarlo unas cuantas veces más y también tener más conocimiento del shell. Esta es una limitación persistente del modelo basado solo en texto in-band, pero abusar de STDERR de esta forma parece que confundiría más de lo que ayudaría. Si heights es un archivo, puedes hacer algo como % head -1 heights ; sed 1,1d heights | sort -k2 -nr, y si heights es un ejecutable caro de correr dos veces, puedes hacer algo como % heights > /tmp/heights ; head -1 /tmp/heights ; sed 1,1d /tmp/heights | sort -k2 -nr. También puedes pasarlo por awk. Las otras opciones son menos cómodas, pero menos sorpresivas, y funcionan aunque el autor del ejecutable tenga otra idea.
    • ¿Qué sería mejor aquí? ¿Mandar el encabezado a stderr, o imprimir el encabezado solo cuando stdout sea una TTY?
  • Esto no funcionó durante mucho tiempo. Chrome antes tenía desactivado position: sticky en elementos thead y tr: https://issues.chromium.org/issues/41303743 Recuerdo que las tablas de soporte de navegadores se veían casi todas en verde, pero justamente en tablas de Chrome no funcionaba.

    • Me sorprende que ahora sea tan simple. Cuando lo necesité antes, para que funcionara en todos los navegadores había que meter todo tipo de porquerías en el HTML y el CSS. Aunque tampoco me sorprendía, porque el desarrollo web suele ser así.
  • Hay una parte de mí que preferiría decir “por favor, no lo hagan”: https://news.ycombinator.com/item?id=32998091

    • En páginas web normales, estoy totalmente de acuerdo. Muchas veces elimino elementos fijos con uBlock Origin porque es más rápido que escribir un estilo en Stylus, y también me han funcionado bastante bien algunos estilos genéricos aplicados a todo el sitio. Pero el artículo original habla de una tabla de datos con una columna de encabezados fija, así que esta propuesta sí es bastante útil.
    • Eso habla de encabezados fijos de toda una página web. En una tabla es algo completamente distinto. Odio cuando estás viendo una tabla con unas doce columnas numéricas y, apenas haces un poco de scroll hacia abajo, ya no sabes qué es qué.
    • ¿Qué tiene de malo la propiedad sticky?
  • El CodePen se ve mejor si desplazas top por el ancho del borde. Por ejemplo, poner -1px en lugar de 0 evita que el cuerpo de la tabla se vea por encima del encabezado. Comparación: https://codepen.io/bradleytaunt/pen/bGZyJBj Versión corregida: https://codepen.io/alokmenghrajani/pen/ExMBQow

  • Propongo usar una altura de viewport limitada en lugar de un encabezado fijo, para que el encabezado siempre esté visible. Algo como DataGridXL(https://datagridxl.com). Para que conste, lo hice yo.

    • Solo se me ocurre que este enfoque es muy difícil de navegar sin un dispositivo apuntador, por ejemplo usando solo el teclado.
    • No es por criticar, pero en móvil nunca me ha gustado este enfoque. Creo que el contenido debería desplazarse junto con la página.