Digamos que tengo un par de columnas, algunas de las cuales me gustaría rotar los valores de:
<div class="container">
<div class="statusColumn"><span>Normal</span></div>
<div class="statusColumn"><a>Normal</a></div>
<div class="statusColumn"><b>Rotated</b></div>
<div class="statusColumn"><abbr>Normal</abbr></div>
</div>
Con este CSS:
.statusColumn b {
writing-mode: tb-rl;
white-space: nowrap;
display: inline-block;
overflow: visible;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
Termina luciendo así:
¿Es posible escribir cualquier CSS que haga que el elemento girado afecte la altura de su padre, de modo que el texto no se superponga a los otros elementos? Algo como esto:
css
css-transforms
Chris
fuente
fuente
writing-mode
está disponible para la mayoría de los navegadores, pero tiene muchos errores. En una pregunta relacionada, pasé por varias iteraciones para tratar de solucionar los errores específicos del navegador antes de rendirme; puede ver mi sucesión de fallas en stackoverflow.com/posts/47857248/revisions , donde comienzo con algo que funciona en Chrome pero no en Firefox o Edge, luego rompo Chrome en el proceso de arreglar los otros dos, y termino revirtiendo mi responder y etiquetarlo como solo para Chrome. Tenga cuidado si quiere seguir este camino. (También tenga en cuenta que no sirve de nada con elementos que no son de texto).Respuestas:
Suponiendo que desea rotar 90 grados, esto es posible, incluso para elementos que no son de texto, pero como muchas cosas interesantes en CSS, requiere un poco de astucia. Mi solución también invoca técnicamente un comportamiento indefinido de acuerdo con la especificación CSS 2, así que aunque he probado y confirmado que funciona en Chrome, Firefox, Safari y Edge, no puedo prometerle que no se romperá en el futuro. lanzamiento del navegador.
Respuesta corta
Dado HTML como este, donde desea rotar
.element-to-rotate
...... introduzca dos elementos de envoltura alrededor del elemento que desea rotar:
... y luego use el siguiente CSS, para rotar en sentido antihorario (o vea el comentario
transform
para una forma de cambiarlo a una rotación en sentido horario):Demostración de fragmentos de pila
Mostrar fragmento de código
¿Como funciona esto?
La confusión ante los encantamientos que he usado anteriormente es razonable; están sucediendo muchas cosas, y la estrategia general no es sencilla y requiere algunos conocimientos de trivia de CSS para comprender. Veámoslo paso a paso.
El núcleo del problema al que nos enfrentamos es que las transformaciones aplicadas a un elemento utilizando su
transform
propiedad CSS ocurren después de que se ha realizado el diseño. En otras palabras, el usotransform
de un elemento no afecta en absoluto el tamaño o la posición de su padre ni de ningún otro elemento. No hay absolutamente ninguna manera de cambiar este hecho de cómotransform
funciona. Por lo tanto, para crear el efecto de rotar un elemento y hacer que la altura de su padre respete la rotación, debemos hacer lo siguiente:.element-to-rotate
.element-to-rotate
para superponerla exactamente en el elemento del paso 1.El elemento del paso 1 será
.rotation-wrapper-outer
. Pero, ¿cómo podemos hacer que su altura sea igual a.element-to-rotate
la anchura de ?El componente clave de nuestra estrategia aquí es el
padding: 50% 0
encendido.rotation-wrapper-inner
. Este exploit es un detalle excéntrico de la especificación parapadding
: ese porcentaje de relleno, incluso parapadding-top
ypadding-bottom
, siempre se define como porcentajes del ancho del contenedor del elemento . Esto nos permite realizar el siguiente truco de dos pasos:display: table
en marcha.rotation-wrapper-outer
. Esto hace que tenga un ancho de encogimiento para ajustar , lo que significa que su ancho se establecerá en función del ancho intrínseco de su contenido, es decir, en función del ancho intrínseco de.element-to-rotate
. (En apoyo a los navegadores, podríamos lograr esto de forma más limpia conwidth: max-content
, pero a partir de diciembre de 2017,max-content
está todavía no se admite en el borde .)height
de.rotation-wrapper-inner
en 0, luego establecemos su relleno en50% 0
(es decir, 50% superior y 50% inferior). Esto hace que ocupe un espacio vertical igual al 100% del ancho de su padre, que, a través del truco del paso 1, es igual al ancho de.element-to-rotate
.A continuación, todo lo que queda es realizar la rotación y el posicionamiento reales del elemento hijo. Naturalmente,
transform: rotate(-90deg)
hace la rotación; usamostransform-origin: top left;
para hacer que la rotación ocurra alrededor de la esquina superior izquierda del elemento girado, lo que hace que la traslación posterior sea más fácil de razonar, ya que deja el elemento girado directamente encima de donde de otro modo se habría dibujado. Luego, podemos usartranslate(-100%)
para arrastrar el elemento hacia abajo una distancia igual a su ancho de prerotación.Eso todavía no consigue el posicionamiento correcto, porque todavía necesitamos compensar el 50% del relleno superior activado
.rotation-wrapper-outer
. Lo logramos asegurándonos de que.element-to-rotate
tienedisplay: block
(para que los márgenes funcionen correctamente en él) y luego aplicando un -50%margin-top
; tenga en cuenta que los márgenes porcentuales también se definen en relación con el ancho del elemento principal.¡Y eso es!
¿Por qué no cumple totalmente con las especificaciones?
Debido a la siguiente nota de la definición de porcentajes de relleno y márgenes en la especificación (negrita mía):
Dado que todo el truco giraba en torno a hacer que el relleno del elemento de envoltura interior fuera relativo al ancho de su contenedor, que a su vez dependía del ancho de su hijo, estamos alcanzando esta condición e invocando un comportamiento indefinido. Sin embargo, actualmente funciona en los 4 navegadores principales, a diferencia de algunos ajustes de enfoque aparentemente compatibles con las especificaciones que he intentado, como cambiar
.rotation-wrapper-inner
para ser hermano en.element-to-rotate
lugar de padre.fuente
writing-mode
soluciones serán el mejor enfoque si IE 11 no necesita ser compatible.Como señala con razón el comentario de G-Cyr , el soporte actual para
writing-mode
es más que decente . Combinado con una simple rotación, obtiene el resultado exacto que desea. Vea el ejemplo a continuación.fuente
writing-mode: vertical-lr; transform: rotate(180deg);
Desafortunadamente (?) Así es como se supone que funciona, aunque gire su elemento, todavía tiene cierto ancho y alto, que no cambia después de la rotación. Lo cambias visualmente, pero no hay una caja de envoltura invisible que cambie su tamaño cuando rotas las cosas.
Imagínese rotándolo menos de 90 ° (por ejemplo
transform: rotate(45deg)
): tendría que introducir una caja invisible que ahora tiene dimensiones ambiguas basadas en las dimensiones originales del objeto que está rotando y el valor de rotación real.De repente, no solo tiene el
width
yheight
del objeto que ha girado, sino que también tiene elwidth
yheight
de la "caja invisible" a su alrededor. Imagine solicitar el ancho exterior de este objeto, ¿qué devolvería? ¿El ancho del objeto o nuestra nueva caja? ¿Cómo distinguiríamos entre ambos?Por lo tanto, no hay CSS que pueda escribir para corregir este comportamiento (o debería decir, "automatizarlo"). Por supuesto, puede aumentar el tamaño de su contenedor principal a mano o escribir algo de JavaScript para manejar eso.
(Para que quede claro, puede intentar usar
element.getBoundingClientRect
para obtener el rectángulo mencionado anteriormente).Como se describe en la especificación :
Esto significa que no se realizarán cambios en el contenido que rodea al objeto que está transformando, a menos que los haga a mano.
Lo único que se tiene en cuenta cuando transforma su objeto es el área de desbordamiento:
Vea este jsfiddle para obtener más información.
De hecho, es bastante bueno comparar esta situación con el desplazamiento de un objeto utilizando:
position: relative
- el contenido circundante no cambia, aunque esté moviendo el objeto ( ejemplo ).Si desea manejar esto usando JavaScript, eche un vistazo a esta pregunta.
fuente
Utilice porcentajes para
padding
y un pseudo elemento para impulsar el contenido. En JSFiddle dejé el pseudo elemento rojo para mostrarlo y tendrás que compensar el desplazamiento del texto, pero creo que ese es el camino a seguir.http://jsfiddle.net/MTyFP/7/
Se puede encontrar un informe de esta solución aquí: http://kizu.ru/en/fun/rotated-text/
fuente
Consulte la versión actualizada en mi otra respuesta . Esta respuesta ya no es válida y simplemente ya no funciona. Lo dejo aquí por razones históricas.
Esta pregunta es bastante antigua, pero con el soporte actual para el
.getBoundingClientRect()
objeto y sus valoreswidth
yheight
, en combinación con la capacidad de usar este método ordenado junto contransform
, creo que mi solución también debería mencionarse.Véalo en acción aquí . (Probado en Chrome 42, FF 33 y 37.)
getBoundingClientRect
calcula el ancho y alto de la caja real del elemento. Entonces, simplemente, podemos recorrer todos los elementos y establecer su altura mínima a la altura real de la caja de sus hijos.(Con algunas modificaciones, puede recorrer los niños y averiguar cuál es el más alto y establecer la altura del padre en el hijo más alto. Sin embargo, decidí hacer el ejemplo más sencillo. También puede agregar el relleno del padre al altura si lo desea, o puede usar un
box-sizing
valor relevante en CSS).Sin embargo, tenga en cuenta que agregué un
translate
ytransform-origin
a su CSS para hacer que el posicionamiento sea más flexible y preciso.fuente
Sé que es una publicación antigua, pero la encontré mientras luchaba con exactamente el mismo problema. La solución que me funciona es un método bastante tosco de "baja tecnología", simplemente rodeando el div. Giro 90 grados con una gran cantidad de
Sabiendo el ancho aproximado (que se convierte en altura después de la rotación) de div, puedo compensar la diferencia agregando br alrededor de este div para que el contenido de arriba y de abajo se empuje en consecuencia.
fuente