一、浮動流是什么
在css中,最常見的兩種流就是標准流和浮動了,其中標准流可以簡單如下理解:
- 塊級元素獨占一行,且它們都可以設置對應的寬高(width和height),例如div,h標簽等
- 行內元素可以在一行中排列多個,它們的大小(寬度和高度)由里面的內容所決定,常見的標簽有span,a標簽等
而浮動定位則是將元素排除在標准流之外,它的一些概念和特點如下:
- 將元素排除在普通流之外
- 元素將不在頁面中占據空間
- 將浮動元素放置在包含框的左邊或者右邊
- 浮動元素依舊位於包含框之內
- 浮動的框可以向左或者向右移動,直到他的外邊緣碰到包含框或另一個浮動框的邊框為止
- 浮動元素的外邊緣不會超過其父元素的內邊緣
- 浮動元素不會互相重疊
- 浮動元素不會上下浮動【只能設置左右浮動】
- 任何元素一旦浮動,display 屬性將完全失效均可以設置寬高,並且不會獨占一行
浮動語法:
#elem {
float: none/left/right;
}
二、通過代碼實例了解浮動特點
1. 搭建測試框架
首先新建一個html文件,body內容如下:
<div id="box">
<div></div>
<div></div>
<div></div>
</div>
對應的css:
#box {
width: 600px;
height: 600px;
background: plum;
}
#box>div:first-child {
width: 200px;
height: 200px;
background: #6ad281;
}
#box>div:nth-child(2) {
width: 200px;
height: 200px;
background: #72d0f6;
}
#box>div:nth-child(3) {
width: 200px;
height: 200px;
background: #df637a;
}
此時的運行效果:
2. 添加浮動
此時如果給第一個元素添加浮動效果:
#box>div:first-child {
...
float: left;
}
可以看到第二個和第三個元素都向上移動了,且第二個元素被第一個元素遮住了,然后將浮動改為右浮動:
此時可以發現浮動的元素移動到了父元素的右邊界處。第2和第3個元素雖然都是獨占一行的,但這並不會影響到浮動元素的排布。這里可以理解為標准流中的元素都排列在地面上,而浮動的元素則是排列在空中的一層,因此地面元素占用的位置不會影響空中元素的排列,此外浮動的元素會遮擋標准流中的元素,例如上面的藍色元素就被綠色元素遮擋住了。
3. 浮動元素的排布
我們先調節第三個div(紅色div)的大小:
#box>div:nth-child(3) {
width: 300px;
height: 300px;
...
}
然后為第二個元素也添加float: right的浮動屬性,此時的效果為:
可以看到紅色的元素被遮擋住了,此時我們再為紅色元素也添加float: right的浮動屬性:
可以看到紅色元素移動到了右下角,這是因為藍色元素左邊的位置已經不足以放下紅色元素了(剩余位置的寬度<紅色元素的寬度),因此紅色元素只能向下尋找第一個可以放下的位置放置。
但如果紅色元素的寬高為200和400,即:
#box>div:nth-child(3) {
width: 200px;
height: 400px;
...
}
則它還是會被排布在藍色元素的左邊:
因此浮動元素是以寬度來判斷是否可以排布在當前位置的。
4. 給行內元素添加浮動效果
這里先編寫兩個span元素:
<span class="floatSpan">我是span標簽</span>
<span class="floatSpan">我是span標簽</span>
對應的css:
.floatSpan {
background: red;
width: 100px;
height: 100px;
}
當前效果:
可以看到,當前設置的寬度和高度對它是無效的,因為行內元素的寬高只由它的內容大小決定。
然后為它添加float: left的浮動效果:
.floatSpan {
...
float: left;
}
效果如下:
可以看到,當添加了浮動效果后,行內元素也可以設置寬高了,而且不會獨占一行(和行內塊元素一樣),這驗證了【任何元素一旦浮動,display 屬性將完全失效均可以設置寬高,並且不會獨占一行】這個浮動屬性的特點。
5. 子元素浮動后對父元素的影響
還是原來的#box元素以及它的3個子元素,但此時我們去掉父元素的寬高設定(子元素先不浮動):
#box {
/* width: 600px;
height: 600px; */
background: plum;
}
此時的效果為:
可以看到,雖然我們沒有為父元素設置寬高,但默認情況下(標准流)父元素的高度會等於子元素的高度之和(也可以理解為子元素將父元素撐開)。
而如果此時我們為第一個元素添加右浮動,效果為:
這是因為綠色元素脫離了標准流,因此父元素就只能由剩下在標准流的子元素撐開了。依此類推,若三個元素均添加浮動,則不再有標准流中的元素將父元素撐開了,因此父元素的高度就會變為0,如下所示:
這也是我們使用浮動布局橫向排列子元素經常會遇到的問題,有以下幾個辦法可以解決:
5.1 在父元素中添加overflow: hidden屬性
即:
#box {
/* width: 600px;
height: 600px; */
background: plum;
/* 在不設置寬高的情況下,讓父元素感知子元素的高度 */
overflow: hidden;
}
效果如下:
可以看到,父元素擁有了子元素的最大高度。
5.2 為父元素也添加浮動屬性
例如添加float: right的浮動屬性:
#box {
/* width: 600px;
height: 600px; */
background: plum;
float: right;
}
可以看到父元素也得到了子元素的最大高度。
6. 消除浮動
例如上面的#box可以看做是網頁中的一個專欄部分,當前希望在它的下面編寫一個新的專欄#new,但#new屬於標准流,而#box添加了float: right的浮動屬性,如果直接編寫則#new會被#box覆蓋,如下所示:
<div id="box">
...
</div>
<div id="new">
我是new專欄
</div>
#new {
height: 300px;
background: pink;
}
此時我們就需要消除上面div的浮動帶來的影響了,消除浮動有以下三種常用的方法。
6.1 在結尾處加上空的div標簽,添加clear: both屬性
<div id="box">
...
</div>
<div style="clear: both;"></div> <!--空的div標簽-->
<div id="new">
我是new專欄
</div>
效果如下:
同理,也可以在new中添加clear: both屬性:
#new {
...
clear: both;
}
效果也是相同的。
6.2 浮動元素父級div添加overflow: hidden屬性
上面5.1中也已經使用過了這個屬性,即可以使標准流中的div獲取浮動的子元素的高度,此時我們可以給#box元素套一個#fatherdiv,如下所示:
<div id="father">
<div id="box">...</div>
</div>
然后給#father添加overflow: hidden屬性:
#father {
overflow: hidden;
}
效果如下:
可以發現這兩種方式的效果是一模一樣的。
6.3 給父元素指定寬高
這個方法應該是最笨的方法了,相當於給上面的father標簽指定它孩子的寬高,不過這個方法可以使用js進行實現。
