CSS入門指南-2:盒子模型、浮動和清除

goodspeed發表於2017-07-22

這是CSS設計指南的讀書筆記,用於加深學習效果。

上一篇介紹了css 的工作原理,這一篇主要介紹盒子模型浮動

盒子模型

所謂盒子模型,就是瀏覽器為頁面中的每個HTML元素生成的矩形盒子。這些盒子們都要按照可見版式模型在頁面上排布。

可見的頁面版式主要由三個屬性控制:position、display和float。

  • position:控制頁面上元素的位置關係
  • display:控制元素是堆疊、並排還是不在頁面出現
  • float:提供控制的方式,以便吧元素組成多欄佈局

元素盒子的屬性可以分成三組:

  • 邊框(board)。可以甚至邊框的寬窄、樣式和顏色
  • 內邊距(padding)。可以甚至盒子內容區與邊框的間距
  • 外邊距(margin)。可以設定盒子與相鄰元素的間距

盒模型示意圖展示了HTML元素的邊框、內邊距和外邊距之間的關係
盒模型示意圖展示了HTML元素的邊框、內邊距和外邊距之間的關係

元素盒子還有一個背景層,可以改變顏色,也可以新增圖片。

簡寫樣式

CSS為邊框、內邊距和外邊距分別規定了簡寫屬性,每個簡寫宣告中,屬性值得順序都是上、右、下、左。

比如:

{
  margin-top: 5px; 
  margin-right: 10px;
  margin-bottom: 12px; 
  margin-left: 8px;
}複製程式碼

使用簡寫則為這樣:

{
    margin: 12px 10px 12px 8px;
}複製程式碼

如果有一個值沒寫,那麼則使用對邊的值。

比如:

{margin: 12px 10px 12px;}
/*等同於*/
{
    margin: 12px 10px 12px 10px;
}複製程式碼

如果只寫一個值,則4個邊都取這個值。

{margin: 12px;}
/*等同於*/
{margin: 12px 12px 12px 12px;}複製程式碼

另外每個盒子的屬性也分三個粒度,這三個粒度從一般到特殊分別舉例如下:

{
    border: 2px dashed red;
}複製程式碼

混合使用三種粒度的簡寫屬性達成設計目標是很常見的。比如,想為盒子的上邊和下邊新增4畫素的紅色邊框,為左邊新增1畫素寬的紅色邊框,而右邊沒有。可以這麼寫:

{border: 4px solid red;} /* 先給4條邊設定相同的樣式*/
{border-left-width: 1px;} /* 修改左邊框寬度*/
{border-fight: none;} /*移出右邊框*/複製程式碼

盒子邊框

border 有三個相關屬性。

  • 寬度(border-width)。可以使用thin、medium和thick等文字值,也可以使用除百分比和負值之外的任何絕對值。
  • 樣式(border-style)。有none、hidden、dotted、dashed等文字值。
  • 顏色(border-color)。可以使用任意顏色值,包括RGB、HSL、十六進位制顏色值和顏色關鍵字。

盒子內邊距

內邊距是盒子內容區與盒子邊框之間的距離。

上圖的樣式為:

p {
    font: 16px helvetica, sans-serif; 
    width: 220px; 
    border: 2px solid red; 
    background-color: #caebff;
}複製程式碼

可以看到在沒有設定內邊距的情況下,內容緊挨著邊框。

設定邊框後:

p {
    font: 16px helvetica, arial, sans-serif; 
    width: 220px; 
    border: 2px solid red; 
    background-color: #caebff; 
    padding: 10px;
}複製程式碼

效果如下,可以看到樣式舒服了很多:

新增內邊距後的效果圖
新增內邊距後的效果圖

內邊距在盒子的內部,所以也會取得盒子背景。也就是說,多出來的內邊距並沒有擠壓文字內容,實際是加在了宣告的盒子寬度之上。

盒子外邊距

外邊距的例子
外邊距的例子

上圖的例子中,第一組是預設情況,第二組是在第一組基礎上新增了邊框,第三組是把第二組的外邊距設定為了0,標題和段落全緊挨在一起了。

推薦大家吧這條規則作為樣式表的第一條規則:

* {margin: 0; padding: 0;}複製程式碼

這條規則是把所有元素預設的外邊距和內邊距都設定為0。這樣,我們可以為那些真正需要新增邊距的元素設定邊距。

疊加外邊距

比如下邊這個樣式:

p {
    height: 50px;
    border: 1px solid #000;
    backgroundcolor: #fff;
    margin-top: 50px;
    margin-bottom: 30px;
}複製程式碼

如果我們把這個樣式應用到3個前後相接的段落上,由於上邊距和下邊距相鄰,你可能會認為他們之間的外邊距是80(50+30)畫素,但是實際上是50畫素,這就是邊距疊加。

垂直方向上外邊距會疊加 水平方向的不會
外邊距單位 根據經驗,水平邊距可以使用畫素,以便該段文字始終與包含元素邊界保持固定間距,不受自豪變大或變小的影響。而對於上下外邊距,已em 為單位則可以讓段間距隨字號變化而相應增大或縮小。

盒子有多大

沒有寬度的盒子

如果沒有顯式的設定元素的 width 屬性,我們就稱這個盒子沒有寬度。
如果沒有設定 width, 那麼這個屬性的預設值是 auto,會讓元素的寬度擴充套件到與父元素同寬。

我們看個例子?:

<body>
<p> 這個元素沒有設定寬度</p>
</body>複製程式碼

設定樣式:

body {
    font-family: helvetica, arial, sans-serif;
    size: 1em;
    marging: 0px;
    background-color: #caebff;
}

p {
    margin: 0;
    background-color: #fff;
}複製程式碼

不設定寬度的樣式
不設定寬度的樣式

可以看到,不給段落設定寬度,段落會填滿 body 元素。

為了更加明顯,我給段落左右分別加一個邊框,再加一個外邊距。

p {
    margin:0 30px; 
    background-color:#fff; 
    padding:0 20px; 
    border: solid red; 
    border-width: 0 6px;
}複製程式碼

段落新增左右邊框
段落新增左右邊框

這時段落內容區域變成了 288畫素(我把瀏覽器寬度手動調成了400px,400-(20+6+30)x2)。

結論:沒有寬度的元素始終會擴充套件到填滿其父元素的寬度為止。新增水平邊框、內邊距和外邊距會導致內容寬度減少,減少量等於水平邊框、內邊距和外邊距的和。

有寬度的盒子

還是上邊的例子,我們先把外邊距去掉,固定寬度400px;

p {
    width:400px; 
    margin:0; 
    padding:0 20px;  
    border:solid red;  
    border-width: 0 6px  0 6px;  
    background-color:#fff;
}複製程式碼

設定寬度、內邊距、邊框的樣式
設定寬度、內邊距、邊框的樣式

可以看到,盒子的寬度並不是400px,而是452畫素(400+(20+6)*2)。

再給盒子加上外邊距:

p {
    width:400px; 
    margin:0 30px; 
    padding:0 20px;  
    border:solid red;  
    border-width: 0 6px  0 6px;  
    background-color:#fff;
}複製程式碼

設定寬度、內邊距、外邊距、邊框的樣式
設定寬度、內邊距、外邊距、邊框的樣式

可以看到,這時總寬度達到了512畫素(30+6+20+400+20+6+30=512)

結論: 為設定了寬度的盒子新增邊框、內邊距和外邊距,會導致盒子更寬。實際上盒子的 width 屬性設定的只是盒子內容區的寬度,而非盒子整體的寬度

浮動與清除

浮動

css 設計 float(浮動)屬性的主要目的是為了實現文字繞排圖片的效果,這個屬性也是建立多欄佈局最簡單的方式。
我們先看一個例子:

<img .../>
<p>..the paragraph text...</p>複製程式碼

css 規則如下。

p {
    margin: 0;
    border: 1px solid red;
}
img {
    float: left;
    margin: 0 4px 4px 0;
}複製程式碼

這個例子的樣式如圖所示:

這裡我們給圖片加了 float: left 樣式,這時瀏覽器就會把圖片向上推,直到它碰到父元素的內邊界(也就是body)。後面的內容不再認為浮動元素在它的前邊,所以它會佔據父元素左上角的位置。不過,它的內容會繞開浮動的圖片。

建立分欄

在上面的基初上如何使內容分欄呢?
只要再用一float 屬性就可以了。

p {
    float: left; /* 加上這兩行*/
    width: 200px;
    ...
}複製程式碼

這樣同時浮動圖片和有寬度的段落,會使圖片繞排效果消失,而浮動的段落也向左向上移動。變成了多欄的效果。

圍住浮動元素

看下這個例子:

<section>
    <img src="images/rubber_duck2.jpg">
    <p>It's fun to float.</p>
</section>
<footer>Here is the footer element that runs across</footer>複製程式碼

應用樣式如下:

section {
    border: 1px solid blue;
    margin: 0 0 10px 0;
}
p {
    marging: 0;
}
footer {
    border: 1px solid red;
}複製程式碼

效果如圖:

浮動圖片後標題跑到了右邊,但父元素section也收縮到只包含文字的高度
浮動圖片後標題跑到了右邊,但父元素section也收縮到只包含文字的高度

但這並不是我們想要的,我們並不想讓footer 被提到上邊。
浮動元素脫離了原來的文件流,不受父元素的控制。如果我們想讓父元素還包含浮動的子元素,怎麼做呢?
有三種方法:

為父元素應用 overflow: hidden

只需要在 section 加上這個樣式:

section {
    overflow: hidden;
    ...
}複製程式碼

現在效果如圖:

section 又包圍了浮動的圖片
section 又包圍了浮動的圖片

實際上,overflow: hidden 宣告凱真正用途是防止包含元素被超大內容撐大。也就是說應用上這個之後,包含元素(父元素)會保持其設定的寬度,如果子元素過大,會被截掉。

浮動父元素

第二種方法是讓父元素和子元素同時浮動。

section {
    float: left;
    width: 100%;
    border: 1px solid blue;
}
img {
    float: left;
}
footer {
    border: 1px solid red;
    clear: left;
}複製程式碼

浮動section 後,不管其子元素是否浮動,都會被包圍。因此需要用 width: 100% 讓section 與瀏覽器同寬。由於section 也浮動,所以footer 會往它旁邊擠,這時需要使用 clear: left 以保證不會被提升到浮動的元素旁邊。

在父元素內容的末尾新增浮動元素,可以直接在標記中加,也可以通過給父元素新增clearfix 類來加。

第三種方法是給父元素新增一個非浮動的子元素,然後清除該子元素。

這種方式可以生效是因為父元素一定會包圍非浮動子元素,且清除會讓這個子元素處於最下。

這裡我們使用神奇的 clearfix 規則:

.clearfix:after {
     content: ".";
     display: block;
     height: 0;
     clear: both;
     visibility: hidden;
    }複製程式碼

這個 clearfix 規則最早是由程式設計師 Tony Aslett 發明的,它只新增了一個清除的包含句點作為非浮動元素(必須有內容,句點是最小的內容)。規則中其他生命是為了確保這個偽元素沒有高度,而且不可見。

after 會在元素內容(而不是元素後插入一個偽元素)
使用clear: both 意味著 section 中新增的子元素會被清除左右浮動元素。

我們看了三種方法圍住浮動元素的方式。

那如果沒有父元素,如果清除浮動呢?

比如下邊這個例子:

<section>
    <img src="images/rubber_duck3.jpg">
    <p>This text sits next to the image and because the text extends below the bottom of the image, the next image positions itself correctly under the previous image.</p>
    <img src="images/beach_ball.jpg">
    <p>This text is short, so the next image can float up beside this one.</p>
    <img src="images/yellow_float.jpg">
    <p>Because the previous image's text does not extend below it, this image and text move up next to the previous image. This problem can be solved by the use of the clear property.</p>
</section>複製程式碼

樣式如下:

section {
    width:300px; b
    order:1px solid red;
}
img {
    float:left; 
    margin:0 4px 4px 0;
}
p {
    font-family:helvetica, arial, sans-serif; 
    margin:0 0 5px 0;
}複製程式碼

效果如圖所示:

由於第二張圖下方有空間,所以第三張圖及說明文字會上浮到第二張圖片右側,這並不是我們想要的結果。

我們想要的效果是如下圖這樣:

那怎麼實現呢? 還是應用 clearfix 規則。為每個段落加上clearfix 類。通過clearfix類清除元素後,佈局就是我們希望的了。

這一篇主要介紹了盒子模型,浮動和清除。下一篇介紹css 佈局。


最後,感謝女朋友支援。

>歡迎關注(April_Louisa) >請我喝芬達
歡迎關注
歡迎關注
請我喝芬達
請我喝芬達

相關文章