現在我們已經熟悉了HTML和CSS。瞭解了它的基礎。現在我們來更深入的瞭解元素在頁面中的呈現和大小。
在這節課中,我們將會討論什麼是盒子模型,它的工作模式是怎樣的。我們也會在課程中學習一些新的CSS屬性,並且將介紹三種長度單位。
元素是如何顯示的
在瞭解盒子模型之前,我們先來了解一下元素是如何顯示的。在第二節課中,我們學習了塊狀元素和內聯元素的差異。快速回顧一下,塊狀元素會另起一行,並佔據所有可用的寬度,不管內容有沒有。而內聯元素會並排顯示,寬度緊隨內容變化而變化。塊狀元素通常用在大塊的內容上,例如標題,結構元素。內聯元素用在小塊的內容上,比如將幾句話加粗或斜體顯示。
display屬性
元素如何顯示——例如塊狀元素,內聯元素和其他元素——都由顯示屬性display
決定。每個元素都有一個預設的display
屬性值。和其他屬性值一樣,這個屬性值是可以被覆蓋的。display
值有很多,其中最常用的是block
,inline
,line-block
和none
。
我們可以通過CSS選中元素並改變和重新宣告元素的display
屬性值。 若值為block
可以使元素成為塊狀元素顯示。
p {
display: block;
}複製程式碼
將值設定為inline
,可以將元素轉化為內聯元素。
p {
display: inline;
}複製程式碼
inline-block
比較有意思,它可以使元素的所有塊狀元素的屬性生效。但元素又按照內聯元素顯示,不會另起一行。
p {
display: inline-block;
}複製程式碼
inline-block
內嵌塊元素有個重要的點,就是它們並非是首尾相接的。兩個內嵌塊元素之間存在小空隙。這個空隙雖然很惱人,但這是正常現象。我們會討論為什麼這個空隙存在,以及怎麼消除。
最後是none
屬性值,會完全隱藏元素,頁面渲染的時候會當它不存在。任何被包裹在這個屬性值元素內的元素都會被隱藏。
div {
display: none;
}複製程式碼
瞭解元素如何顯示,以及怎麼修改display
屬性非常重要,因為它會影響盒子模型的呈現效果。討論盒子模型的時候,我們會知道他們之間的差別,意義和影響。
什麼是盒子模型?
根據盒子模型的概念,每個在頁面上的元素都是一個擁有寬,高,內邊距,邊框和外邊距的長方形盒子。
頁面上每個元素都符合盒子模型的定義,所以它非常重要。我們使用一些新的CSS屬性來來熟悉它。
使用盒子模型
每個元素都是一個長方形盒子,有幾個屬效能確定這個盒子的大小。盒子的核心屬性是元素的寬高,這兩個值可能是由元素的display
屬性、元素的內容或具體的width
,height
屬性值生成的。內邊距padding
和邊框border
擴充了元素的高寬。最後是我們定義的在邊框外的外邊距margin
。
盒子模型對應的CSS屬性為:width
,height
,padding
,border
,margin
。
我們來看例子:
div {
border: 6px solid #949599;
height: 100px;
margin: 20px;
padding: 20px;
width: 400px;
}複製程式碼
根據盒子模型,元素的總寬度計算如下:
margin-right + border-right + padding-right + width + padding-left + border-left + margin-left複製程式碼
使用上述公式,就能算出示例中的高寬值
- Width:492px = 20px + 6px + 20px + 400px + 20px + 6px + 20px
- Height:192px = 20px + 6px + 20px + 100px + 20px + 6px + 20px
毫無疑問盒子模型是HTML和CSS很容易混淆的部分之一。
我們將width
的值設定為400
畫素,但元素的實際寬度為492
畫素。預設情況下,盒子模型是加法。因此想要確定盒子的實際大小,我們需要考慮將四面的內邊距,邊框,外邊距都考慮進去。寬度不僅僅是width
屬性的值,也要加上左右兩側的內邊距,邊框和外邊距。
到目前為止,上述屬性看著沒什麼實際意義。因為這只是為了澄清所有形成盒子模型的屬性:width
,height
,padding
,border
和 margin
。
寬度和高度
每個元素都有預設的高度和寬度。雖然寬度和高度都有可能是0
畫素,但預設情況下,瀏覽器會渲染每個元素的大小。元素的預設寬度和高度依賴於元素是怎麼顯示的。如果元素是頁面佈局的關鍵元素。那麼它就需要設定具體的width
和height
屬性值。這種情況下,只能指定非內聯元素的屬性值。
寬度
元素的預設寬度依賴於它display
屬性的值。塊狀元素的預設寬度為100%
,佔據整行空間。內聯元素和內嵌塊元素的寬度都隨著元素的內容變化而變化。內聯元素不具備固定的大小,所以width
和height
屬性只有在非內聯元素上才能生效。如下是為非內聯元素設定寬度的例子:
div {
width: 400px;
}複製程式碼
高度
元素的預設高度取決於它的內容。元素根據內容需要進行垂直擴充套件或收縮。我們可以使用height
屬性為非內聯元素設定高度:
div {
height: 100px;
}複製程式碼
調整內聯元素
請記住內聯元素不支援width
和height
屬性和與其相關的值。塊狀元素和內嵌塊元素支援width
和height
屬性和與其對應的值。
外邊距和內邊距
瀏覽器會根據元素設定其預設的外邊距和內邊距,使其更清晰易讀。我們使用基於文字的元素來看一下這個現象。不同瀏覽器和不同元素之間的預設外邊距和內邊距可能存在差異。我們在第一課中有討論過CSS重置,將這些差別調低,或使其為零。這樣我們就可以從頭開始定義我們需要的樣式。
外邊距
margin
屬性設定一個元素的周圍空間大小。外邊距在元素邊框外並且是完全透明的。外邊距可以幫助我們將元素定位在頁面的特定位置,並且可以與其他元素保持距離。 示例如下:
div {
margin: 20px;
}複製程式碼
margin
有一個特殊的現象,就是在內聯元素中垂直外邊距margin-top
和margin-bottom
不生效,在塊狀元素和內嵌塊元素中有效。
內邊距
padding
屬性和margin
屬性相似,只不過它在邊框內部,padding
是為元素提供內部空間。示例如下:
div {
padding: 20px;
}複製程式碼
padding
屬性和margin
屬性不一致的地方是垂直內邊距在內聯元素中同樣有效;雖然垂直內邊距顯示在元素基準線之上或之下,但是它確實是存在的。
內聯元素的外邊距和內邊距
內聯元素對內邊距和外邊距的實現和塊狀元素與內嵌塊元素不同。外邊距只有橫向margin-left
和margin-right
有效。內邊距在內聯元素中完全生效,但是垂直內邊距padding-top
和padding-bottom
在元素基準線上面或下面顯示(譯者注:內聯元素加上垂直內邊距之後,元素內部的內容部分在視覺上沒有產生偏移)。
塊狀元素和內嵌塊元素的外邊距和內邊距的顯示是正常的。
外邊距和內邊距的宣告方式
在CSS中,很多屬性都有多種宣告方法。普通的寫法,就是一個屬性一個值,一個個地列出來。但我們也可以使用簡寫,一個屬性包含多個值。不是所有的屬性都有簡寫,所以我們必須確保寫出的屬性和值的結構是正確的。
margin
和padding
有普通和簡寫兩種書寫方式。當元素四面設定相同的外邊距時,可以使用margin
屬性,並只指定一個值:
div {
margin: 20px;
}複製程式碼
如果上下外邊距的值一致,左右外邊距的值一致,我們可以輸入兩個值。 設定上下外邊距的值在前面。以下例子將上下外邊距設定為10
畫素,將左右外邊距設定為20
畫素:
div {
margin: 10px 20px;
}複製程式碼
如果四個值都不一致,那麼我們按照 上右下左 的順序輸入值。例如,我們為div
設定10
畫素的頂部外邊距,20
畫素的右側外邊距,0
畫素的底部外邊距,以及15
畫素的左側外邊距:
div {
margin: 10px 20px 0 15px;
}複製程式碼
若我們要設定多個值,優先考慮用margin
和padding
。但我們也可以用普通寫法,輸入一一對應的屬性和值。每個屬性名(該例子中是外邊距和內邊距)後跟隨一個破折號-
以及要設定值的盒子的方向:top
,bottom
,right
和left
。
例如,padding-left
屬性只接受一個值,設定元素的左側內邊距;margin-top
只接受一個值,設定元素的頂部外邊距。
div {
margin-top: 10px;
padding-left: 6px;
}複製程式碼
當我們只想設定單邊的margin
和padding
值時,這種普通寫法是最好的選擇。保持程式碼的精確性可以防止出現混淆。例如,我們是否只想將元素的上右左三側的外邊距設為0
,是否只想將底部外邊距設為10
畫素?
普通寫法輸入屬性和值可以讓目標更明確。當處理三個或以上的值時,縮寫更有幫助。
外邊距和內邊距的顏色margin
和padding
屬性是完全透明的,不可以設定顏色。但因為是透明的,所以透出了相關元素的背景色。元素外邊距部分看到的顏色為它父級元素的背景色。元素內邊距部分看到的顏色為該元素的背景色。
邊框
邊框在內邊距和外邊距之間,畫出了元素輪廓。border
屬性要求三個值:寬度,樣式,顏色。邊框屬性簡寫時值的順序為:寬度,樣式,顏色。普通書寫方式下,邊框的三個屬性名為:border-width
,border-style
和border-color
。普通書寫方式因為是單個值,更容易修改和複寫。
邊框的寬度和顏色能分別使用第三節課中討論過的長度單位和色值。
邊框有很多不同樣式。最常用的樣式值為solid
,dashed
,dotted
和none
,但你可以在列表中看到很多其他的樣式。
以下是邊框設定示例:
div {
border: 6px solid #949599;
}複製程式碼
單側邊框
和margin
,padding
屬性一樣,也可以一次只設定元素一個方向的邊框。使用屬性名:border-top
, border-right
,border-bottom
和border-left
。它們的屬性值和border
的屬性值一樣有三個:寬度,樣式和顏色。如下所示:
div {
border-bottom: 6px solid #949599;
}複製程式碼
另外,單側邊框的樣式也可以被細分,如下所示:
div {
border-bottom-width: 12px;
}複製程式碼
這些高度細分的邊框屬性名都由連字元分隔,由border單詞開頭,隨後是邊框的方向:top
,right
,bottom
,left
,最後是要設定的樣式:width
,style
,color
。
border-radius
border-radius
可以使元素的邊角變圓。
border-radius
接受多種長度單位,如百分比,畫素,確定元素邊角變圓的半徑。單個值表示四個角的弧度一直,兩個值按分別表示top-left
/bottom-right
和top-right
/bottom-left
,輸入四個值按順序分別表示:top-left
,top-right
,bottom-right
和bottom-left
。
思考border-radius
多個值的順序時(包括margin
和padding
),記住它們是從左上角開始(margin
和padding
從上側開始)按順時針方向排序的。
div {
border-radius: 5px;
}複製程式碼
border-radius
屬性也允許我們使用普通方法書寫單個屬性值。這些普通的屬性以border
單詞開通,跟著是邊角的垂直位置(top
或bottom
),再是邊角的橫向位置(left
或right
),最後是半徑radius
。例如,要設定<div>
右上角的邊角半徑,可以使用border-top-right-radius
屬性:
div {
border-top-right-radius: 5px;
}複製程式碼
box-sizing
現在,在盒子模型中有一個附加屬性。如果你設定了元素的width
為400
畫素,並將padding
設定為20
畫素,將border
設定為10
畫素,那麼實際的盒子寬度為460
畫素。記住,盒子的寬度是width
,padding
和border
相加獲得的。
但是在CSS3中,盒子模型有了一個不一樣的計算方式。CSS3推出了box-sizing
屬性,完全改變了盒子模型的運作模式和元素大小的計算方式。這個屬性有三個主要值——content-box
,padding-box
和 border-box
——每個值對盒子模型大小的計算稍微有些不一樣。
content-box
content-box
這個屬性值是預設值。這個預設值和元素不加box-sizing
屬性時的效果是一致的。元素從width
和height
屬性的值開始計算,加上padding
,border
和margin
屬性值獲得盒子的實際尺寸。
div {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}複製程式碼
上例中box-sizing
屬性前的連字元和字母是什麼?
CSS3的推出後,瀏覽器逐步開始以加字首的方式支援新屬性和值,包括box-sizing
屬性。隨著部分CSS規範被瀏覽器廣泛支援以及瀏覽器版本的更新,字首的作用也越來越小,隨著時間的發展將不再是一個問題。但在老版本瀏覽器中還是不可或缺的。
屬性名和屬性值都可以新增字首。例如,上例中的box-sizing
屬性名加了字首。瀏覽器可以選擇什麼時候加字首什麼時候不加字首,因此有些屬性需要帶有某瀏覽器的字首,有些屬性不需要。
接下來的課程中,若某個屬性或值需要字首,只會在介紹那個屬性時新增使用(這有利於保持程式碼的簡潔)。不過你們在實際寫程式碼的時候不要忘記新增字首。
最常見的幾個瀏覽器字首概括如下:
- Mozilla的火狐瀏覽器:
-moz-
- 微軟的IE瀏覽器:
-ms-
- Webkit(谷歌的Chrome瀏覽器和蘋果的Safari瀏覽器):
-webkit-
padding-box
屬性值padding-box
時,元素將padding
屬性值計算入width
和height
屬性值內,改變了盒子模型計算模式。例如,元素的width
設定為400
畫素,padding
值設為20
畫素,最終元素實際的寬度還是400
畫素。隨著內邊距的擴大,元素的內容區域會隨著縮小,但是盒子實際大小並未發生改變。
如果我們增加border
或margin
,那麼盒子的大小就是這些屬性值加上width
和height
的值。例如,我們將元素的的width
設定為400
畫素,每個方向的border
都設定為10
畫素,padding
設定為20
畫素,那麼元素的實際寬度就為420
畫素。
div {
box-sizing: padding-box;
}複製程式碼
隨著CSS規範的更新,box-sizing
的值padding-box
已被棄用,我們不應再使用它。
Border Box
最後一個屬性值是border-box
,它將border
和padding
都算在元素的width
和height
屬性值內。例如,一個元素的width
為400
畫素,每邊的padding
為20
畫素,border
為10
畫素,最終元素的實際寬度仍然為400
畫素。
若我們還增加了margin
屬性,在獲取盒子總大小時它的值需要做加法計算。不管box-sizing
的屬性值是什麼, 計算盒子總大小時任何margin
的值都需要做加法計入。
div {
box-sizing: border-box;
}複製程式碼
使用box-sizing屬性
通常來說,box-sizing
最佳屬性值為border-box
,這個屬性值更易計算。如果我們將一個元素的width
為400
畫素,那麼不管你增加了邊框還是內邊距,它的大小都還是400
畫素。
另外,我們也可以輕鬆的相對值。如果我們設定一個元素的寬度為40%
,元素每邊的padding
值為20
畫素,border
值為10
畫素。那麼儘管有地方設定了畫素值,元素盒子的實際大小仍然為40%
。
唯一遺憾的是box-sizing
是CSS3的屬性,並不是所有瀏覽器都支援,尤其是老版本瀏覽器。所幸隨著瀏覽器版本更新,影響會越來越小。我們使用box-sizing
的時候,需要留意哪些瀏覽器會出現相容問題。
開發者工具
大多數瀏覽器都有開發者工具。我們可以使用這些工具檢視頁面上的元素、這些元素的HTML結構
和CSS屬性及它們值。它們大部分都有盒子模型圖解。
在Chrome瀏覽器中開啟選單欄,找到“更多工具”選項中的“開發者工具”選項並點選它,瀏覽器視窗的底部會顯示出一個視窗,其中提供了一些程式碼檢查工具。
懸停或點選視窗中的元素節點,可以檢視這個元素的資訊。
選中一個元素後,在視窗右側選中“Computed”選項,我們就可以看到我們選中的元素的盒子模型。
Chrome, Firefox,Safari以及其他瀏覽器中都有開發者工具。檢視原始碼可以學到很多東西。我在編寫HTML和CSS的時候通常都會開啟開發者工具,也常常用它檢視分析其他網站的原始碼。
練習
現在我們回到之前做的“樣式討論會”網站,並未它新增更多的內容。
- 首先,在
main.css
檔案中新增一個box-sizing
屬性,值設定為border-box
,這樣可以使我們的元素更容易控制。在檔案的頁面重置樣式下,新增一條註釋,有助於網站佈局。把它放在樣式重置程式碼之下,是使其放在正確的層疊關係上。
在這裡,我們可以使用萬用字元選擇器*
,後面跟隨帶偽元素的選擇器*:before
和*:after
,這樣就可以選中頁面中所有的元素,將其box-sizing
值設定為border-box
。請記住,box-sizing
是有字首的,因為它是一個較新的屬性。
/*
========================================
Grid
========================================
*/
*,
*:before,
*:after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}複製程式碼
- 接下來我們要建立一個可以作為我們元素容器的class屬性。用它在不同的元素上設定共同的
width
,padding
屬性,並將元素居中。 在我們萬用字元選擇器下,建立一個新的class選擇器名為container
。在選擇器中將width
設定為960
畫素,padding-left
和padding-right
設定為30
畫素,上下外邊距設定為0
,左右外邊距設為auto
。container
告訴瀏覽器所有使用了這選擇器的元素的寬度。左右外邊距值設為auto
,再加之設好的寬度值,可以讓瀏覽器自動計算出左右相等的外邊距,元素就相對於頁面居中了。最後設定左右內邊距,使內容不緊貼元於素的邊緣,為內容提供一點喘息的空間。
.container {
margin: 0 auto;
padding-left: 30px;
padding-right: 30px;
width: 960px;
}複製程式碼
- 現在
container
已經可以使用,我們把它新增到所有頁面的<header>
和<footer>
元素上,所有頁面包括index.html
,speakers.html
,schedule.html
,venue.html
以及register.html
頁面。
<header class="container">...</header>
<footer class="container">...</footer>複製程式碼
- 接下來,我們將
container
新增到介紹會議的<session>
元素和包含<section>
作為子元素的`元素上。
<section class="container">...</section>複製程式碼
- 另外,也將
container
新增到其他頁面中包含有<h1>
元素的<section>
元素上。
<section class="container">
<h1>...</h1>
</section>複製程式碼
- 稍後我們還會再回來調整這些元素和class屬性。現在我們先做另一件事。
- 現在我們的內容已經居中顯示,接下來為元素建立縱向的間隔。我們先把標題和段落的底部外邊距設定為
22
畫素。我們將這個排版樣式以及它的註釋放在之前的容器樣式之下。
/*
========================================
Typography
========================================
*/
h1, h3, h4, h5, p {
margin-bottom: 22px;
}複製程式碼
- 我們在此跳過了
<h2>
和<h6>
元素,因為設計中<h2>
不需要外邊距,<h6>
這次我們不會用到。 - 現在我們在頁面第一個
<section>
的底部放置一個按鈕,併為其設定邊框和圓角。
我們先新增一個<a>
元素,並將其的class屬性值設為btn
和btn-alt
.
<a class="btn btn-alt">...</a>複製程式碼
- 接下來我們在排版樣式之下為這兩個屬性值新增樣式。
- 首先建立一個能被所有按鈕共享的樣式的class選擇器
btn
。我們希望所有的按鈕的border-radius
為5
畫素,display
為inline-block
,並移除所有外邊距。
/*
========================================
Buttons
========================================
*/
.btn {
border-radius: 5px;
display: inline-block;
margin: 0;
}複製程式碼
- 我們使用
btn-alt
為當前按鈕設定特殊的樣式。我們增加1畫素的灰色邊框,並且設定上下內邊距為10
畫素,左右內邊距為30
畫素
.btn-alt {
border: 1px solid #dfe2e5;
padding: 10px 30px;
}複製程式碼
- 我們在同一
<a>
元素中使用了btn
和btn-alt
,那麼相應的樣式都會渲染上去。 - 在主頁上,我們為包含上述
<a>
元素的<section>
元素設定padding
樣式。我們通過在其上新增一個class屬性值hero
來實現。
<section class="hero container">
...
</section>複製程式碼
- 最後,我們在CSS檔案分隔出一塊專門設定主頁的樣式,然後
hero
新增padding
屬性。
/*
========================================
Home
========================================
*/
.hero {
padding: 22px 80px 66px 80px;
}複製程式碼
現在我們的網站更加完整了,尤其是主頁。
在此練習的第一步,我們提到了萬用字元選擇器*
,它會選中所有的元素。相比於一一列出所有能想到的單個元素,不如使用它來選中所有的元素。
我們也在第一步中提到了偽元素:before
和:before
,它們可以在CSS中動態生成元素。我們不會當前專案中使用它。不過在萬用字元選擇器中使用偽元素是很常用的做法。
演示原始碼
這是練習的原始碼。點選下載
總結
休息一下我們再繼續。
將盒子模型所有內容學完並不容易。這些概念雖然只是簡單介紹,卻花了很多時間來掌握它。
這節課所學內容概括如下:
- 元素是如何顯示的
- 什麼是盒子模型,它為什麼很重要
- 怎麼修改元素的大小,包括寬度和高度
- 怎麼新增元素的外邊距,內邊距和邊框
- 怎麼修改元素box-sizing及其對盒子模型的影響
現在我們對如何顯示元素和設定尺寸有了更好的瞭解,接下來我們深入瞭解一下元素的定位。