假设您希望旋转90度,即使对于非文本元素也可以旋转-但是像CSS中许多有趣的事情一样,它需要一点技巧。根据CSS 2规范,我的解决方案还从技术上调用了未定义的行为-因此,尽管我已经测试并确认它可以在Chrome,Firefox,Safari和Edge中运行,但我不能保证将来不会损坏浏览器版本。
简短答案
给定这样的HTML,您想在其中旋转.element-to-rotate
...
<div id="container">
<something class="element-to-rotate">bla bla bla</something>
</div>
... 在要旋转的元素周围引入两个包装器元素:
<div id="container">
<div class="rotation-wrapper-outer">
<div class="rotation-wrapper-inner">
<something class="element-to-rotate">bla bla bla</something>
</div>
</div>
</div>
...,然后使用以下CSS逆时针旋转(或查看注释,transform
以将其更改为顺时针旋转):
.rotation-wrapper-outer {
display: table;
}
.rotation-wrapper-inner {
padding: 50% 0;
height: 0;
}
.element-to-rotate {
display: block;
transform-origin: top left;
/* Note: for a CLOCKWISE rotation, use the commented-out
transform instead of this one. */
transform: rotate(-90deg) translate(-100%);
/* transform: rotate(90deg) translate(0, -100%); */
margin-top: -50%;
/* Not vital, but possibly a good idea if the element you're rotating contains
text and you want a single long vertical line of text and the pre-rotation
width of your element is small enough that the text wraps: */
white-space: nowrap;
}
堆栈片段演示
p {
/* Tweak the visuals of the paragraphs for easier visualiation: */
background: pink;
margin: 1px 0;
border: 1px solid black;
}
.rotation-wrapper-outer {
display: table;
}
.rotation-wrapper-inner {
padding: 50% 0;
height: 0;
}
.element-to-rotate {
display: block;
transform-origin: top left;
/* Note: for a CLOCKWISE rotation, use the commented-out
transform instead of this one. */
transform: rotate(-90deg) translate(-100%);
/* transform: rotate(90deg) translate(0, -100%); */
margin-top: -50%;
/* Not vital, but possibly a good idea if the element you're rotating contains
text and you want a single long vertical line of text and the pre-rotation
width of your element is small enough that the text wraps: */
white-space: nowrap;
}
<div id="container">
<p>Some text</p>
<p>More text</p>
<div class="rotation-wrapper-outer">
<div class="rotation-wrapper-inner">
<p class="element-to-rotate">Some rotated text</p>
</div>
</div>
<p>Even more text</p>
<img src="https://i.stack.imgur.com/ih8Fj.png">
<div class="rotation-wrapper-outer">
<div class="rotation-wrapper-inner">
<img class="element-to-rotate" src="https://i.stack.imgur.com/ih8Fj.png">
</div>
</div>
<img src="https://i.stack.imgur.com/ih8Fj.png">
</div>
这是如何运作的?
我上面使用的魔咒面对的困惑是合理的;发生了很多事情,总体策略并不简单,需要一些CSS琐事知识才能理解。让我们逐步进行一下。
我们面临的问题的核心是,使用其transform
CSS属性应用于元素的转换都在布局发生后发生。换句话说,transform
在元素上使用完全不影响其父元素或任何其他元素的大小或位置。绝对没有办法改变这种transform
工作原理。因此,为了产生旋转元素并使其父代的高度尊重旋转的效果,我们需要执行以下操作:
- 以某种方式构造高度等于宽度的其他元素
.element-to-rotate
- 编写我们的转换,
.element-to-rotate
以便将其准确地覆盖在步骤1的元素上。
步骤1中的元素应为.rotation-wrapper-outer
。但是,如何使它的高度等于.element-to-rotate
的宽度呢?
我们策略中的关键部分是padding: 50% 0
on .rotation-wrapper-inner
。此漏洞利用是该规范的怪异细节padding
:即使对于padding-top
和padding-bottom
,填充百分比也总是定义为元素容器宽度的百分比。这使我们能够执行以下两步技巧:
- 我们设定
display: table
的.rotation-wrapper-outer
。这将导致其具有“ 收缩至适合”宽度,这意味着将根据其内容的固有宽度(即基于的固有宽度)来设置其宽度.element-to-rotate
。(在支持的浏览器,我们可以更干净地做到这一点width: max-content
,但截至2017年12月,max-content
是仍然不支持边)。
- 我们将
height
of 设置.rotation-wrapper-inner
为0,然后将其padding设置为50% 0
(即50%顶部和50%底部)。这将导致它占用等于其父级宽度100%的垂直空间-通过第1步中的技巧,它等于的宽度.element-to-rotate
。
接下来,剩下的就是执行子元素的实际旋转和定位。自然地,transform: rotate(-90deg)
旋转;我们transform-origin: top left;
通常使旋转发生在旋转元素的左上角附近,这使得后续平移更容易推论,因为它使旋转元素直接位于原本应绘制的位置上方。然后,我们可以使用translate(-100%)
向下拖动元素,使其距离等于其预旋转宽度。
那仍然不能完全正确地定位,因为我们仍然需要为上的50%顶部填充补偿.rotation-wrapper-outer
。我们通过确保.element-to-rotate
具有display: block
(使边距在其上正常工作)然后应用-50%来实现这一点margin-top
-请注意,还相对于父元素的宽度定义了边距百分比。
就是这样!
为什么不完全符合规范?
由于以下规范中的填充百分比和边距定义(注释矿井),请注意以下几点:
即使对于'padding-top'和'padding-bottom'而言,百分比也是相对于所生成的盒子的包含块的宽度来计算的。如果包含块的宽度取决于此元素,则CSS 2.1中未定义结果布局。
由于整个技巧都围绕着使内部包装器元素的填充相对于其容器的宽度而定,而容器的宽度又取决于其子容器的宽度,因此我们遇到了这种情况并调用了不确定的行为。不过,它目前可在所有4种主要浏览器中使用-与我尝试过的一些看似符合规范的调整方法不同,例如更改.rotation-wrapper-inner
为同级.element-to-rotate
而不是父级。