盒模型
1. 文件流(normalflow)
網頁是一個多層的結構,一層摁著一層
通過CSS可以分別為每一層來設定樣式,作為使用者來講只能看到最頂上一層
這些層中,最底下的一層稱為文件流
文件流是網頁的基礎我們所建立的元素預設都是在文件流中進行排列
對於我們來元素主要有兩個狀態
- 在文件流中
- 不在文件流中(脫離文件流)
那麼元素在文件流中有什麼特點,我們接著往下看
2. 塊元素
- 塊元素會在頁面中獨佔一行
- 預設寬度是父元素的全部(會把父元素撐滿)
- 預設高度是被內容撐開(子元素)
3. 行內元素
- 行內元素不會獨佔頁面的一行,只佔自身的大小
- 行內元素在頁面中左向右水平排列(書寫習慣一致)
- 如果一行之中不能容納下所有的行內元素,則元素會換到第二行繼續自左向右排列
- 行內元素的預設寬度和高度都是被內容撐開
4. 盒子模型
網頁設計中常聽的屬性名:內容(content)、內邊距(padding)、邊框(border)、外邊距(margin), CSS盒子模型都具備這些屬性。
這些屬性我們可以用日常生活中的常見事物——盒子作一個比喻來理解,所以叫它盒子模型。
CSS盒子模型就是在網頁設計中經常用到的CSS技術所使用的一種思維模型。[1]
盒模型、盒子模型、框模型(box model)
CSS將頁面中的所有元素都設定為了一個矩形的盒子
將元素設定為矩形的盒子後,對頁面的佈局就變成將不同的盒子擺放到不同的位置
每一個盒子都由一下幾個部分組成:
- 內容區(content)
- 內邊距(padding)
- 邊框(border)
- 外邊距(margin)
內容區(content)
內容區是盒子模型的中心,它呈現了盒子的主要資訊內容,這些內容可以是文字、圖片等多種型別
元素中的所有的子元素和文字內容都在內容區中
width和height
設定排列內容區的大小width
設定內容區的寬度height
設定內容區的高度
示例
.box1{
width: 200px;
height: 200px;
background-color: #bfa;
}
效果
邊框(border)
邊框屬於盒子邊緣,邊框裡邊屬於盒子內部,出了邊框都是盒子的外部
注意:邊框的大小會影響到整個盒子的大小
border-width
邊框的寬度:預設3pxborder-top-width
上邊框的寬度border-right-width
右邊框的寬度border-bottom-width
下邊框的寬度border-left-width
左邊框的寬度
border-color
邊框的顏色:預設使用color的顏色值border-top-color
上邊框的顏色border-right-color
右邊框的顏色border-bottom-color
下邊框的顏色border-left-color
左邊框的顏色border-style
邊框的樣式:沒有預設值,必須指定border-top-style
上邊框的樣式border-right-style
右邊框的樣式border-bottom-style
下邊框的樣式border-left-style
左邊框的樣式
示例
.box1{
border-width: 10px;
border-color: red;
/*
solid 實線
dotted 點狀虛線
dashed 虛線
double 雙線
*/
border-style: solid;
}
效果(solid)
效果(dotted)
效果(dashed)
效果(double)
不論是border-width
、 border-color
、border-style
還是其衍生出來的屬性寫法,都可以指定每個方向的邊框情況
設定幾個值就決定了對應方向的寬度、顏色或樣式
- 四個值:
上 右 下 左
- 三個值:
上 左右 下
- 兩個值:
上下 左右
- 一個值:
上下左右
其實不管設定幾個值,只要記住:其順序是按順時針方向設定的,剩下的可以由矩形的對稱性推匯出來
border
:簡寫屬性,通過該屬性可以同時設定邊框所有的相關樣式,並且沒有順序要求
border-top
上邊框的寬度、顏色和樣式border-right
右邊框的寬度、顏色和樣式border-bottom
下邊框的寬度、顏色和樣式border-left
左邊框的寬度、顏色和樣式
.box1{
border: 10px red solid;
}
內邊距(padding)
內邊距,也叫填充,是內容區和邊框之間的空間
padding-top
上內邊距padding-right
右內邊距padding-bottom
下內邊距padding-left
左內邊距
padding內邊距的簡寫屬性,可以同時指定四個方向的內邊距,規則和邊框中屬性值設定一樣
注意:內邊距的設定會影響到盒子的大小,背景顏色會延伸到內邊距上
示例
<style>
.outer{
width: 200px;
height: 200px;
border: 10px orange solid;
padding-right: 100px;
padding-bottom: 100px;
padding-left: 100px;
}
.inner {
width: 200px;
height: 200px;
background-color: greenyellow;
}
</style>
<div class="outer">
<div class="inner"></div>
</div>
效果
可以看出,當內外div寬度和高度一樣時,由於outer設定了一個padding屬性,其盒子大小被“撐大了”
盒子可見框的大小,由內容區、內邊距和邊框共同決定,所以在計算盒子大小時,需要將這三個區域加到一起計算
外邊距(margin)
外邊距,也叫空白邊,位於盒子的最外圍,是新增在邊框外周圍的空間。空白邊使盒子之間不會緊湊地連線在一起,是CSS 佈局的一個重要手段
注意:外邊距不會影響盒子可見框的大小,但是外邊距會影響盒子的位置和佔用空間
一共有四個方向的外邊距:
margin-top
上外邊距- 設定正值,元素自身向下移動
- 設定負值,元素自身向上移動
margin-right
右外邊距- 設定正值,其右邊的元素向右移動
- 設定負值,其右邊的元素向左移動
- 上述說法並不準確,對於塊元素,設定
margin-right
不會產生任何效果
margin-bottom
下外邊距- 設定正值,其下邊的元素向下移動
- 設定負值,其下邊的元素向上移動
- 上述說法並不準確,對於塊元素,會有垂直方向上的邊距重疊問題(後面會細說)
margin-left
左外邊距- 設定正值,元素自身向右移動
- 設定負值,元素自身向左移動
元素在頁面中是按照自左向右的順序排列的,所以預設情況下
- 如果我們設定的左和上外邊距則會移動元素自身
- 而設定下和右外邊距會移動其他元素
示例1
.box1 {
width: 200px;
height: 200px;
background-color: #bfa;
border: 10px orange solid;
margin-top: 100px;
margin-right: 100px;
margin-bottom: 100px;
margin-left: 100px;
}
效果
示例2
.box1 {
width: 200px;
height: 200px;
background-color: #bfa;
border: 10px orange solid;
margin-bottom: 100px;
}
.box2 {
width: 200px;
height: 200px;
background-color: #bfa;
border: 10px red solid;
margin-top: 100px;
}
效果
5. 水平方向佈局
元素在其父元素中水平方向的位置由以下幾個屬性共同決定
margin-left
border-left
padding-left
width
padding-right
border-right
margin-right
一個元素在其父元素中,水平佈局必須要滿足以下的等式
margin-left + border-left + padding-left + width + padding-right + border-right + margin-right = 其父元素的寬度
以上等式必須滿足,如果相加結果使等式不成立,則稱為過渡約束
則等式會自動調整調整的情況:
-
如果這七個值中沒有
auto
的情況,則瀏覽器會自動調整margin-right
值以使等式滿足100 + 0 + 0 + 200 + 0 + 0 + 0 = 800
==>100 + 0 + 0 + 200 + 0 + 0 + 500 = 800
-
如果這七個值中有
auto
的情況,則會自動調整auto
值以使等式成立這七個值中有三個值可以設定為
auto
:width
、margin-left
、maring-right
-
如果某個值為auto,則會自動調整
auto
的那個值以使等式成立
200 + 0 + 0 + auto + 0 + 0 + 200 = 600
==>200 + 0 + 0 + 400 + 0 + 0 + 200 = 800
auto + 0 + 0 + 200 + 0 + 0 + 200 = 600
==>400 + 0 + 0 + 200 + 0 + 0 + 200 = 800
200 + 0 + 0 + 200 + 0 + 0 + auto = 600
==>200 + 0 + 0 + 200 + 0 + 0 + 400 = 800
-
如果寬度為
auto
,則寬度會調整到最大,其他auto
的外邊距會自動設定為0auto + 0 + 0 + auto + 0 + 0 + 200 = 600
==>0 + 0 + 0 + 600 + 0 + 0 + 200 = 800
200 + 0 + 0 + auto + 0 + 0 + auto = 600
==>200 + 0 + 0 + 600 + 0 + 0 + 0 = 800
auto + 0 + 0 + auto + 0 + 0 + auto = 600
==>0 + 0 + 0 + 800 + 0 + 0 + 0 = 800
-
如果外邊距都為
auto
,則auto
的外邊距會自動均分以使等式成立auto + 0 + 0 + 200 + 0 + 0 + auto = 600
==>300 + 0 + 0 + 200 + 0 + 0 + 300 = 800
-
示例
<style>
.box1 {
width: 200px;
height: 200px;
background-color: #bfa;
border: 10px orange solid;
/* 下列條件等價於 margin: 0 auto */
margin-left: auto;
margin-right: auto;
}
</style>
<div class="box1"></div>
效果
6. 垂直方向佈局
元素溢位
子元素是在父元素的內容區中排列的,如果子元素的大小超過了父元素,則子元素會從父元素中溢位
使用overflow
/overflow-x
/overflow-y
屬性來設定父元素如何處理溢位的子元素
可選值:visible
/hidden
/scroll
/auto
visible
溢位內容會在父元素外部位置顯示,預設值
示例
<style>
.box1 {
width: 200px;
height: 200px;
background-color: #bfa;
border: 10px orange solid;
overflow: visible; /* 預設值 */
}
</style>
<div class="box1">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores aspernatur illo inventore
deleniti laudantium quaerat excepturi sed quidem tempore? Eaque, cumque porro. Fuga quam error cupiditate quasi
eveniet in numquam!
</div>
效果
hidden
溢位內容會被裁剪,不會顯示
示例
<style>
.box1 {
width: 200px;
height: 200px;
background-color: #bfa;
overflow: hidden; /* 隱藏溢位內容 */
}
</style>
<div class="box1">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores aspernatur illo inventore
deleniti laudantium quaerat excepturi sed quidem tempore? Eaque, cumque porro. Fuga quam error cupiditate quasi
eveniet in numquam!
</div>
效果
scroll
生成兩個滾動條,通過滾動條來檢視完整的內容
示例
<style>
.box1 {
width: 200px;
height: 200px;
background-color: #bfa;
overflow: scroll;
}
</style>
<div class="box1">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores aspernatur illo inventore
deleniti laudantium quaerat excepturi sed quidem tempore? Eaque, cumque porro. Fuga quam error cupiditate quasi
eveniet in numquam!
</div>
效果
auto
根據需要生成滾動條
示例
<style>
.box1 {
width: 200px;
height: 200px;
background-color: #bfa;
overflow: auto;
}
</style>
<div class="box1">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores aspernatur illo inventore
deleniti laudantium quaerat excepturi sed quidem tempore? Eaque, cumque porro. Fuga quam error cupiditate quasi
eveniet in numquam!
</div>
效果
邊距摺疊
垂直外邊距的重疊(摺疊):相鄰的垂直方向外邊距會發生重疊現象
兄弟元素
兄弟元素間的相鄰,垂直外邊距會取兩者之間的較大值(兩者都是正值)
特殊情況:
- 如果相鄰的外邊距一正一負,則取兩者的和
- 如果相鄰的外邊距都是負值,則取兩者中絕對值較大的
示例
.box1,.box2{
width:200px;
height:200px;
font-size:100px;
}
.boxl{
background-color: #bfa;
/*設定一個下外邊距*/
margin-bottom: 100px;
}
.box2{
background-color: orange;
/*設定一個上外邊距*/
margin-top: 100px;
}
效果
疑問
當瀏覽器縮放比例是100%時,我們使用FastStone Capture工具自帶的刻度尺測量,發現“兄弟”之間似乎沒有我們想象的那麼“親近”
兩者的垂直方向間距是125px,我們明明上下元素設定的都是100px啊,這是為什麼呢?
在網頁佈局中,通過谷歌瀏覽器或火狐瀏覽器預覽時,發現我們定義的盒模型width,height,margin,padding 值都是不準確的
谷歌、火狐瀏覽器 縮放為80% 時,margin值才正確[2]
總結
兄弟元素之間的外邊距的重疊,對於開發是有利的,所以我們不需要進行處理
父子元素
父子元素間相鄰外邊距,子元素會傳遞給父元素(上外邊距)
示例
.box3{
width:200px;
height:200px;
background-color: #bfa;
}
.box4{
width: 100px;
height: 100px;
background-color: orange;
/* margin-top: 100px; */
}
效果
父子外邊距的摺疊會影響到頁面的佈局,必須要進行處理
處理方式1
1、我們轉換思路,將對子元素的調整轉為對父元素的調整
.box3 {
width: 200px;
height: 200px;
background-color: #bfa;
padding-top: 100px; /* 不調整子元素的margin,而是轉而調整父元素的padding */
}
.box4 {
width: 100px;
height: 100px;
background-color: orange;
/* margin-top: 100px; */
}
效果
可以看到父元素位置雖然正確了,但是高度卻被“撐大了”。我們之前說過,padding屬性會影響元素的大小
2、這裡我們還需要計算並手動調整下父元素的高度
.box3 {
width: 200px;
height: 100px; /* height: 200px; */
background-color: #bfa;
padding-top: 100px;
}
.box4 {
width: 100px;
height: 100px;
background-color: orange;
}
效果
處理方式2
1、我們仍然保留子元素的margin-top
屬性,但是給父元素加一個上邊框
.box3 {
width: 200px;
height: 200px;
background-color: #bfa;
border-top: 1px rebeccapurple solid; /* 在父元素上加一個border-top(上邊框) */
}
.box4 {
width: 100px;
height: 100px;
background-color: orange;
margin-top: 100px; /* 不刪除,保留 */
}
效果
2、但是因為加了1px的邊框,所以父元素盒子的高度也增加了1px。那我們就需要手動調整父元素的高度,同時讓邊框顏色與父元素盒子顏色保持一致
.box3 {
width: 200px;
height: 199px; /* height: 200px; */
background-color: #bfa;
border-top: 1px #bfa solid;
}
.box4 {
width: 100px;
height: 100px;
background-color: orange;
margin-top: 100px;
}
但是我們沒有發現一個問題不難發現一個問題,子元素也往下移動了1px的距離
因為父元素高度少了1px,而子元素的margin-top是從邊框下面開始算的
所以,憑藉大家樸素的情感,哪個應該怎麼判? 應該怎麼改?
改法也很簡單,margin-top減去一個畫素即可
.box3 {
width: 200px;
height: 199px;
background-color: #bfa;
border-top: 1px #bfa solid;
}
.box4 {
width: 100px;
height: 100px;
background-color: orange;
margin-top: 99px; /* margin-top: 100px; */
}
效果
同時,我們用刻度尺測量,父子元素底部是在一條水平線上的
脫離文件流
上述示例2中,使用了border屬性,就讓子元素的外邊距不去傳遞給父元素了,這是為什麼呢?
margin (子元素遠離父元素邊框)[3]
如果父盒子沒有設定border框著,那麼他的子元素無法利用margin-top 來遠離父元素的上邊框
如果使用了margin-top會使子元素和父元素一起往下移
(子想離,父不設定border邊框 則離得是流 不是父盒子)
應該是border讓元素脫離了文件流(margin塌陷)
好吧好吧,至於什麼是margin塌陷,我也是問了度娘,有興趣的可以自行百度,這裡就不再贅述了
7. 行內元素的盒模型
-
行內元素不支援設定寬度和高度
.s1 { /* 行內元素設定了寬高也沒用,不會生效 */ width: 100px; height: 100px; background-color: yellow; }
-
行內元素可以設定
padding
,但是垂直方向padding
不會影響頁面的佈局.s1 { /* 下方的div元素並沒有因span設定了padding屬性,而受到位置上的影響 */ padding: 100px; background-color: yellow; } .box1 { width: 200px; height: 200px; background-color: #bfa; }
-
行內元素可以設定
border
,垂直方向的border
不會影響頁面的佈局.s1 { border: 10px orange solid; background-color: yellow; } .box1 { width: 200px; height: 200px; background-color: #bfa; }
-
行內元素可以設定
margin
,垂直方向的margin
不會影響頁面的佈局.s1 { margin: 100px; background-color: yellow; } .box1 { width: 200px; height: 200px; background-color: #bfa; }
如果我就是想要行內元素對頁面佈局產生影響呢?
那就拉出去槍斃了! 那也是有辦法的!
display
用來設定元素顯示的型別
-
inline
將元素設定為行內元素 -
block
將元素設定為塊元素.s1 { margin: 100px; background-color: yellow; /* 將行內元素設定為塊元素 */ display: block; }
-
inline-block
將元素設定為行內塊元素行內塊,既可以設定寬度和高度又不會獨佔一行.s1 { margin: 100px; background-color: yellow; /* 將行內元素設定為行內塊元素,兼顧行內元素和塊元素的特點 */ display: inline-block; }
-
table
將元素設定為一個表格 -
none
元素不在頁面中顯示.s1 { margin: 100px; background-color: yellow; /* 將行內元素設定為none:不顯示 */ display: none; }
不顯示是不顯示了,但是原來屬於s1的位置也沒了
visibility
用來設定元素的顯示狀態
-
visible
預設值,元素在頁面中正常顯示 -
hidden
元素在頁面中隱藏不顯示,但是依然佔據頁面的位置.s1 { margin: 100px; background-color: yellow; display: block; visibility: hidden; }
8. 瀏覽器的預設樣式
通常情況,瀏覽器都會為元素設定一些預設樣式
預設樣式的存在會影響到頁面的佈局,通常情況下編寫網頁時必須要去除瀏覽器的預設樣式(PC端的頁面)
在當今網頁設計/開發實踐中,使用CSS來為語義化的(X)HTML標記新增樣式風格是重要的關鍵。
在設計師們的夢想中都存在著這樣的一個完美世界:所有的瀏覽器都能夠理解和適用多有CSS規則,並且呈現相同的視覺效果(沒有相容性問題)。
但是,我們並沒有生活在這個完美的世界,現實中發生的失竊卻總是恰恰相反,很多CSS樣式在不同的瀏覽器中有著不同的解釋和呈現。
當今流行的瀏覽器(如:Firefox、Opera、Internet Explorer、Chrome、Safari等等)中,有一些都是以自己的方式去理解CSS規範,這就會導致有的瀏覽器對CSS的解釋與設計師的CSS定義初衷相沖突,使得網頁的樣子在某些瀏覽器下能正確按照設計師的想法顯示
而且有些瀏覽器卻並沒有按照設計師想要的樣子顯示出來,這就導致瀏覽器的相容性問題。
更糟的是,有的瀏覽器完全無視CSS的一些宣告和屬性。[4]
我們可以嘗試編寫css樣式,以去除瀏覽器的預設樣式
示例
html程式碼
<div class="box1"></div>
<p>我是一個段落</p>
<p>我是一個段落</p>
<p>我是一個段落</p>
<ul>
<1i>列表項1</1i>
<1i>列表項2</1i>
<1i>列表項3</1i>
</ul>
css程式碼
.box1{
width: 100px;
height: 100px;
border: 1px solid black;
}
效果
F12看盒子預設樣式
-
段落之間有16px的預設行距
-
列表外有16px的上下外邊距和40px的左內邊距,而且每項列表前有一個小黑點
去除預設樣式
-
去除與瀏覽器的邊緣間距
body { margin: 0; }
-
去除段落之間行距
p { margin: 0; }
-
去除列表的上下外邊距和左內邊距
ul { margin: 0; padding: 0; }
我們只是去除了列表的內外邊距,但是發現前面的黑點也消失了,真的如此嗎?
我們先給
ul
加上一個margin-left
ul { margin: 0; padding: 0; margin-left: 16px; }
看來黑點並沒有自動清除,而只是“縮排”了瀏覽器的左側
-
去除列表前的黑點
ul { margin: 0; padding: 0; margin-left: 16px; list-style: none; }
再將之前加的16px的
margin-left
樣式去除ul { margin: 0; padding: 0; /* margin-left: 16px; */ list-style: none; }
到這裡似乎就大功告成了,但是我們會發現寫法似乎
很完美有點麻煩body { margin: 0; } p { margin: 0; } ul { margin: 0; padding: 0; list-style: none; }
有沒有簡化空間了呢?
答案是肯定的,我們前面介紹過通配選擇器的概念,可以直接簡化成一個
-
簡化寫法
* { margin: 0; padding: 0; list-style: none; }
效果是一樣的
去除瀏覽器的預設樣式的需求是非常普遍的,我們難道每次都需要手動去除瀏覽器的預設樣式?
這樣豈不是很麻煩,難道官方就沒有想到解決方案嗎?
答案也是肯定的,有!
正因為上述衝突和問題依然存在於這個”不完美的世界”,所以一些設計師想到了一種避免瀏覽器相容性問題的方法,那就是CSS Reset
什麼是CSS Reset?
我們可以把它叫做CSS重設,也有人叫做CSS復位、預設CSS、CSS重置等。
CSS重設就是先定義好一些CSS樣式,來讓所有瀏覽器都按照同樣的規則解釋CSS,這樣就能避免發生這種問題。[4:1]
下方兩種css樣式,我們引入其中一個即可
reset樣式
官方地址:reset.css
<link rel="stylesheet" href="assets/reset.css">
效果
我們可以看到reset.css的作用就是將各個內外邊距置為0,將一些樣式置為none
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
normalize樣式
官方地址:normalize.css
<link rel="stylesheet" href="assets/normalize.css">
效果
這裡並沒有去除所有樣式,因為normalize的作用不同於reset。reset是將所有預設樣式去除,而normalize是將所有預設樣式統一,這樣在不同的瀏覽器裡顯示效果也是統一的
至於檔案內容就不再這裡贅述了,感興趣的可以仔細研究
參考資料
CSS盒子模型:https://baike.baidu.com/item/CSS盒子模型/9814562?fr=aladdin ↩︎
谷歌、火狐瀏覽器 縮放為80% 時,margin值才正確:https://www.cnblogs.com/taohuaya/p/7642742.html ↩︎
margin(子元素遠離父元素邊框):https://www.cnblogs.com/FlFtFw/p/9627026.html ↩︎
目前比較全的CSS重設(reset)方法總結:https://www.cnblogs.com/hnyei/archive/2011/10/04/2198779.html ↩︎ ↩︎