【CSS深入】设置不同块级流方向时的属性百分比计算

uolcano

百分比在屏幕自适应是我们常用,但是很多时候某个CSS属性的百分比计算值,并非如我们所想象的那样子。前段时间有位同学分享了一篇关于margin/padding自适应布局的文章,看完后我去w3.org查了下marginpadding百分比计算的注意事项,描述如下:

Note that in a horizontal flow, percentages on ‘margin-top’ and ‘margin-bottom’ are relative to the width of the containing block, not the height (and in vertical flow, ‘margin-left’ and ‘margin-right’ are relative to the height, not the width).[1]

Note that percentages on ‘padding-top’ and ‘padding-bottom’ are relative to the width of the containing block, not the height (at least in a horizontal flow; in a vertical flow they are relative to the height).[2]

水平流?垂直流?那是甚么鬼?之前我一直不明白这两者何意,直到最近看CSS权威指南,讲到direction的时候提到了CSS Writing Modes Level 3里的writing-mode,查了官方文档后才知道,CSS3以后就有了定义内容书写方向的规范。


什么是块级流方向

块级流方向就是块级盒子在块级格式化上下文中以何种方向来进行顺序排列。这里要注意的一点是对于英文(也是简体中文)这种从上至下从左至右书写的语言,writing-modedirection分别会被默认设为horizontal-tbltr。简言之,块级流方向包含两种:一种是水平流,一种是垂直流。另外在CSS权威指南P171有提到,我们常见的margin的初始值是0,但是我们看到的大都是靠在左上方的,因为在英文语言的书写顺序、也就是块级流方向下,margin-rightmargin-bottom被默认强制设为auto了。如果不明白这些默认的强制格式化属性规范,很多时候我们做出来页面的效果可能会有点不合本意。这时我才渐渐意识到文本语言码识别lang和字符码识别charset在多语言情境下的重要性,另外关于FBC的内容还我也还未深入了解(这里挖个坑,以后填),请参看参考目录部分。

如何设置块级流方向

direction属性只是影响的行内类型内容的书写方向,而writing-mode则是可以直接影响块级元素的布局。horizontal-tb是我们常用页面的默认设定,决定了内容的水平方向书写和块级流方向的从上往下推进;vertical-rlvertical-lr则是部分语言的书写方向,这两个属性值决定了内容的垂直方向书写以及块级流方向分别是从右往左推进和从左往右的推进,比如,古汉字应用中最常见的是圣旨是从右向左推进、从上往下书写的,现代的日语也有这种格式的。

对百分比计算的影响

首先,先明确这里要讨论的是块级元素的水平流和垂直流对marginpaddingwidthheight的百分比属性值的计算值的影响。
然后,准备好测试代码(可以去我的github下找到ver_hor_flow.html和ver_hor_flow.css):

<div id="outer">test contet
    <div id="inner">test content</div>
</div>
#outer {
    background-color: fuchsia;
    height: 300px;
    width: 500px;
}
#inner {
    background-color: lime;
    margin: 1% 8% 2% 5%;
    padding: 1% 8% 2% 5%;
    height: 10%;
    width: 50%;
}

这里,我们对内部的子元素直接设置了宽高以便于,观察父元素容器的水平流和垂直流对子元素宽高的影响。但是如果不设置宽高,则子元素的宽高默认会是内容宽高,而内容高(垂直流中变成横向的了,以width衡量)由行高决定,而行高则在字体大小的基础上乘以一个浏览器默认的缩放因子来得到,字体大小也是有一个浏览器默认的计算值。比如我的浏览器默认是font-size:16px;以及line-height:21px;,这个21px是字体大小与一个缩放因子相乘后的结果,内容高度就是它了。Anyway,下面继续。

父元素容器水平流

对父元素,默认设置writing-mode: horizotal-tb;,水平流。
测试图:
clipboard.png
clipboard.png
margin-toppadding-top:500px乘以1%=5px
margin-rightpadding-right:500px乘以8%=40px
margin-bottompadding-bottom:500px乘以2%=10px
margin-leftpadding-left:500px乘以5%=25px
width:500px乘以50%=250px
height:300px乘以10%=30px
小结:可以看出,子元素marginpadding是以父元素的width为基数计算的,而子元素的widthheight是对应以父元素的widthheight为基数计算的。

父元素容器垂直流

对父元素设置writing-mode:vertical-lr;,垂直流。
测试图:
clipboard.png
clipboard.png
margin-toppadding-top:300px乘以1%=3px
margin-rightpadding-right:300px乘以8%=24px
margin-bottompadding-bottom:300px乘以2%=6px,这里margin-bottom的258px是因为我们设置了height:10%;,由于margin只是设置的最小值,一旦不足他会自动补上剩余的部分(300px-3px-3px-30px-6px=258px)。如果没设置height就会“正常”了。(这里要考虑到“过度受限”规则影响,也就是一个盒子的计算值相互矛盾的情况下,进行的一种“优先级”权衡。这里的自动补充计算值其实是因为对于水平流、从上往下推进的语言,实际上的margin-bottom会被强制设为auto,至于为何margin-right又正常呢?嗯,我也还在深入了解这个影响计算规则的“过度受限overconstrained”。)
margin-leftpadding-left:300px乘以5%=15px
width:500px乘以50%=250px
height:300px乘以10%=30px
小结:设置垂直流以后,marginpadding的百分比计算基数变成了父元素的高度(height:300px;),而子元素的widthheight的百分比计算仍然是对应以父元素的widthheight为基数计算的。
这里只测试了垂直流中从右向左推进时,各属性值的计算,另一种从左向右推进的各属性值计算结果是一样的,在此不赘述。

子元素垂直流

上面都是对作为容器的父元素进行块级流方向设置,如果只是对于子元素设置呢?
对内部的子元素设置writing-mode: vertical-lr;父元素不做其他设置,即默认。
clipboard.png
clipboard.png
小结:子元素的宽高和外边距、内边距都没有改变,也就是说子元素改变的块级流方向不影响本身marginpaddingwidthheight的计算值。

2D变形中旋转的影响

2D变形中有个rotate()函数可以扭转一个元素的摆放方向,那这个函数的设置会不会对子元素本身的marginpaddingwidthheight计算值造成影响呢?
设置transform:rotate(-90deg);
clipboard.png
clipboard.png
小结:变形只是改变了子元素的表现形式,但是并未改变子元素的百分比计算值。
--------------------------------------割----------------------------------
两天后,回过头看了下,这部分还要加个父元素的测试才算完整。不过结果是一样的:各属性的百分比数值计算并不受影响。我的Github上的测试代码,会同步更新。

边框不可设置百分比

查看边框的官方标准可知,边框不能设置百分比属性值,但是有相对属性值em、ex等,它们的计算都是以当前字体大小为基数。

box-sizing属性的影响

这个属性只会影响到设置widthheight后,内容区的大小,它对于外边距和内边距的计算不影响。

总结

在常用的盒模型百分比计算中,子元素的widthheight始终跟随父元素对应的宽高计算;而子元素的marginpadding则要考虑当前文档的块级流方向是水平流还是垂直流,如果是水平流,则以父元素的width为基数计算百分比,如果是垂直流则以父元素的height为基数计算百分比。单个子元素改变块级流方向以及设置变形都不改变父元素下子元素的块级流方向,不影响百分比计算。边框不可设置百分比。


参考

  1. 《CSS权威指南(第三版)》

  2. CSS basic box model

  3. CSS Writing Modes Level 3

  4. Visual formatting model

  5. 详说 Block Formatting Contexts (块级格式化上下文) | Kayo's Melody

阅读 5k

编程人生
努力提升自我专业能力,以期做出改善周边生活环境的产品和方案。
158 声望
36 粉丝
0 条评论
你知道吗?

158 声望
36 粉丝
宣传栏