比方说,我有一对夫妇列,其中的一些,我想旋转的值:
http://jsfiddle.net/MTyFP/1/
<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,这样文本将不会覆盖其他元素? 事情是这样的:
Assuming that you want to rotate 90 degrees, this is possible, even for non-text elements - but like many interesting things in CSS, it requires a little cunning. My solution also technically invokes undefined behaviour according to the CSS 2 spec - so while I've tested and confirmed that it works in Chrome, Firefox, Safari, and Edge, I can't promise you that it won't break in a future browser release.
Short answer
Given HTML like this, where you want to rotate .element-to-rotate
...
<div id="container">
<something class="element-to-rotate">bla bla bla</something>
</div>
... introduce two wrapper elements around the element that you want to rotate:
<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>
... and then use the following CSS, to rotate anti-clockwise (or see the commented out transform
for a way to change it into a clockwise rotation):
.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;
}
Stack snippet demo
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>
How does this work?
Confusion in the face of the incantations I've used above is reasonable; there's a lot going on, and the overall strategy is not straightforward and requires some knowledge of CSS trivia to understand. Let's go through it step by step.
The core of the problem we face is that transformations applied to an element using its transform
CSS property all happen after layout has taken place. In other words, using transform
on an element does not affect the size or position of its parent or of any other elements, at all. There is absolutely no way to change this fact of how transform
works. Thus, in order to create the effect of rotating an element and having its parent's height respect the rotation, we need to do the following things:
- Somehow construct some other element whose height is equal to the width of the
.element-to-rotate
- Write our transform on
.element-to-rotate
such as to overlay it exactly on the element from step 1.
The element from step 1 shall be .rotation-wrapper-outer
. But how can we cause its height to be equal to .element-to-rotate
's width?
The key component in our strategy here is the padding: 50% 0
on .rotation-wrapper-inner
. This exploit's an eccentric detail of the spec for padding
: that percentage paddings, even for padding-top
and padding-bottom
, are always defined as percentages of the width of the element's container. This enables us to perform the following two-step trick:
- 我们设置
display: table
上.rotation-wrapper-outer
。 这将导致它有收缩到合适宽度 ,这意味着它的宽度将根据其内容的固有宽度被设置-即,基于对所述固有宽度.element-to-rotate
。 (在支持的浏览器,我们可以更干净地实现这个width: max-content
,但截至2017年12月, max-content
是仍然不支持边 )。 - 我们设置了
height
的.rotation-wrapper-inner
为0,那么它的填充设定为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
-注意百分比的利润也相对的宽度定义父元素。
就是这样!
为什么不是这个,符合技术规范的全部?
因为从规范的百分比填充和利润率的定义如下说明 :(加粗雷)
的百分比相对于所生成的框的宽度计算出包含块 ,即使对于“填充顶”和“填充底部” 。 如果包含块的宽度取决于该元件上,然后将所得的布局是在CSS 2.1未定义。
由于整个招围绕使内包装元素的填充是相对于其容器的宽度,后者又取决于其子的宽度,我们达不到这个条件,调用未定义的行为。 目前,它适用于所有的4级主要的浏览器,虽然-不像一些看似规范兼容的调整接近,我试过,如改变.rotation-wrapper-inner
是一个兄弟.element-to-rotate
,而不是父母。
不幸的是(?),这是它是如何想,即使你旋转你的元素它还是有一定的宽度和高度,不旋转后换个工作。 你在视觉上改变它,但是当你旋转的东西,改变其大小没有看不见的包装箱。
想象一下,旋转它小于90°(如transform: rotate(45deg)
你将不得不推出这样无形的盒子现在有基于你旋转物体与实际转速值的原始尺寸暧昧尺寸。
突然间,你不仅有width
和height
,你已经旋转的对象,但你也有width
和height
的“无形的盒子”,围绕它的。 想象一下,请求该对象的外部宽度 - 那会回来吗? 对象,还是我们的新框的宽度? 我们如何在两者之间区别?
因此,没有CSS,你可以写来解决这个问题(或者我应该说,“自动化”的话)。 当然你也可以通过手工增加你父容器的大小,或者写一些JavaScript来处理这个问题。
(只是要清楚,你可以尝试使用element.getBoundingClientRect
获得前面提到的矩形)。
由于在规范中描述 :
在HTML命名空间,变换属性不影响周围的变换元素中的内容的流动。
这意味着,任何改变都会给你周围正在改变,除非你手工做出来的对象的内容进行。
当你改变你的对象时考虑的唯一的事情就是溢出区:
(...)的溢出区域的范围考虑到了转化的元件。 此行为是相似的元素时,通过相对定位偏移会发生什么。
看到这个的jsfiddle了解更多信息。
它实际上是相当不错的这种情况比较对象使用偏移: position: relative
-周围的内容不会改变,即使你四处移动你的对象( 例如 )。
如果你想解决这个使用JavaScript,看看这个问题。
使用百分比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://jsfiddle.net/MTyFP/7/
该解决方案的记录可以在这里找到: http://kizu.ru/en/fun/rotated-text/
作为由G圣西尔评论理所当然地指出, 当前支持writing-mode
比体面的多 。 用一个简单的旋转相结合,你会得到你想要的精确结果。 请参见下面的例子。
.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; }
<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>
请参阅在更新的版本我其他的答案 。 这个答案是不再有效,根本不起作用了。 我会离开这里的历史原因。
这个问题是很老,但对于当前支持.getBoundingClientRect()
对象和它的width
和height
值,在使用这种方法整齐一起的能力相结合transform
,我觉得我的解决方案应该提到的为好。
看到它在行动这里 。 (在铬42,FF 33 37测试)
getBoundingClientRect
计算元件的实际框的宽度和高度。 很简单的话,我们可以通过所有元素循环,并设置它的最小高度子女的实际框的高度。
$(".statusColumn").each(function() {
var $this = $(this),
child = $this.children(":first");
$this.css("minHeight", function() {
return child[0].getBoundingClientRect().height;
});
});
(经过一些修改可以通过孩子环路,并找出哪些人的最高和家长的高度设置为最高的孩子。不过,我决定让这个例子更简单。你也可以在父母的添加填充高度,如果你愿意,也可以使用相关的box-sizing
的CSS值。)
但是请注意,我添加了一个translate
和transform-origin
于你的CSS,使定位更加灵活和准确。
transform: rotate(-90deg) translateX(-100%);
transform-origin: top left;
书写模式属性将做到这一点。 当前支持writing-mode
比体面的多 。 用一个简单的旋转相结合,你会得到你想要的精确结果。 请参见下面的例子。
.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; }
<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>
(从答案拆分布拉姆Vanroy )
我知道这是一个老的文章,但我发现它,而具有完全相同的问题所困扰。 这对我的作品的解决方案是通过简单而粗糙“低科技”的方式包围我通过90度旋转分度,很多
<br>
知道了近似宽度(其旋转之后变得高度)的div我可以通过添加BR的解决此以上的div所以内容和下面被相应地推补偿的差值。