【面試必備】CSS盒模型的點點滴滴
從接觸CSS佈局開始,就一直在聽盒模型的概念了,網上的文章有很多,深淺不一。有些人會認為盒模型很簡單,不就是border、margin、padding、content嘛,一個元素所佔的空間就是把它們都加起來~僅僅如此嗎?當然不是,盒模型的概念其實挺好理解,但難的是與其他屬性一塊使用時產生的現象。下面把我知道的一些特性梳理一下,這也是css中最基礎的知識,面試常會問的東西。
盒模型的基本概念
正如上面說的,盒子模型的幾個要素就是border、margin、padding、content,相信你已經聽過很多次了,就像下面這張百看不厭的圖一樣:
不過要明確的是,這裡所說的盒子是指塊級(block-level)元素,行內元素有自己的一套標準,正如給行內元素設定margin-top無效一樣,不在這個盒子的討論範圍之內。本篇文章所說的盒子就是針對塊級元素。一個盒子其實是包含了四層,分別是content-box,padding-box,border-box,margin-box,它們的分界線就是上面畫出的那四個輪廓。這四個概念非常重要,後面我們要進行的各種邊界區分,就以它們為標準來討論。
一個盒子在沒有被定位時,即沒有加position也沒有float,在普通流中所佔的空間就是這些值的總和。即橫向空間為:marginLeft + borderLeftWidth + paddingLeft + width + paddingRight + borderRightWidth + marginRight,縱向的同理。
jQuery用多了,竟然忘記了如何用原生js來取這些值,所以在這裡也提一下。首先如果css樣式是寫在行內的,即元素的style屬性中,那麼直接通過element.style.marginLeft這樣就可以取到。如果樣式不在行內(通常情況都不在),通過style是無法取到的。IE和opera支援currentStyle屬性,可以取到定義在外部的樣式,其他瀏覽器則需要通過window.getComputedStyle來取,所以完整的獲取屬性的程式碼應該如下:
var element = document.getElementById(`id`); var currentStyle = null; if(element.currentStyle){ currentStyle = element.currentStyle; } else{ currentStyle = window.getComputedStyle(element); } console.log(currentStyle.marginTop);
寬度的計算
從簡單的開始,我們給一個盒子指定樣式width:100px,是給上述四層盒子的哪一層來指定的呢?是content-box,即最內層的內容區域。另外我們也知道,元素的寬度會被它的padding撐開,實際的寬度會是width + padding。那border會不會撐開元素的寬度呢?這個。。平時寫邊框大多數就是1個畫素寬,基本忽略了。。。其實border也是會撐開寬度的。那margin會不會呢?都是外邊距了,已經在盒子外頭了怎麼會撐開呢,少年你想多了~
這樣來看,光一個寬度就會有三種值,我們來舉個例子:
<style> #container{ position: relative; width: 400px; height: 400px; background-color: lightgreen; overflow:hidden; } #box1{ width: 100px; height: 100px; margin: 20px; padding: 20px; border:20px dotted; background-color: lightblue; } </style> <div id="container"> <div id="box1"></div> </div>
我這裡姑且把它們分別叫做“指定寬度”、“實際寬度”、“偏移寬度”。指定寬度就是css樣式中的width值,實際寬度是被padding撐開後的寬度,由clientWidth屬性可訪問到,偏移寬度是被border撐開後的寬度,由offsetWidth可以訪問到。這裡我又想到了jQuery,jq中有兩種方式可以取到元素的寬度,它們取到的是哪個值呢,來看一下:
var $width = $(`#box1`).width(); console.log($width);//100 var csswidth = $(`#box1`).css(`width`); console.log(csswidth);//100px
可以看到兩者都是取到了指定寬度,不同的是.width()返回一個數字100,可以直接參與數值運算。而.css(`width`)返回了字串100px。
上面是指定了寬度值的情況,如果不指定寬度的盒子是怎樣的呢?首先對於一個只有content-box的盒子,它會沾滿父元素的整行寬度,就像是指定了width:100%一樣,如下圖:
如果指定了margin值,那麼這個content-box的寬度就變成了父容器的寬度減去margin值,即除了外邊距剩下的寬度:
看來預設寬度挺好理解的,就是父容器減去margin值後剩餘的寬度,是能自適應的~
但情況遠不是這麼簡單。當元素有float屬性或position為absolute時,寬度就不是自適應的了,而是會收縮起來,包裹住內容。例如我給粉色區域加了position:absolute,就變成這樣了:
事實上,在給粉色元素加上display:inline-block時,也會收縮起來像上面一樣。inline-block的內容談起來也不是一篇文章能說清的,在本篇就不探討了。我們還是繼續聊寬度。
我們在進行自適應佈局時,會使用百分比作為寬度單位,這樣頁面可以適應不同大小的螢幕。然而我們常常還需要設定一些比較小的間距,我在看響應式設計那本書時作者建議無論多小的長度都使用百分比,即你可能會寫出這樣的css程式碼:margin-left:0.3212332%; 當然這數值你用計算器算下的,如果能除盡,你可以把小數位數全寫出來,儘管不好看,但可以保證精確。但總有除不盡的時候,當我們進行四捨五入的時候,有時候稍稍大了那麼一點,就會出現元素被擠到下一行的尷尬場面。這個時候你多麼希望,那5px的邊距直接寫成5px就好,再也不必計算什麼百分比。
囉嗦了這麼多,我其實就是想介紹一個css3的新特性而已。。。它就是calc,讓你的寬度值通過計算得出。最關鍵的時,它支援百分比和畫素混合計算,簡直太酷了,話不多說,上栗子:
#box3,#box4{ height: 100px; padding: 10px; background-color: orange; border:5px solid; float: left; } #box3{ width: 40%; } #box4{ width: 60%; } <div id="container"> <div id="box3">box3</div> <div id="box4">box4</div> </div>
在上面這種情況下,由於padding和border的存在,實際兩個div的寬度加起來要比100%大,所以box4就被擠到下一行了。下面我們來試試這個calc的威力,把box3和box4的寬度修改為:
#box3{
width: -webkit-calc(40% - 30px);
}
#box4{
width: -webkit-calc(60% - 30px);
}
這下就不會換行了。需要注意的是calc是css3的新屬性,現在支援度還不高,需要加私有字首使用。另外要注意的一點是,運算子號+-(加減)與數值之間一定要留有空格,否則會被認為是非法的取值。而*/(乘除)運算子則不需要。
background的覆蓋區域
設定背景色我們平時用的太多了,不知你是否注意過,元素的背景到底是以哪個區域為邊界的呢,border-box?padding-box?還是content-box?不著急回答,我們需要分兩種情況,設定背景色和背景圖片。
先說背景色,通過background-color設定的背景色總是填充滿border-box,我們用一個虛線框的元素就可以看出來,就像上面的box1一樣:
下面來看背景圖片的情況,通過background-image設定的背景圖片預設填充padding-box,看下面的程式碼:
<style> #box5{ width: 200px; height: 300px; margin: 20px; padding: 20px; border:30px dotted; background-image: url(http://images.cnblogs.com/cnblogs_com/lvdabao/507840/o_Img347406026.jpg); background-repeat: no-repeat; } </style> <div id="box5">box5</div>
左上方從padding-box的區域開始填充,右側和下側超出後會超到border-box的區域,但不會超到margin-box,這也是合理的。
在背景圖片中,我之所以說“預設”而不是“總是”,是因為現在我們可以通過background-origin來設定背景圖片的填充區域了,這是css3的一個新屬性,用於設定了background-repeat為no-repeat的元素。它的取值有三種:padding-box、border-box、content-box,分別指定背景圖片的填充區域。這三個值正好對應我前邊說的盒子模型的概念。效果你應該能想象到,我們來試一下吧:
border-box
padding-box
content-box
overflow:hidden;隱藏了哪裡?
我們都知道overflow:hidden;可以隱藏掉內容超出元素的部分,但是你有沒有細細探究過到底是超出哪裡的部分呢?具體來說就是,超出content-box被隱藏?超出padding-box被隱藏?還是超出border-box?通過下面的例子便可一探究竟:
<style> #box1{ width: 100px; height: 100px; margin: 20px; padding: 20px; border:20px dotted; background-color: lightblue; overflow: hidden; } #box1_1{ width: 200px; height: 200px; background-color: red; } </style> <div id="box1"> <div id="box1_1"></div> </div>
效果如下:
可以看到紅色盒子被隱藏掉了padding-box以外的部分,子元素的內容並不會延伸到父元素的邊框上,這也是符合常規邏輯的。
left/top的定位參照點
當給一個元素指定position:absolute;後,即絕對定位,便可以參照它的包含塊(containing block)進行定位。所謂包含塊就是指父級元素中最近的擁有定位屬性的元素,即position值不為static的元素。通過left和top值來指定相對包含塊的左上角的偏移距離。那麼這個“左上角”具體是指哪裡呢?是下面ABCD四個點中的哪一個?同樣,元素自己的點又是取哪一個呢?
通過下面的例子來探究一下:
<style> #container2{ position: relative; width: 400px; height: 400px; margin: 20px; padding:20px; border: 20px dotted; background-color: lightgreen; } #box6{ position: absolute; width: 100px; height: 100px; padding: 20px; border: 10px dotted; background-color: red; } </style> <div id="container2"> <div id="box6"></div> </div>
通過點選上面的按鈕,我們可以得出以下幾個結論:
- 元素自身的參照點是最外圍的盒子,即margin-box,如果沒有margin就以border-box,以此類推。
- left/top值為預設值(auto),元素還在原來的位置上,即緊貼父元素的content-box區域左上側。
- left/top指定值後,參照父元素的padding-box左上角,即我們上面圖中的C點。
取負值的情況
border、padding取負值都是非法的,而margin取負值是合法的,而且還大有所用。簡單來說,margin會影響元素的寬高,使元素往回“縮”一定的長度。看下面的例子:
<style> #box7,#box8{ width: 200px; height: 200px; background-color: red; border: 1px solid; } #box7{ background-color: green; margin-bottom: -100px; } </style> <div id="box7">box7</div> <div id="box8">box8</div>
儘管box7的高度指定為200px,但因為margin-bottom:-100px讓它縮回去100px,所以只剩100px的高度了。關於margin負值的應用場景非常的經典,我這裡就不一一列舉了,可參考瑤姐的這篇文章:http://blog.doyoe.com/~posts/css/2013-12-06-margin%E7%B3%BB%E5%88%97%E4%B9%8B%E5%86%85%E7%A7%80%E7%AF%87.md
BFC
BFC同樣也是盒模型中非常重要的一個概念,出於篇幅的原因,我不能詳細的解釋了,有一篇文章介紹的非常好,可參考http://blog.melonhuang.gitpress.org/~docs/css/1formattingContext.md
本文轉自呂大豹部落格園部落格,原文連結:http://www.cnblogs.com/lvdabao/p/3521680.html,如需轉載請自行聯絡原作者
相關文章
- css必備知識點CSS
- Redis 面試必備知識點Redis面試
- 前端面試2:CSS盒模型前端面試CSS模型
- 必備知識點 模型層ORM模型ORM
- CSS盒模型CSS模型
- css 盒模型CSS模型
- 【前端盲點】DOM事件流論證CSS盒模型是否具有厚度前端事件CSS模型
- 精通CSS盒模型CSS模型
- css之盒模型CSS模型
- CSS盒模型深入CSS模型
- css-盒模型CSS模型
- CSS的兩種盒模型CSS模型
- css&&js盒模型CSSJS模型
- CSS盒模型詳解CSS模型
- css3盒模型CSSS3模型
- 詳解CSS盒模型CSS模型
- 必備知識點 路由路由
- 必備知識點 模版
- Delphi入門點點滴滴
- 面試必知的web知識點面試Web
- Python工程師面試必備25條知識點Python工程師面試
- Vue中的點點滴滴在此記錄Vue
- 杭州找Android工作的點點滴滴Android
- css盒子模型與盒模型的浮動CSS模型
- Css規範整理:2、css盒模型CSS模型
- 前端必備知識點—SVG前端SVG
- 必備知識點 檢視
- Linux面試題-交換機/路由有哪些必備知識點?Linux面試題路由
- 前端面試之盒模型前端面試模型
- 東軟ACM題目的點點滴滴ACM
- CSS知識點面試總結CSS面試
- css&html面試知識點CSSHTML面試
- JVM知識點總覽:高階Java工程師面試必備JVMJava工程師面試
- CSS系列 (04):盒模型詳解CSS模型
- 第 16 章 CSS 盒模型[上]CSS模型
- 第 16 章 CSS 盒模型[下]CSS模型
- 面試必備知識點:悲觀鎖和樂觀鎖的那些事兒面試
- DBA七個必備知識點