Disons que j'ai quelques colonnes, dont certaines que j'aimerais faire pivoter les valeurs 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>
Avec ce CSS:
.statusColumn b {
writing-mode: tb-rl;
white-space: nowrap;
display: inline-block;
overflow: visible;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
Cela finit par ressembler à ceci:
Est-il possible d'écrire n'importe quel CSS qui fera que l'élément pivoté affecte la hauteur de son parent, de sorte que le texte ne chevauche pas les autres éléments? Quelque chose comme ça:
css
css-transforms
Chris
la source
la source
writing-mode
est disponible pour la plupart des navigateurs, mais horriblement bogué. Sur une question connexe, je suis passé par plusieurs itérations pour essayer de contourner les bogues spécifiques au navigateur avant d'abandonner; vous pouvez voir ma succession d'échecs sur stackoverflow.com/posts/47857248/revisions , où je commence par quelque chose qui fonctionne dans Chrome mais pas Firefox ou Edge, puis je casse Chrome en train de réparer les deux autres, et finis par revenir sur mon répondez et étiquetez-le comme Chrome uniquement. Soyez prudent, si vous voulez emprunter cette voie. (Notez également que cela ne sert à rien avec les éléments non textuels.)Réponses:
En supposant que vous souhaitiez faire pivoter de 90 degrés, cela est possible, même pour les éléments non textuels - mais comme beaucoup de choses intéressantes dans CSS, cela nécessite un peu de ruse. Ma solution invoque également techniquement un comportement indéfini selon la spécification CSS 2 - donc, bien que j'aie testé et confirmé qu'elle fonctionne dans Chrome, Firefox, Safari et Edge, je ne peux pas vous promettre qu'elle ne se cassera pas à l'avenir. version du navigateur.
Réponse courte
Compte tenu du HTML comme celui-ci, où vous voulez faire pivoter
.element-to-rotate
...... introduisez deux éléments wrapper autour de l'élément que vous souhaitez faire pivoter:
... puis utilisez le CSS suivant, pour tourner dans le sens anti-horaire (ou voir le commenté
transform
pour un moyen de le changer en une rotation dans le sens horaire):Démo d'extraits de pile
Afficher l'extrait de code
Comment cela marche-t-il?
La confusion face aux incantations que j'ai utilisées ci-dessus est raisonnable; il se passe beaucoup de choses, et la stratégie globale n'est pas simple et nécessite une certaine connaissance des anecdotes CSS pour la comprendre. Passons en revue étape par étape.
Le cœur du problème auquel nous sommes confrontés est que les transformations appliquées à un élément à l'aide de sa
transform
propriété CSS se produisent toutes après la mise en page. En d'autres termes, l'utilisationtransform
sur un élément n'affecte pas du tout la taille ou la position de son parent ou de tout autre élément. Il n'y a absolument aucun moyen de changer ce fait de commenttransform
fonctionne. Ainsi, pour créer l'effet de rotation d'un élément et que la hauteur de son parent respecte la rotation, nous devons faire les choses suivantes:.element-to-rotate
.element-to-rotate
manière à la superposer exactement sur l'élément de l'étape 1.L'élément de l'étape 1 doit être
.rotation-wrapper-outer
. Mais comment faire en sorte que sa hauteur soit égale à.element-to-rotate
la largeur de s ?L'élément clé de notre stratégie ici est le
padding: 50% 0
sur.rotation-wrapper-inner
. Cet exploit est un détail excentrique de la spécification pourpadding
: que les pourcentages de rembourrage, même pourpadding-top
etpadding-bottom
, sont toujours définis comme des pourcentages de la largeur du conteneur de l'élément . Cela nous permet d'effectuer l'astuce en deux étapes suivante:display: table
sur.rotation-wrapper-outer
. Cela lui donne une largeur de rétrécissement , ce qui signifie que sa largeur sera définie en fonction de la largeur intrinsèque de son contenu, c'est-à-dire en fonction de la largeur intrinsèque de.element-to-rotate
. (Sur les navigateurs pris en charge, nous pourrions y parvenir plus proprement avecwidth: max-content
, mais à partir de décembre 2017, cemax-content
n'est toujours pas pris en charge dans Edge .)height
of.rotation-wrapper-inner
sur 0, puis définissons son remplissage sur50% 0
(c'est-à-dire 50% haut et 50% bas). Cela l'amène à prendre un espace vertical égal à 100% de la largeur de son parent - ce qui, grâce à l'astuce de l'étape 1, est égal à la largeur de.element-to-rotate
.Ensuite, il ne reste plus qu'à effectuer la rotation et le positionnement réels de l'élément enfant. Naturellement,
transform: rotate(-90deg)
fait la rotation; nous utilisonstransform-origin: top left;
pour faire en sorte que la rotation se produise autour du coin supérieur gauche de l'élément pivoté, ce qui rend la translation ultérieure plus facile à raisonner, car elle laisse l'élément pivoté directement au-dessus de l'endroit où il aurait été dessiné autrement. On peut ensuite utilisertranslate(-100%)
pour faire glisser l'élément vers le bas d'une distance égale à sa largeur de pré-rotation.Cela n'obtient toujours pas le bon positionnement, car nous devons toujours compenser le rembourrage supérieur de 50%
.rotation-wrapper-outer
. Nous y parvenons en nous assurant que.element-to-rotate
hasdisplay: block
(pour que les marges fonctionnent correctement dessus), puis en appliquant un -50%margin-top
- notez que les marges en pourcentage sont également définies par rapport à la largeur de l'élément parent.Et c'est tout!
Pourquoi n'est-ce pas entièrement conforme aux spécifications?
En raison de la note suivante tirée de la définition des pourcentages de rembourrage et des marges dans la spécification (mine en gras):
Étant donné que toute l'astuce tournait autour de rendre le remplissage de l'élément enveloppe interne par rapport à la largeur de son conteneur qui dépendait à son tour de la largeur de son enfant, nous remplissons cette condition et invoquons un comportement non défini. Cependant, cela fonctionne actuellement dans les 4 principaux navigateurs, contrairement à certains ajustements apparemment conformes aux spécifications que j'ai essayés, comme changer
.rotation-wrapper-inner
pour être un frère.element-to-rotate
plutôt qu'un parent.la source
writing-mode
solutions seront la meilleure approche si IE 11 n'a pas besoin d'être pris en charge.Comme le souligne à juste titre le commentaire de G-Cyr , le soutien actuel
writing-mode
est plus que décent . Combiné à une simple rotation, vous obtenez le résultat exact que vous souhaitez. Voir l'exemple ci-dessous.la source
writing-mode: vertical-lr; transform: rotate(180deg);
Malheureusement (?) C'est ainsi que cela est supposé fonctionner même si vous faites pivoter votre élément, il a toujours une certaine largeur et hauteur, cela ne change pas après la rotation. Vous le modifiez visuellement, mais il n'y a pas de boîte d'emballage invisible qui change sa taille lorsque vous faites pivoter les choses.
Imaginez une rotation de moins de 90 ° (par exemple
transform: rotate(45deg)
): vous devriez introduire une telle boîte invisible qui a maintenant des dimensions ambiguës basées sur les dimensions d'origine de l'objet que vous faites tourner et la valeur de rotation réelle.Du coup, vous n'avez pas seulement le
width
etheight
de l'objet que vous avez tourné, mais vous avez également lewidth
etheight
de la "boîte invisible" autour de lui. Imaginez demander la largeur extérieure de cet objet - que renverrait-il? La largeur de l'objet, ou notre nouvelle boîte? Comment distinguerions-nous les deux?Par conséquent, il n'y a pas de CSS que vous pouvez écrire pour corriger ce comportement (ou devrais-je dire, «automatiser»). Bien sûr, vous pouvez augmenter la taille de votre conteneur parent à la main ou écrire du JavaScript pour gérer cela.
(Juste pour être clair, vous pouvez essayer d'utiliser
element.getBoundingClientRect
pour obtenir le rectangle mentionné précédemment).Comme décrit dans la spécification :
Cela signifie qu'aucune modification ne sera apportée au contenu entourant l'objet que vous transformez, sauf si vous les faites manuellement.
La seule chose qui est prise en compte lors de la transformation de votre objet est la zone de débordement:
Voir ce jsfiddle pour en savoir plus.
Il est en fait assez bon de comparer cette situation à un décalage d'objet en utilisant:
position: relative
- le contenu environnant ne change pas, même si vous déplacez votre objet ( exemple ).Si vous souhaitez gérer cela en utilisant JavaScript, jetez un œil à cette question.
la source
Utilisez des pourcentages pour
padding
et un pseudo élément pour pousser le contenu. Dans le JSFiddle, j'ai laissé le pseudo élément en rouge pour le montrer et vous devrez compenser le décalage du texte mais je pense que c'est la voie à suivre.http://jsfiddle.net/MTyFP/7/
Une description de cette solution peut être trouvée ici: http://kizu.ru/en/fun/rotated-text/
la source
Veuillez voir la version mise à jour dans mon autre réponse . Cette réponse n'est plus valable et ne fonctionne tout simplement plus. Je vais le laisser ici pour des raisons historiques.
Cette question est assez ancienne, mais avec le support actuel de l'
.getBoundingClientRect()
objet et ses valeurswidth
etheight
, en combinaison avec la possibilité d'utiliser cette méthode soignée avectransform
, je pense que ma solution devrait également être mentionnée.Voyez-le en action ici . (Testé dans Chrome 42, FF 33 et 37.)
getBoundingClientRect
calcule la largeur et la hauteur réelles de la boîte de l'élément. Nous pouvons donc tout simplement parcourir tous les éléments et définir sa hauteur minimale sur la hauteur réelle de la boîte de leurs enfants.(Avec quelques modifications, vous pouvez parcourir les enfants en boucle et découvrir lequel est le plus grand et définir la hauteur du parent sur l'enfant le plus grand. Cependant, j'ai décidé de rendre l'exemple plus simple. Vous pouvez également ajouter un remplissage du parent au height si vous le souhaitez, ou vous pouvez utiliser une
box-sizing
valeur pertinente en CSS.)Notez cependant que j'ai ajouté un
translate
ettransform-origin
à votre CSS pour rendre le positionnement plus flexible et précis.la source
Je sais que c'est un vieux post mais je l'ai trouvé en luttant exactement avec le même problème. La solution qui fonctionne pour moi est une méthode "low-tech" plutôt rudimentaire en entourant simplement le div que je fais pivoter de 90 degrés avec beaucoup de
Connaissant la largeur approximative (qui devient la hauteur après rotation) de div, je peux compenser la différence en ajoutant des br autour de cette div afin que le contenu au-dessus et en dessous soit poussé en conséquence.
la source