CSS支持多种单位形式,如百分比、px、pt、rem等,百分比和px是常用的单位,随着移动端和响应式的流行,rem、vh、vw也开始普遍使用。
今天在SegmentFault社区碰到了两个关于百分比计算的问题,一个是在translate中使用百分比的时候,是相对于哪个DOM元素的大小计算的;另外一个是在padding、margin等中使用百分比时,百分比又是怎么转为px的呢?
对于第一个,移动距离是根据自身元素的大小来计算的:
[The percentage] refer[s] to the size of the element's box
例如:在不知道元素的宽度和高度的情况下,让元素水平垂直居中
创建类名为wrapper的div,并设置其样式
.wrapper { padding: 20px; background:orange; color:#fff; position:absolute; top:50%; left:50%; border-radius: 5px; -webkit-transform:translate(-50%,-50%); -moz-transform:translate(-50%,-50%); transform:translate(-50%,-50%); }
对于第二个,我认为percentage转px应该是浏览器根据css规定来完成的,但是具体怎么算呢?
Example 1: Margins
<div style="width: 20px"> <div id="temp1" style="margin-top: 50%">Test top</div> <div id="temp2" style="margin-right: 25%">Test right</div> <div id="temp3" style="margin-bottom: 75%">Test bottom</div> <div id="temp4" style="margin-left: 100%">Test left</div> </div>
得到的offset如下:
temp1.marginTop = 20px * 50% = 10px; temp2.marginRight = 20px * 25% = 5px; temp3.marginBottom = 20px * 75% = 15px; temp4.marginLeft = 20px * 100% = 20px;
然后,我又测试了padding,原以为padding的值会根据应用了该属性的相关元素来计算,但让我惊讶的是,padding也是根据应用该属性的父元素的宽来计算的,跟margin表现一致。(再插一句:当按百分比设定一个元素的宽度时,它是相对于父容器的宽度计算的,元素竖向的百分比设定也是相对于容器的宽度,而不是高度。)
但有一个坑,上面都是对于未定位元素。好奇的我又很好奇,对于非静态定位元素的top, right, bottom, 和left的百分比值又怎么计算呢?
Example 2: Positioned Elements
<div style="height: 100px; width: 50px"> <div id="temp1" style="position: relative; top: 50%">Test top</div> <div id="temp2" style="position: relative; right: 25%">Test right</div> <div id="temp3" style="position: relative; bottom: 75%">Test bottom</div> <div id="temp4" style="position: relative; left: 100%">Test left</div> </div>
得到的offset如下:
temp1.top = 100px * 50% = 50px; temp2.right = 100px * 25% = 25px; temp3.bottom = 100px * 75% = 75px; temp4.left = 100px * 100% = 100px;
对于定位元素,这些值也是相对于父元素的,但与非定位元素不同的是,它们是相对于父元素的高而不是宽。
when the parent element does not have a height, then percentage values are processed as auto instead
虽然有点困惑,但只需要记住:对于margin和padding,百分比按照父元素的宽计算,对于定位元素,则按照父元素的高计算。
FK
429***967@qq.com
参考地址
CSS margin 百分比
假设一个块级包含容器,宽 1000px,高 600px,块级子元素定义 margin:10% 5%; 大家说说 margin 的 top, right, bottom, left 计算值最终是多少?
CSS 代码:
HTML 代码:
结果为:100px 50px 100px 50px
为什么会这样?
诧异吗?不用怀疑浏览器出了问题,因为这是正确的实现。
规范中注明 margin 的百分比值参照其包含块的宽度进行计算。但这只发生在默认的 writing-mode: horizontal-tb; 和 direction: ltr; 的情况下。
当书写模式变成纵向的时候,其参照将会变成包含块的高度。我们改变一下上面例子中的 CSS 书写模式:
CSS 代码:
这时的结果为:60px 30px 60px 30px
也就是说书写模式影响 margin 百分比的参照对象。
顺带再说说
你是否觉得这不符合常规的感性认知?感性认知更多感觉应该横向参照包含块宽度,纵向参照包含块高度。
其实这是为了要横向和纵向2个方向都创建相同的 margin,如果它们的参照物不一致,那就无法得到两个方向相同的留白。
你可能会问那为什么要选择宽度做参照而不是高度呢?
这其实更多的要从 CSS 设计意图上去想,因为CSS的基础需求是排版,而通常我们所见的横排文字,其水平宽度一定(仔细回想一下,如果没有显式的定义宽度或者强制一行显示,都会遇到边界换行,而不是水平延展),垂直方向可以无限延展。但当书写模式为纵向时,其参照就变成了高度而不再是宽度了。
FK
429***967@qq.com
参考地址
Cirunger
812***595@qq.com
上面有些错误 我需要纠正一下 对于非定位元素 top left right bottom 的百分比 确实是相对于父元素的宽来设定的。
对于相对定位元素 top 和 bottom 是相对父元素的高 left 和 right 是相对父元素的宽。
对于绝对定位元素 top 和 bottom 是相对最近一级非 static 定位父元素(否则就是 html), left 和 right 是相对最近一级非 static 定位父元素(否则就是html)的宽。
Cirunger
812***595@qq.com