Encabezados de columnas de tabla rotadas… ¡ahora con menos números mágicos!
Los encabezados de columna rotados table
es algo que se ha cubierto antes aquí en CSS-Tricks, así que agradezco que me ayude a comenzar ya lograr este efecto. Como señala el artículo, si no utiliza la trigonometría para calcular los estilos de sus tablas, tendrá que confiar en números mágicos y su tabla será frágil y cualquier sueño de capacidad de respuesta será destruido.
Afortunadamente, en este caso, podemos eliminar la trigonometría y reemplazarla con una geometría cuidadosa y todos nuestros números mágicos se convertirán en 0 (un número verdaderamente mágico).
Para aquellos que tienen prisa, aquí está el CSS (es muy similar a los estilos del otro artículo). A continuación se muestra un recorrido completo.
thdivspanColumn Header 1/span/div/th
table { border-collapse: collapse; --table-border-width: 1px;}th.rotate { white-space: nowrap; position: relative;
}th.rotate div { /* place div at bottom left of the th parent */ position: absolute; bottom: 0; left: 0; /* Make sure short labels still meet the corner of the parent otherwise you'll get a gap */ text-align: left; /* Move the top left corner of the span's bottom-border to line up with the top left corner of the td's border-right border so that the border corners are matched * Rotate 315 (-45) degrees about matched border corners */ transform: translate(calc(100% - var(--table-border-width) / 2), var(--table-border-width)) rotate(315deg); transform-origin: 0% calc(100% - var(--table-border-width)); width: 100%;
}th.rotate div span { /* make sure the bottom of the span is matched up with the bottom of the parent div */ position: absolute; bottom: 0; left: 0; border-bottom: var(--table-border-width) solid gray;}td { border-right: var(--table-border-width) solid gray; /* make sure this is at least as wide as sqrt(2) * height of the tallest letter in your font or the headers will overlap each other*/ min-width: 30px; padding-top: 2px; padding-left: 5px; text-align: right;}
Analizamos esta tabla y vemos qué está pasando. La magia comienza con esa divertida cadena de etiquetas HTML. Estamos poniendo un span
interior de un div
interior de nuestro th
. ¿Es todo esto realmente necesario? Entre cómo se comportan los bordes, la flexibilidad de posicionamiento que necesitamos y lo que determina el ancho de una columna de la tabla… sí, cada uno tiene un propósito y es necesario.
Veamos qué pasa si rotamos th
directamente:
thColumn header 1/th
table { border-collapse: collapse;}th.rotate { border-bottom: 1px solid gray; transform: rotate(315deg); white-space: nowrap;}td { border-right: 1px solid gray; min-width: 30px; padding-top: 2px; padding-left: 5px; text-align: right;}
Ignorando el hecho de que no hemos corregido la posición, aquí hay dos grandes problemas:
- El ancho de la columna todavía se calcula a partir de la longitud del encabezado, que es lo que intentábamos evitar.
- Nuestra frontera no vino con nosotros en la rotación, porque en realidad forma parte de la mesa.
Estos problemas no son tan difíciles de solucionar. Sabemos que si th
tiene un elemento secundario con un borde, el navegador no tratará ese borde como parte de la tabla. Además, sabemos que los elementos en posición absoluta se eliminan del flujo del documento y no afectarán el ancho del documento principal. Ingrese div
la etiqueta, escenario hacia la izquierda… y hacia la derecha, supongo.
thdivColumn header 1/div/th
table { border-collapse: collapse;}th.rotate { white-space: nowrap; position: relative;}th.rotate div { position: absolute; transform: rotate(315deg); border-bottom: 1px solid gray;}td { border-right: 1px solid gray; min-width: 30px; text-align: right; padding-top: 2px; padding-left: 5px;}
Es más fácil distinguirlo en la imagen con los th
elementos rotados, pero esa rotación ocurre alrededor del centro del elemento (ese es el comportamiento predeterminado de transform-origin). Es sólo otra transformación en xey para llevar al lugar correcto, pero aquí es donde necesitaríamos trigonometría para determinar cuánto xey hay que alinearlo con los bordes de la columna. Si, en cambio, elegimos cuidadosamente el punto sobre el que rotar el encabezado y usamos transform-origin para seleccionarlo, entonces podemos terminar con distancias que son más sencillas que los números mágicos.
La siguiente animación ayuda a ilustrar lo que vamos a hacer para evitar matemáticas complicadas. El punto negro en la parte superior izquierda del borde azul debe coincidir con el punto rojo en el borde derecho de la columna de la tabla y girar sobre él. Entonces no habrá brechas entre las dos fronteras.
No sirve de nada empezar a ir a algún lugar si no sabes dónde estás. El posicionamiento absoluto nos ayudará con esto. Al especificarlo bottom: 0; left: 0;
, div
termina en la parte inferior izquierda del padre th
. Esto significa que la div
esquina inferior izquierda del borde se encuentra encima del borde de la columna izquierda y a mitad de camino. A partir de aquí, es evidente que necesitamos movernos hacia abajo un ancho de borde y más de un ancho de celda, pero ¿cómo vamos a lograrlo de manera receptiva? Es en este mismo momento que tal vez recuerdes que aún no hemos agregado el span
: ¡lo vamos a necesitar!
Usaremos div
para "descubrir" qué tan grandes son las celdas de la tabla y para span
contener el texto y posicionarlo absolutamente también para desbordar el padre.
thdivspanColumn header 1/span/div/th
th.rotate{ white-space: nowrap; position: relative;}th.rotate div { position: absolute; bottom: 0; left: 0; width: 100%; /* - now the div parent is as wide as the columns */}th.rotate div span { position: absolute; bottom: 0; left: 0; border-bottom: 1px solid gray;}
¡Genial! Cuando configuramos el ancho de la columna div
en 100%, contiene la información sobre el tamaño de la columna, independientemente del contenido de las celdas de la tabla. Con esto en su lugar, podemos trasladar fácilmente las cosas según el ancho del div
, pero no olvidemos que debemos reducir la mitad del ancho del borde. Nuestra traducción se convierte en:
transform: translate( calc( 100% - var(--table-border-width)/2), var(--table-border-width));
Ahora está div
en el lugar correcto para rotar, pero debemos asegurarnos de elegir el origen de transformación correcto. Queremos que esté en la esquina superior izquierda del borde, que estará a la izquierda y arriba del ancho de un borde desde la parte inferior de nuestro div
elemento:
transform-origin: 0%, calc(100% - var(--table-border-width));
Esto nos lleva a nuestro estilo final para el encabezado de la tabla.
table { border-collapse: collapse; --table-border-width: 1px;}th.rotate{ white-space: nowrap; position: relative;}th.rotate div { position: absolute; bottom: 0; left: 0; width: 100%; transform: translate( calc( 100% - var(--table-border-width)/2), var(--table-border-width)); rotate(315deg); transform-origin: 0%, calc(100% - var(--table-border-width));}th.rotate div span { position: absolute; bottom: 0; left: 0; border-bottom: var(--table-border-width) solid gray;}
Tenga en cuenta que las transformaciones ocurren después de que todo esté colocado. Eso significa que los encabezados rotados se desbordarán sobre todo lo mejor que puedan. Tendrás que envolver toda la mesa con algo para compensar la altura inesperada. Junté el título y la tabla en un flexbox div
y configuré el flex-basis
título en un valor lo suficientemente grande como para compensar los encabezados altos.
#div-with-table { display: flex; flex-direction: column; justify-content: space-around;}#title { flex-basis: 140px;}
Deja un comentario