本來按照正常的學習順序, 應該是HTML、CSS、JavaScript,再到Vue。但是到我這裡順序就反過來了一樣,先Vue 、再JavaScript,然後CSS。原因在於我之前就學習過這些,雖然當初學的不紮實,但是勉強能用,需要用到什麼,然後忘記了就重新再學習一下,這看起來像是逆生長一樣,但後面會將這個系列的文章補齊。
前言
在上海地鐵是大多數人的通勤方式,有的時候地鐵人多,就會很擁擠,那擁擠表達的意思是什麼呢? 我想是人與人之間的距離很小吧。如果將人視做html的元素,那麼人與人間的距離在在CSS中稱為margin,也被稱為外邊距。但是人和HTML的標籤還是有些區別,HTML的元素分塊級元素和行內元素、
塊級元素(Block-level elements)
那什麼是塊級元素? 簡單的說就是塊級元素佔滿一行,如下圖所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>This</p>
</body>
<style>
p {
background-color: #8ABB55;
}
</style>
</html>
效果圖:
雖然標籤p的內容只有一個this,但是當我們為它新增上背景色,你會發現整個一行都出現了綠色。細心的朋友執行程式碼之後可能會說也沒佔滿一行啊,旁邊還有兩個空白啊。那是因為我們寫的p標籤在body標籤裡面,body標籤是一個更大的盒子:
瀏覽器給body預設的margin大小是8個畫素, 我們可以透過瀏覽器的工具來驗證我們的論斷:
然後我們將body標籤的margin清空就會發現p標籤完全佔一整行:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>This</p>
</body>
<style>
p {
background-color: #8ABB55;
margin: 0px;
}
body{
margin: 0px;
}
</style>
</html>
所以塊級元素佔據其父元素的整個水平空間,高度等於其內容高度,像是一塊一樣,所以被稱為塊級元素。所以兩個塊級元素不能位於一行,預設情況下在塊級元素之後,再寫塊級元素,塊級元素會新起一行。以下是HTML中所有的塊級元素列表:
- address article aside blockquote dd div
- dl fieldset figcaption figure footer h1-h6 form
- header hgroup hr ol p pre section table ul
行內元素
那我們可以類比塊級元素對行內元素下定義,塊級元素佔據一行,那行內元素就是隻佔據它對應標籤的邊框所包含的空間:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>This <span>span</span> is an inline element; its background has been colored to display both the beginning and end of the inline element's influence</p>
</body>
<style>
span { background-color: #8ABB55; }
</style>
</html>
一般情況下,行內元素只能包含資料和其他行內元素。而塊級元素可以包含行內元素和其他塊級元素。預設情況下,行內元素不會以新行開始,而塊級元素會新起一行。下面的元素都是行內元素:
- b, big,i,samll,tt。
- abbr,acronym,cite,code,dfn,em,kbd,strong,samp,var。
- a,bdp,br,img,object,q,script,span,sub,sup
- button,input,label,select,textarea。
盒子模型
但內容之間通常有距離還往往不夠用,就像一幅畫一樣,我們為了保護這幅畫通常會買一個畫框,通常畫框會比要裝的畫大一些,起到留白的效果:
當然也有padding(padding為0)的,瀏覽器的渲染引擎會根據標準之一的CSS基礎盒模型(CSS basic box model),將所有的元素表示為一個個矩形的盒子(box)。根據網頁中宣告的CSS,來決定這些盒子的大小、位置、以及屬性(例如顏色、背景、邊框尺寸)。每個盒子都由四個部分來組成,如上面的圖片所示,每個盒子有四個組成區域
- 內容區域 content area:容納著元素的“真實內容”,例如文字、影像。它的尺寸為內容寬度和內容高度。通常含有一個背景顏色或背景影像。
如果box-sizing 這個屬性為預設屬性即content-box,則內容區域可以透過明確的width、min-width、max-width、height、min-height,和max-height控制。
- 內邊距區域 padding area: 擴充套件內容區域,間距的大小可以透過明確的padding-top、padding-right、padding-bottom、padding-left和簡寫屬性padding來控制。
- 邊框區域 border area: 擴充套件內邊距區域,是容納邊框的區域,邊框的粗細由border-width和簡寫的border屬性控制,如果boder-sizing屬性被設定為border-box。那border區域的大小可以明確透過width、min-width, max-width、height、min-height,和 max-height 屬性控制。假如框盒上設有(background-color 或 background-image),背景將會一直延伸至邊框的外沿(預設為在邊框下層延伸,邊框會蓋在背景上)。此預設表現可透過 CSS 屬性 background-clip 來改變。
- 外邊距區域 margin area: 即盒子與盒子的距離,外邊距的大小由 margin-top、margin-right、margin-bottom、margin-left,和簡寫屬性 margin 控制。在發生外邊距合併的情況下,由於盒之間共享外邊距,外邊距不容易弄清楚。
上面我們提到的就屬於盒子模型,一般我們稱之為標準盒模型。在標準盒模型中,如果你給盒子本身設定width和height,實際上設定的是content box,即內容的長寬高。padding和border再加上設定的寬高一起決定盒子的大小。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>This</p>
</body>
<style>
p {
background-color: #8ABB55;
margin: 10px;
width: 200px;
padding: 10px;
border-width:10px;
border-style: solid;
border-color: blue;
}
body{
margin: 0px;
}
</style>
</html>
實際效果:
IE盒子模型
某些時候標準盒子模型也讓我們產生困擾,難道我們我們不能直接設定整個盒子的寬高嗎? 還要加上border和padding,這很麻煩。IE模型中,內容寬度是設定的寬度減去邊框和填充部分。一般情況下瀏覽器採用的都是標準模型,如果需要使用IE模型,可以透過設定box-sizing: border-box來實現。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>This</p>
</body>
<style>
p {
box-sizing: border-box;
background-color: #8ABB55;
margin: 10px;
width: 200px;
padding: 10px;
border-width:10px;
border-style: solid;
border-color: blue;
}
body{
margin: 0px;
}
</style>
</html>
如果你希望所有元素都使用IE盒子模型,那我們可以將box-sizing在html元素上,然後設定所有元素繼承該屬性,如下面程式碼所示:
html {
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
}
IE瀏覽器預設使用IE盒子模型,不支援切換標準盒子模型(IE8+ 支援使用box-sizing進行切換)
塊級盒子和內聯盒子
HTML中元素分為塊級元素和行級元素,在CSS中盒子也分為塊級盒子和內聯盒子。塊級盒子由塊級元素產生,內聯盒子由行內元素產生。塊級元素會表現出以下行為:
- 盒子會在內聯方向擴充套件並佔據父容器在該方向上所有可用空間,在絕大多數情況下意味著盒子會和父容器一樣寬。
- 塊級盒子不能並列,每個盒子獨佔一行。
- width和height屬性可以發揮作用
- 內邊距(padding), 外邊距(margin)和邊框(border)會將其他元素從當前盒子周圍推開。
除非特殊指定,注入標題h1等和段落在預設情況下都是塊級的盒子。我們可以透過display屬性來將當前元素設定為塊級元素或內聯元素。display常見的屬性有:
- block: 將當前盒子設定為塊級盒子
- inline: 將當前盒子設定為內聯盒子
- inline-block: 我們有的時候會希望元素具備寬度和高度屬性,但是有具備同行特性。在這種情況下就要可以使用inline-box。
如果一個盒子為內聯盒子,那麼這個盒子具備以下性質:
- 盒子不會換行
- width和height屬性不起作用
- 垂直方向的內邊距(padding)、外邊距(margin)以及邊框(border)會被應用但是不會把其他處於
inline
狀態的盒子推開。 - 水平方向的內邊距、外邊距以及邊框會被應用且會把其他處於
inline
狀態的盒子推開。
用做連結的 <a>
元素、 <span>
、 <em>
以及 <strong>
都是預設處於 inline
狀態的。
我們可以透過display屬性的設定,比如inline或者block,來控制盒子的外部顯示型別。那麼有外部顯示型別,就會有內部顯示型別。外部顯示型別決定盒子是塊級還是內聯,而內部顯示型別則決定盒子內部元素是如何佈局的。預設情況下和其他塊元素以及內聯元素一樣。但是我們也可以透過使用flex的display屬性值來更改內部顯示型別。如果設定display:flex,在一個元素上,外部顯示類型別是block,但是內部顯示型別修改為flex。該盒子的所有直接子元素都會變成flex元素,會根據彈性盒子flexbox 規則進行佈局,我們會在後文介紹這些內容。
塊級和內聯佈局是web上的預設行為,有的時候,他們也被稱為正常文件流。
外邊距
外邊距是盒子周圍一圈看不到的空間。它會把其他元素從盒子旁邊推開。外邊距屬性值可以為正,也可以為負。設定負值會導致和其他內容重疊。無論使用標準模型還是替代模型,外邊距總是在計算可見部分後額外新增。我們可以使用margin屬性一次控制一個元素的所有邊距,或者每邊單獨使用等價的普通屬性控制:
- margin-top
- margin-right
- margin-bottom
- margin-left
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="container">
<div class="box">Change my margin.</div>
</div>
</body>
<style>
.box {
margin-top: -40px;
margin-right: 30px;
margin-bottom: 40px;
margin-left: 4em;
border: 5px solid rebeccapurple;
background-color: lightgray;
padding: 10px;
height: 150px;
}
.container {
border: 5px solid blue;
margin: 40px;
}
</style>
</html>
嘗試更改外邊距的值,感受一下在外邊距設定為正時是如何推開周邊元素,以及設定為負時是如歌重疊的。
外邊距摺疊
理解外邊距的一個關鍵是外邊距摺疊概念,如歌你有兩個外邊距相接的元素,這些外邊距將合併為一個外邊距,即最大的單個外邊距的大小。在下面的例子中,我們有個兩個p標籤,第一個標籤的margin-bottom為50px。第二段的margin-top為30px。因為外邊距摺疊的概念,所以框之間的實際外邊距是50px,而不是兩個外邊距的總和。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="container">
<p class="one">I am paragraph one.</p>
<p class="two">I am paragraph two.</p>
</div>
</body>
<style>
.container {
border: 5px solid blue;
margin: 100px;
}
p {
border: 5px solid rebeccapurple;
background-color: lightgray;
padding: 10px;
}
.one {
margin-bottom: 50px;
}
.two {
margin-top: 30px;
}
</style>
</html>
可以嘗試修改一下.two的margin-top,只要小於50px,兩者的距離不會發生變化,當大於五十的時候按.two的摺疊。
內邊距
內邊距位於邊框和內容區域之間。與外邊距不同,不可以設定負值。應用於元素的任何背景色都將顯示在內邊距中。我們可以使用padding簡寫屬性控制元素所有邊,或者每邊單獨使用等價的普通屬性:
- padding-top
- padding-right
- padding-bottom
- padding-left
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="container">
<div class="box"> 改內邊距</div>
</div>
</body>
<style>
.container {
border: 5px solid blue;
margin: 40px;
padding: 20px;
}
.box {
padding-top: 40px;
padding-right: 20px;
padding-bottom: 40px;
padding-left: 4em;
border: 5px solid rebeccapurple;
background-color: lightgray;
}
</style>
</html>
邊框
相對於內邊距和外邊距,邊框的屬性很多,可以設定邊框的寬度、邊框顏色,邊框樣式(邊框是虛線 還是直線)。上面的例子我們已經有意無意的用過了:
border: 5px solid blue;
這是為四個邊框統一設定寬度、樣式、顏色。我們也可以分別設定四個邊框的寬度、樣式、顏色:
- border-top
- border-right
- border-bottom
- border-left
設定所有邊的寬度、樣式、顏色也可以這麼宣告:
- border-width
- border-style
- border-color
我們也可以單獨設定每個邊的寬度、樣式、顏色:
- border-top-width
- border-top-style
- border-top-color
- border-right-width
- border-right-style
- border-right-color
- border-bottom-width
- border-bottom-style
- border-bottom-color
- border-left-width
- border-left-style
- border-left-color
總結一下
盒子模型類似於搬家之後對東西進行重新擺放,這也被稱為佈局,如果房子小,margin就會小就會顯得很擁擠。一個良好的佈局會讓居住者賞心悅目。本篇基本參考了《千古前端圖文教程》,《MDN web docs》。這裡用我自己的方式將這些內容整合了一下。注意JavaFX我們前面寫的文章也會有這樣的佈局問題,兩者是通用的。
參考資料
- 千古前端圖文教程 https://web.qianguyihao.com/0...
- mdn web docs https://developer.mozilla.org...
- CSS 中的眾多盒子概念怎麼區分? https://www.zhihu.com/questio...