百分比在屏幕自適應是咱們經常使用,可是不少時候某個CSS屬性的百分比計算值,並不是如咱們所想象的那樣子。前段時間有位同窗分享了一篇關於margin/padding自適應佈局的文章,看完後我去w3.org查了下margin
和padding
百分比計算的注意事項,描述以下:css
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]html
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]css3
水平流?垂直流?那是甚麼鬼?以前我一直不明白這二者何意,直到最近看CSS權威指南,講到direction
的時候提到了CSS Writing Modes Level 3裏的writing-mode
,查了官方文檔後才知道,CSS3之後就有了定義內容書寫方向的規範。git
塊級流方向就是塊級盒子在塊級格式化上下文中以何種方向來進行順序排列。這裏要注意的一點是對於英文(也是簡體中文)這種從上至下從左至右書寫的語言,writing-mode
和direction
分別會被默認設爲horizontal-tb
和ltr
。簡言之,塊級流方向包含兩種:一種是水平流,一種是垂直流。另外在CSS權威指南P171有提到,咱們常見的margin
的初始值是0,可是咱們看到的大都是靠在左上方的,由於在英文語言的書寫順序、也就是塊級流方向下,margin-right
和margin-bottom
被默認強制設爲auto了。若是不明白這些默認的強制格式化屬性規範,不少時候咱們作出來頁面的效果可能會有點不合本意。這時我才漸漸意識到文本語言碼識別lang
和字符碼識別charset
在多語言情境下的重要性,另外關於FBC的內容還我也還未深刻了解(這裏挖個坑,之後填),請參看參考目錄部分。github
direction
屬性只是影響的行內類型內容的書寫方向,而writing-mode
則是能夠直接影響塊級元素的佈局。horizontal-tb
是咱們經常使用頁面的默認設定,決定了內容的水平方向書寫和塊級流方向的從上往下推動;vertical-rl
和vertical-lr
則是部分語言的書寫方向,這兩個屬性值決定了內容的垂直方向書寫以及塊級流方向分別是從右往左推動和從左往右的推動,好比,古漢字應用中最多見的是聖旨是從右向左推動、從上往下書寫的,現代的日語也有這種格式的。segmentfault
首先,先明確這裏要討論的是塊級元素的水平流和垂直流對margin
、padding
、width
、height
的百分比屬性值的計算值的影響。
而後,準備好測試代碼(能夠去個人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;
,水平流。
測試圖:margin-top
和padding-top
:500px乘以1%=5pxmargin-right
和padding-right
:500px乘以8%=40pxmargin-bottom
和padding-bottom
:500px乘以2%=10pxmargin-left
和padding-left
:500px乘以5%=25pxwidth
:500px乘以50%=250pxheight
:300px乘以10%=30px
小結:能夠看出,子元素margin
和padding
是以父元素的width
爲基數計算的,而子元素的width
和height
是對應以父元素的width
和height
爲基數計算的。佈局
對父元素設置writing-mode:vertical-lr;
,垂直流。
測試圖:margin-top
和padding-top
:300px乘以1%=3pxmargin-right
和padding-right
:300px乘以8%=24pxmargin-bottom
和padding-bottom
:300px乘以2%=6px,這裏margin-bottom
的258px是由於咱們設置了height:10%;
,因爲margin
只是設置的最小值,一旦不足他會自動補上剩餘的部分(300px-3px-3px-30px-6px=258px)。若是沒設置height
就會「正常」了。(這裏要考慮到「過分受限」規則影響,也就是一個盒子的計算值相互矛盾的狀況下,進行的一種「優先級」權衡。這裏的自動補充計算值實際上是由於對於水平流、從上往下推動的語言,實際上的margin-bottom
會被強制設爲auto,至於爲什麼margin-right又正常呢?嗯,我也還在深刻了解這個影響計算規則的「過分受限overconstrained」。)margin-left
和padding-left
:300px乘以5%=15pxwidth
:500px乘以50%=250pxheight
:300px乘以10%=30px
小結:設置垂直流之後,margin
和padding
的百分比計算基數變成了父元素的高度(height:300px;
),而子元素的width
和height
的百分比計算仍然是對應以父元素的width
和height
爲基數計算的。
這裏只測試了垂直流中從右向左推動時,各屬性值的計算,另外一種從左向右推動的各屬性值計算結果是同樣的,在此不贅述。測試
上面都是對做爲容器的父元素進行塊級流方向設置,若是隻是對於子元素設置呢?
對內部的子元素設置writing-mode: vertical-lr;
父元素不作其餘設置,即默認。
小結:子元素的寬高和外邊距、內邊距都沒有改變,也就是說子元素改變的塊級流方向不影響自己margin
、padding
、width
、height
的計算值。
2D變形中有個rotate()
函數能夠扭轉一個元素的擺放方向,那這個函數的設置會不會對子元素自己的margin
、padding
、width
、height
計算值形成影響呢?
設置transform:rotate(-90deg);
小結:變形只是改變了子元素的表現形式,可是並未改變子元素的百分比計算值。
--------------------------------------割----------------------------------
兩天後,回過頭看了下,這部分還要加個父元素的測試纔算完整。不過結果是同樣的:各屬性的百分比數值計算並不受影響。個人Github上的測試代碼,會同步更新。
查看邊框的官方標準可知,邊框不能設置百分比屬性值,可是有相對屬性值em、ex等,它們的計算都是以當前字體大小爲基數。
box-sizing
屬性的影響這個屬性只會影響到設置width
和height
後,內容區的大小,它對於外邊距和內邊距的計算不影響。
在經常使用的盒模型百分比計算中,子元素的width
和height
始終跟隨父元素對應的寬高計算;而子元素的margin
和padding
則要考慮當前文檔的塊級流方向是水平流仍是垂直流,若是是水平流,則以父元素的width
爲基數計算百分比,若是是垂直流則以父元素的height
爲基數計算百分比。單個子元素改變塊級流方向以及設置變形都不改變父元素下子元素的塊級流方向,不影響百分比計算。邊框不可設置百分比。