羅嗦的開頭
早上感覺不對勁,一睜眼就發(fā)現(xiàn)媳婦趴在我身上,她告訴我她的手機找不到了問我看沒看到。我去啊~我剛睡醒誰特么知道你手機丟哪里去了?我就直接告訴她我沒看到,而且我剛睡醒怎么可能知道。我又告訴她是不是早上上廁所了放廁所了,而且昨天晚上她是玩手機玩睡著的。這樣看來,手機在廁所的幾率是30%,手機在臥室的幾率是70%。不過她非說是我藏起來的。我欲哭無淚啊,我說你再無理取鬧我就不理你了。就算你用白花花的大美腿來誘惑我也沒用。就像下面這張圖一樣。

說什么都不行,媳婦不依不饒,我算是無奈了。不過還好最后在床下面找到了。我看了看表才特么6點鐘,這娘們這么早爬起來第一反應就是看自己的手機。算是沒救了……不過她竟然在我申辯之后竟然不相信自己的老公,也著實可惡。我要處罰她……
不過,仔細想想。百分比這種方式在我們的日常生活中還是比較常見的。例如我百分百沒有×××,你百分百×××,某某百分百是×××等等。在我們的工作學習中百分比的形式更是多見。CSS中有些屬性的值存在百分比的形式的,今天就來做個總結把這些屬性百分比的知識加深下理解。
width和height
在頁面中很多元素都是可以設置width和height的。設置可能值的形式中也包含百分比。在早期網(wǎng)頁設計中使用table經(jīng)行布局時,為了保證表格能響應內(nèi)容的變化,很多人都會使用百分比的值來渲染table。后來經(jīng)過技術的演化迭代,table布局逐漸沒落,div+css開始興起。給width和height設置固定的PX成為主流。百分比table的形式榮光不再,但偉大的想法總會是卷土重來。再后來移動客戶端興起,響應式布局也隨著開始火起來。百分比也就是解決響應視口變化的不二法門。DIV+CSS、百分比形式再加上@media三者的結合有稱霸前端的趨勢。當然現(xiàn)在似乎更前沿的是css中的flex布局,這個有機會再聊。
前面說了這么多,其實width和height設置百分比還是很容易被理解的,就是參照物是父元素。例如width:50%就是說元素的寬度是父元素寬度的50%,height:30%就是高度是父元素高度的30%。這個沒什么要特別說的,就是對應父元素的屬性值進行百分比計算,width對width;height對height。看下面的圖就能理解。

margin和padding
margin和padding的百分比是個比較難以理解的屬性。當然它也是相對于父元素來計算自己百分比的值的,不過計算方式有點奇葩,它們是基于父元素的寬度(width)來進行計算的。margin-left/margin-right和padding-left/padding-right基于父元素寬度還好理解,奇葩點就是margin-top/margin-bottom和padding-top/padding-bottom的百分比也是基于父元素的寬度來計算的。什么個情況?難道不是width和height的計算方法啊?

上面的圖中可以清晰的看出來實際渲染結果卻是是按照父元素寬度的百分比來設置的。margin-top:10%;的實際渲染結果50px;padding-top:1%;的實際渲染效果是5px,它們都是根據(jù)父元素的寬度width:500px;產(chǎn)生的計算結果。這個試驗印證了:子元素邊距和填充距的值設為百分比,那么它的計算方式就是根據(jù)父元素的寬度(width)來進行計算的。另外提一下的是,在上面的圖中可以看到我在父元素設置了一個overflow:hidden;的聲明。這個是為了防止margin collapsing的出現(xiàn)。關于margin collapsing的詳細介紹出門右轉在我的文章《淺析讓人D疼的margin折疊》中有說明。
嗯!奇葩的百分比,我也跟著奇葩了。我竟然不說原理直接上實驗結果了。酒香不怕巷子深,這點小小的“奇葩”不耽誤我們理解這個知識點。從相應的官方文檔《8.3 Margin properties》也能看到相應的說明。下面引用相應關于margin的資料。
The percentage is calculated with respect to the width of the generated box’s containing block. Note that this is true for ‘margin-top’ and ‘margin-bottom’ as well. If the containing block’s width depends on this element, then the resulting layout is undefined in CSS 2.1.
蹩腳的翻譯:該百分比相對于設置元素的包含塊的寬度計算。如果包含塊的寬度取決于此元素,那么在CSS 2.1中的結果布局是未定義的。
然后這里是引用相應關于padding的資料,它來自于《5. The padding properties》。
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).Note that percentages are not required for CSS level 2.
蹩腳的翻譯:注意“padding-top”和“padding-bottom”的百分比與包含塊的寬度有關,而不是高度(至少在水平流中),在垂直流中它們與高度相對應。CSS level2不需要百分比。
問題來了,為什么是基于寬度來計算呢?
這是因為我們的“閱讀模式”導致的,我們都是“從左向右逐字,由上到下逐行”的閱讀習慣,這種模式也就決定了寬度必須是固定的,而高度是可以無限擴展的。在一個高度可以隨時擴展且是無限的容器內(nèi),百分比的計算結果就會不固定,這個有悖于我們的“排版、布局”的設計初衷,頁面元素變的不容易可控。
所以依據(jù)寬度固定的計算結果能更好的控制“設計結果”。其實這是西方的閱讀方式,我們中國的傳統(tǒng)閱讀習慣是“從上到下逐字,從右向左逐列”的模式,沒辦法誰讓這玩意是人家發(fā)明的呢。
如果使用屬性writing-mode改變文本流的方向變成垂直流的話,那么這個計算方式就不是依據(jù)父元素的寬度了,而是依據(jù)復原度的高度。因為在垂直文本流中,高度變成固定而寬度變成了可以無限擴展。這個介紹到這里差不多了,繼續(xù)下一個。
position
position是個大寶貝兒,不管是position:absolute;還是position: relative;使用方位都非常廣。關于兩者的區(qū)別不再過多啰嗦,這篇文章只關于百分比的問題。設置完畢position之后可以根據(jù)top/right/bottom/left屬性的值來對元素進行定位,它們的取值形式中也還有百分比。關于百分比是和誰有關呢?先買個關子。我們先來建立一個概念,讓我們的腦海中有個“逆Y軸坐標”——自己胡亂起的名字,別較真~

有了這個圖之后,再理解top/right/bottom/left屬性的百分比值就容易許多。說白了其實還是與父元素的width和height屬性有關。從圖上可以知道top就是和父元素height有關,其他的幾個屬性的百分比計算也是一樣,都是通過父元素來確定自己的值的。
需要注意的是top/right/bottom/left屬性在同方向上只能有一個屬性有效,例如設置了top再去設置bottom就會無效,設置了right再去設置left就會無效。如果四個同時設置,只會生效兩個。他們的權重是上大于下,左大于右,意思是同時設置上下,那么上生效。同時設置左右,左生效。
而且在設置不同的組合,相當于原點來計算的元素頂點位置也是不一樣的。具體情況如圖:

常用的就這些了,不過還沒完嘿嘿嘿~

盒模型影響
上面所有的情況都是在常規(guī)盒模型下的結果。也就是box-sizing: content-box;時的結果。如果修改為怪異盒模型即box-sizing: border-box;之后,計算方式?jīng)]有變,該與誰有關就與誰有關。可是計算結果會多出一步來,就是需要減去border和padding的值。
因為在標準盒模型下,寬和高的值就是固定的,是不包含border和padding的。而怪異盒模型下的寬和高是包含border和padding的值的。換句話說:在標準盒模型下,百分比的計算和寬高的值有關,拿來直接計算;在怪異盒模型下,百分比的計算是和容器真實大小有關(寬高 減去 margin-padding=真實大?。?/strong>關于盒模型的概念在我的文章《盒模型與box-sizing》中很詳細的說明。
舉個例子就能驗證下我的說法是否正確。點擊進入“栗子”
如果我的心算沒有錯,橙色塊的width:80px;height:15px;,我要快點閃了,沒時間貼驗證圖了。自己可以進入瀏覽器調試模式,選中橙色的塊看下我的心算結果對不對。我閃了,88~
