%
百分比是一定有其对应的参照值的。也就是说,百分比值是一种相对值,任何时候要分析它的效果,都需要正确找到它的参照。
可用百分比值的常见 CSS 属性
width & height
宽和高在使用百分比值时,其参照都是元素的包含块(Containing Block,详情)。width 参照包含块的宽度,height 参照包含块的高度。在大部分情况下,包含块就是父元素的内容区(盒模型里的 content)。
我们有时会写这样的代码 width: 100%; height: 100%;
来实现尺寸和父元素一致。但会发现有时候 width: 100%
是可以生效的 ,但 height: 100%;
却没有效果。请看下面这个示例:
如果我们在中间的 div 中加上 height: 100%;
看下效果:
可以看到,直接父元素(包含块)是否有明确的高度定义,会影响 height 为百分比值时的结果。
如果直接父元素 height
为 auto
,只要子元素在文档流中(即 position
不等于 fixed
或者 absolute
),那子元素 height: 100%
会完全就被忽略了,等同于 auto
初始默认值。
如果元素是根元素(<html>
),它的高度等于视窗高度。所以,<html>
标签的高度定义百分比总是有效的,而如果你希望在 <body>
里也用高度百分比,就一定要先为 <html>
定义明确的高度。这就是为什么在之前的固定页脚一文中,有以下这样写法:
html,
body {
height: 100%;
}
为什么?如果包含块(即父元素)的高度没有显式指定(即高度由内容决定),并且该元素不是绝对定位,则计算值为 auto(这是计算值,是指渲染之后解释的值,并不是我们设置 height: auto 所指的值)。一句话总结就是:因为解释成了 auto。要知道,auto 和百分比计算,肯定是算不了的:
'auto' * 100/100 = NaN
此时,他们的计算结果是 NaN,这就是父元素没有设置高度时,子元素高度百分比不生效的原因了。
margin & padding
这两个属性属于混合属性,也通过一个例子说明:
对于 margin
和 padding
,其任意方向的百分比值,参照都是包含块的宽度。
为什么会多个方向都取包含块的宽度作为参照呢?在我看来,包含块的宽度在块布局的排版中是最有用的(想象一下 word 里输入文字,到宽度边缘后换行的场景),对应的,水平方向的内外边距一定要参照包含块的宽度。再考虑垂直方向的内外边距,它们如果不和水平方向取相同的参照物,就会因为不一致而很难使用。所以,总体来说,统一以包含块的宽度作为参考,会具有相对最好的可用性。
严格地说,参照是包含块的宽度,是在样式属性 writing-mode 为默认值时的情况。不过这个属性极少被用到,所以在此不做考虑。
border-radius
你也许见过有人用下面的代码来让一个矩形变成刚好的圆形(请体会这个“刚好”):
.circle {
border-radius: 50%;
}
如果一个元素的 border-radius
为百分比值,其参照物是这个元素自身的尺寸。
也就是说,假如这个元素宽是 60px,高是 40px(border-box 的尺寸),那么 border-radius:50%
的结果等同于 border-radius: 30px / 20px
。
如果你还疑惑这里带 /
的圆角写法,请查看 MDN 对 border-radius 的说明。
background-position
background-position
的初始值就是百分比值 0% 0%
。下面是一个使用示例:
background-position
的百分比值,取的参照是一个减法计算值,由放置背景图的区域尺寸,减去背景图的尺寸得到,可以为负值。
对照上面的示例,思考一下,应该可以感受到,以这个减法计算值为参照的话,正好可以符合我们感官上对背景图位置的理解。这个属性包括水平位置和垂直位置,它们分别参照的是宽度减法计算值和高度减法计算值。
font-size
font-size
参照是直接父元素的 font-size
。
例如,一个元素的直接父元素的 font-size
是 14px,无论这个是直接定义的,还是继承得到的,当该元素定义 font-size: 100%
,获得的效果就是 font-size: 14px
。
line-height
line-height
为百分比其参照是元素自身的 font-size
。
例如,一个元素的 font-size
是 12px ,那么 line-height: 150%
的效果是 line-height: 18px
。
line-height: 1.5
和 line-height: 150%
对于当前元素效果是一样的。
百分比与无单位值之间的区别
line-height 为百分比
body {
font-size: 14px;
line-height: 150%;
}
p {
font-size: 26px;
}
/* 结果就是 */
body {
line-height: 21px; /* 14*150%=21 */
}
p {
line-heigt: 21px; /* 继承父元素 */
}
line-height 为数值
body {
font-size: 14px;
line-height: 1.5;
}
p {
font-size: 26px;
}
/* 结果就是 */
body {
line-height: 21px; /* 14*1.5=21 */
}
p {
line-heigt: 39px; /* 26*1.5=39 */
}
设置
line-height` 的推荐使用无单位,这样子元素继承的也是无单位的值,而不是计算后的特定值。
vertical-align
vertical-align
为百分比其参照是元素自身的 line-height
。
例如,一个元素的 line-height
是 30px,则 vertical-align: 10%
的效果是 vertical-align: 3px
。
尽管 vertical-align
可以使用数字,百分比值,但浏览器兼容性差异较大,所以不推荐使用数字和百分比。
bottom, left, right, top
这四个定位用的值是百分比时其参照是元素的包含块。left 和 right 是参照包含块的宽度,bottom 和 top 是参照包含块的高度。
transform: translate
平移变换,在水平方向和垂直方向上也可以使用百分比,其参照是变换的边界框的尺寸(等于这个元素自己的 border-box 尺寸)。
例如,一个宽度为 150px,高度为 100px 的元素,定义 transform:translate(50%, 50%)
的效果是 transform:translate(75px, 50px)
。另外,translate3d
对应是还有第三个维度的,但经过测试,最后的第 3 个值不可以使用百分比(否则样式定义无效)。
如果你想要知道更多的百分比值在 CSS 属性中的可用情况及参照值,请参考 MDN CSS percentage values。
百分比值的继承
当百分比值用于可继承属性时,只有结合参照元素计算后的绝对值会被继承,而不是百分比值本身。
例如,一个元素的 font-size
是 14px,并定义了 line-height:150%
,那么该元素的下一级子元素继承到的 line-height
就是 21px ,而不会再和子元素自己的 font-size
有关。