假设我有几列,其中一些我想旋转值:
<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>
使用这个CSS:
.statusColumn b {
writing-mode: tb-rl;
white-space: nowrap;
display: inline-block;
overflow: visible;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
最终看起来像这样:
是否可以编写任何会导致旋转元素影响其父级高度的CSS,这样文本就不会与其他元素重叠?像这样:
答案 0 :(得分:38)
不幸的是(?)即使你旋转你的元素它仍然具有一定的宽度和高度,并且旋转后不会改变。你可以直观地改变它,但是当你旋转东西时,没有看不见的包装盒会改变它的大小。
想象一下旋转它小于90°(例如transform: rotate(45deg)
):你必须引入这样一个不可见的盒子,它现在根据你正在旋转的物体的原始尺寸和实际旋转值具有模糊的尺寸。
突然间,您不仅拥有已旋转对象的width
和height
,而且还拥有“隐身框”的width
和height
“ 周围。想象一下请求这个对象的外部宽度 - 它会返回什么?对象的宽度,还是我们的新盒子?我们如何区分两者?
因此,没有CSS可以编写来修复此行为(或者我应该说,“自动化”它)。当然,您可以手动增加父容器的大小,或者编写一些JavaScript来处理它。
(为了清楚起见,您可以尝试使用element.getBoundingClientRect
来获取前面提到的矩形。)
在HTML命名空间中,transform属性不会影响转换元素周围内容的流动。
这意味着除非您亲手操作,否则不会对您正在转换的对象周围的内容进行任何更改。
转换对象时唯一需要考虑的是溢出区域:
(...)溢出区域的范围考虑了转换后的元素。此行为类似于当元素通过相对定位进行偏移时会发生什么。
See this jsfiddle to learn more.
使用以下方法将此情况与对象偏移进行比较实际上非常好:position: relative
- 即使您移动对象(example),周围的内容也不会改变。
如果您想使用JavaScript处理此问题,请查看this问题。
答案 1 :(得分:31)
假设您想要旋转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
。但是我们如何才能使 height 等于.element-to-rotate
的 width ?
我们的策略中的关键组件是padding: 50% 0
上的.rotation-wrapper-inner
。此漏洞利用an eccentric detail of the spec for padding
:即使对于padding-top
和padding-bottom
,该百分比填充也始终定义为元素容器的宽度的百分比。这使我们能够执行以下两步操作:
display: table
上设置.rotation-wrapper-outer
。这导致它具有shrink-to-fit width,这意味着它的宽度将根据其内容的固有宽度设置 - 即,基于.element-to-rotate
的固有宽度。 (在支持浏览器方面,我们可以使用width: max-content
更清晰地实现此目标,但截至2017年12月,max-content
为still not supported in Edge。)height
的{{1}}设置为0,然后将其填充设置为.rotation-wrapper-inner
(即50%顶部和50%底部)。这导致它占据的垂直空间等于其父级宽度的100% - 通过步骤1中的技巧,它等于50% 0
的宽度。接下来,剩下的就是执行子元素的实际旋转和定位。当然,.element-to-rotate
进行轮换;我们使用transform: rotate(-90deg)
使旋转发生在旋转元素的左上角周围,这使得后续平移更容易推理,因为它将旋转元素直接留在原本将被绘制的位置上方。然后我们可以使用transform-origin: top left;
将元素向下拖动一个等于其旋转前宽度的距离。
这仍然不能很好地定位,因为我们仍然需要在translate(-100%)
上的50%顶部填充偏移。我们通过确保.rotation-wrapper-outer
具有.element-to-rotate
(以便边距在其上正常运行)然后应用-50%display: block
来实现这一点 - 请注意百分比边距也< / em>相对于父元素的宽度定义。
就是这样!
由于the following note from the definition of percentage paddings and margins in the spec(加粗我的):
百分比是根据生成的框containing block的宽度计算的,即使对于'padding-top'和'padding-bottom'也是如此。 如果包含块的宽度取决于此元素,则在CSS 2.1中未定义结果布局。
由于整个技巧围绕使内包装元素的填充相对于其容器的宽度而言,而容器的宽度又依赖于其子的宽度,因此我们遇到这种情况并调用未定义的行为。它目前适用于所有4种主流浏览器 - 不像我试过的一些看似符合规范的调整,比如将margin-top
改为.rotation-wrapper-inner
的兄弟而不是父母。
答案 2 :(得分:25)
使用padding
的百分比和伪元素来推送内容。在JSFiddle中,我将伪元素留下来显示它,你必须补偿文本的移动,但我认为这是要走的路。
.statusColumn {
position: relative;
border: 1px solid #ccc;
padding: 2px;
margin: 2px;
width: 200px;
}
.statusColumn i, .statusColumn b, .statusColumn em, .statusColumn strong {
writing-mode: tb-rl;
white-space: nowrap;
display: inline-block;
overflow: visible;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
transform: rotate(-90deg);
-webkit-transform: rotate(-90deg);
/* also accepts left, right, top, bottom coordinates; not required, but a good idea for styling */
-webkit-transform-origin: 50% 50%;
-moz-transform-origin: 50% 50%;
-ms-transform-origin: 50% 50%;
-o-transform-origin: 50% 50%;
transform-origin: 50% 50%;
/* Should be unset in IE9+ I think. */
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
}
.statusColumn b:before{ content:''; padding:50% 0; display:block; background:red; position:relative; top:20px
}
<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>
可在此处找到此解决方案的说明:http://kizu.ru/en/fun/rotated-text/
答案 3 :(得分:16)
正如the comment by G-Cyr正确指出的那样,current support for writing-mode
is more than decent。结合简单的旋转,您可以获得所需的精确结果。请参阅下面的示例。
.statusColumn {
position: relative;
border: 1px solid #ccc;
padding: 2px;
margin: 2px;
width: 200px;
}
.statusColumn i,
.statusColumn b,
.statusColumn em,
.statusColumn strong {
writing-mode: vertical-rl;
transform: rotate(180deg);
white-space: nowrap;
display: inline-block;
overflow: visible;
}
&#13;
<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>
&#13;
答案 4 :(得分:10)
请参阅my other answer中的更新版本。这个答案不再有效,根本不再起作用。我会因为历史原因留在这里。
此问题相当陈旧,但目前支持.getBoundingClientRect()
对象及其width
和height
值,并结合使用此简洁方法和{ {1}},我认为我的解决方案也应该被提及。
在行动here中查看。 (在Chrome 42,FF 33&amp; 37中测试过。)
transform
计算元素的实际框宽度和高度。很简单,那么,我们可以循环遍历所有元素并将其最小高度设置为其子项的实际盒高。
getBoundingClientRect
(通过一些修改,你可以循环遍历孩子,找出哪一个是最高的,并将父母的身高设置为最高的孩子。但是,我决定让这个例子更直接。你也可以添加填充如果需要,可以使用父级到父级,也可以在CSS中使用相关的$(".statusColumn").each(function() {
var $this = $(this),
child = $this.children(":first");
$this.css("minHeight", function() {
return child[0].getBoundingClientRect().height;
});
});
值。)
请注意,我在您的CSS中添加了box-sizing
和translate
,以使定位更加灵活和准确。
transform-origin
答案 5 :(得分:3)
写入模式属性将执行此操作。 Current support for writing-mode
is more than decent。结合简单的旋转,您可以获得所需的精确结果。请参阅下面的示例。
.statusColumn {
position: relative;
border: 1px solid #ccc;
padding: 2px;
margin: 2px;
width: 200px;
}
.statusColumn i,
.statusColumn b,
.statusColumn em,
.statusColumn strong {
writing-mode: vertical-rl;
transform: rotate(180deg);
white-space: nowrap;
display: inline-block;
overflow: visible;
}
&#13;
<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>
&#13;
(从Bram Vanroy的答案中分开)
答案 6 :(得分:0)
支持跨浏览器的好解决方案(Firefox、Chrome、Safari、Edge 和 IE11 也是如此!):
尝试一下,同时调整浏览器窗口的大小。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width>">
<title></title>
<style>
.container {
display: flex;
border: 1px solid grey;
}
.vertical,
.horizontal {
padding: 8px;
font-size: 16px;
}
.vertical {
min-width: 20px;
line-height: 20px;
writing-mode: tb-rl;
writing-mode: vertical-rl;
white-space: nowrap;
text-align: center;
transform: rotate(180deg);
}
.horizontal {
border-left: 1px solid grey;
}
</style>
</head>
<body>
<div class="container">
<div class="vertical">
Lorem ipsum dolor sit amet eiusmod
</div>
<div class="horizontal">
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</div>
</body>
</html>
答案 7 :(得分:-16)
我知道它是一个古老的帖子,但我在遇到完全相同的问题的同时找到了它。对我有用的解决方案相当粗糙&#34;低技术&#34;方法简单地用div围绕div旋转90度,用很多
<br>
知道div的近似宽度(旋转后的高度)我可以通过在此div周围添加br来补偿差异,因此上下的内容会被相应推动。