本文推薦 PC 端閱讀~
本文版權歸 “公眾號 | 前端一萬小時” 所有,未經授權,請勿轉載!
複製程式碼
css_10
複製程式碼
1. 浮動元素有什麼特徵?對父容器、其他浮動元素、普通元素、文字分別有什麼影響?
2. 清除浮動指什麼?如何清除浮動?兩種以上方法。
複製程式碼
前言: 前 10 篇文章,我們基本上都是在用“理論”學習“理論”,那從這篇開始,我們試著用“實踐”來學習理論,然後又用於實踐。
一個原則:把程式碼拷貝到 JS Bin 上,對照效果搞懂每行程式碼的“是什麼”、“為什麼”、“怎麼樣”?
1 為什麼需要“浮動”?
假設我們需要有個東西,然後它的排版不是依照盒模型的定義——從上往下依次排列,而是從左到右這種結構,那麼我們需要考慮到使用“浮動”。
例如一個網站的頭部,一部分在左邊,一部分在右邊。首先,“部分”的表示我們會用 div ,而 div 是塊級元素,按理說它會從上到下,佔據一整行,不可能整列排列。那這個時候我們就需要“浮動”。
2 “浮動”是怎麼用的,有什麼表現效果?
2.1 放不下會換行
一個“浮動盒”會向左或向右移動,直到其外邊(outer edge)捱到包含塊邊沿或者另一個浮動盒的外邊。如果沒有足夠的水平空間來浮動,它會向下移動,直到空間合適或者不會再出現其它浮動了。
?原始碼及效果展示
html
<div class="ct">
<div class="box box1">1</div>
<div class="box box2">2</div>
<div class="box box3">3</div>
</div>
複製程式碼
css
.ct {
width: 280px;
height: 300px;
border: 1px solid;
margin: 100px;
}
.box {
color: #fff;
width: 100px;
height: 100px;
background: red;
float: left;
/*?直接在你需要浮動的元素上加 float 屬性。*/
}
.box1{
background: blue;
}
.box2{
background: pink;
}
複製程式碼
?對比:
?原始碼及效果展示
css
.ct {
width: 280px;
height: 300px;
border: 1px solid;
margin: 100px;
}
.box {
color: #fff;
width: 100px;
height: 100px;
background: red;
float: right;
}
/*?站在瀏覽器的角度看,它會挨著順序依次渲染*/
.box1{
background: blue;
}
.box2{
background: pink;
}
複製程式碼
2.2 被卡住的情況
?原始碼及效果展示
html
<body>
<div class="ct">
<div class="box box1">1</div>
<div class="box box2">2</div>
<div class="box box3">3</div>
</div>
</body>
複製程式碼
css
.ct {
width: 280px;
height: 300px;
border: 1px solid;
margin: 100px;
}
.box {
color: #fff;
width: 100px;
height: 100px;
background: red;
float: left;
}
.box1{
background: blue;
height: 120px;
}
.box2{
background: pink;
}
/*依然站在瀏覽器的角度,從上往下渲染文件,
當依次渲染完 1、2 後,渲染 3 的時候,右邊放不下,
然後他要被擠下去,擠下去後它貼著 2 的下邊緣開始向左移動,
當移動碰到 1 右下角時,動不了了,1 被卡住了。
所以我們在設定高度不一樣時,會出現一個“卡住”的問題。*/
複製程式碼
2.3 當浮動元素與文字有交集的時候
?原始碼及效果展示
html
<body>
<div class="ct">
<div class="box box1">1</div>
<p>捱到包含塊邊沿或者另一個浮動盒的外邊。
如果存在行盒,浮動盒的外 top (邊)會與當前行盒的 top (邊)對齊。
如果沒有足夠的水平空間來浮動,它會向下移動,直到空間合適或者不會再出現其他浮動了。
</p>
<div class="box box2">2</div>
<div class="box box3">3</div>
</div>
</body>
複製程式碼
css
.ct {
width: 280px;
height: 300px;
border: 1px solid;
margin: 100px;
}
.box {
color: #fff;
width: 100px;
height: 100px;
background: red;
float: left;
}
.box1 {
background: blue;
width: 140px;
height: 120px;
}
.box2 {
background: pink;
}
複製程式碼
?可以得到:
普通流中的一個元素,如果沒有設定定位和浮動,那它和浮動元素在一起之後,它會被浮動元素所遮擋。
?進一步驗證:
?原始碼及效果展示
css
.ct {
width: 280px;
height: 300px;
border: 1px solid;
margin: 100px;
}
.box {
width: 100px;
height: 100px;
background: red;
float: left;
}
.box1 {
background: blue;
height: 120px;
width: 140px;
opacity: 0.2; /*?設定透明度來觀察*/
}
.box2 {
background: pink;
}
/*?但裡邊的文字並沒有被這個浮動元素所遮擋,那他呈現的這個效果是:
這個段落 p 是看不到這個浮動元素的,而文字看得到,並且圍繞這個浮動元素排列。
*/
/*?即展現出來的一個規則就是:
當一個普通元素碰到一個浮動元素後,這個普通元素看不見這個浮動元素,
但普通元素裡邊的文字看得見這個浮動元素。
*/
複製程式碼
2.4 浮動元素脫離了普通流
脫離普通流是指:他的父容器在去計算寬高的時候,發現不了浮動元素。即,父容器不會被裡面的浮動元素撐開;
⚠️注意:和 absolute 不一樣。
?原始碼及效果展示
html
<div class="ct">
<div class="box box1">1</div>
<div class="box box2">2塊盒看不見浮動的 box1,但我是文字我能看見</div>
<div class="box box3">3</div>
</div>
複製程式碼
css
.ct {
width: 280px;
height: 300px;
border: 1px solid;
margin: 100px;
}
.box {
color: #fff;
width: 100px;
height: 100px;
background: red;
}
.box1 {
background: blue;
float: left;
opacity: 0.6;
}
.box2 {
background: pink;
height: 110px;
width: 110px;
}
複製程式碼
2.5 塊級元素浮動寬度收縮,行內元素浮動以塊級特性去呈現
?原始碼及效果展示
html
<body>
<div class="box">這是div</div>
<span>這是span</span>
</body>
複製程式碼
css
.box {
color: #fff;
float: left;
background: red;
}
span {
color: #fff;
float: left;
background: blue;
width: 100px;
height: 50px;
margin: 10px;
}
/*?塊級元素設定浮動之後,它就呈現出 inline-block 這種感覺,他的寬度會收縮。*/
/*?行內元素設定為浮動之後,它就呈現了塊級的特性,
也有 inline-block 的感覺,就把行內元素變成可以設定寬高、margin 等,
但沒有居中這些東西。
*/
複製程式碼
3 “浮動”的使用場景
3.1 兩欄佈局(左側固定寬度,右側自適應; 右側固定寬度,左側自適應)
<div class="aside">側邊欄固定寬度</div>
<div class="main">內容區塊自適應寬度</div>
複製程式碼
css
.aside {
color: #fff;
width: 150px;
height: 400px;
background: red;
float: left;
}
.main {
color: #fff;
margin-left: 160px;
/*?表示左邊的這 160px 的範圍我不用了*/
background: blue;
height: 500px;
}
複製程式碼
?對比(右側固定寬度,左側自適應):
?原始碼及效果展示
html
<div class="aside">側邊欄固定寬度</div>
<div class="main">內容區塊自適應寬度</div>
複製程式碼
css
.aside {
color: #fff;
width: 150px;
height: 400px;
background: red;
float: right;
}
.main {
color: #fff;
margin-right: 160px;
/*?表示右邊的這 160px 的範圍我不用了*/
background: blue;
height: 500px;
}
複製程式碼
3.2 三欄佈局——兩側寬度固定,中間自適應(注意 HTML 中的 menu aside main 的順序!)
?原始碼及效果展示
html
<div class="menu">側邊欄固定寬度</div>
<div class="aside">側邊欄固定寬度</div>
<div class="main">內容區塊自適應寬度</div>
複製程式碼
css
.menu {
color: #fff;
width: 150px;
height: 400px;
background: red;
float: left;
}
.aside {
color: #fff;
width: 150px;
height: 400px;
background: red;
float: right;
}
.main {
color: #fff;
margin-right: 160px;
margin-left: 160px;
/*?加左右 margin 就把位置撐開了*/
background: blue;
height: 500px;
}
複製程式碼
⚠️如果 HTML 中的 menu aside main 的順序變了:
?原始碼及效果展示
html
<div class="menu">側邊欄固定寬度</div>
<div class="main">內容區塊自適應寬度</div>
<div class="aside">側邊欄固定寬度</div>
<!--順序一旦變了,後邊的 aside 就會跳行,跑到下邊去了。
原因:假設我是瀏覽器,我需要對著 html 來畫出對應的影像,
首先畫 menu ,結合其樣式,左浮;
但這裡我們遇到了 main ,這個 main 是一個塊級元素,它會佔據一整行的寬度;
那接下來的 aside 就只有在 main 的基礎上往右下流動。-->
複製程式碼
css
.menu {
color: #fff;
width: 150px;
height: 400px;
background: red;
float: left;
}
.aside {
color: #fff;
width: 150px;
height: 400px;
background: red;
float: right;
}
.main {
color: #fff;
margin-right: 160px;
margin-left: 160px;
/*加左右 margin 就把位置撐開了*/
background: blue;
height: 500px;
}
複製程式碼
3.3 利用浮動實現“導航條”
3.3.1 “導航條”靠左
?原始碼及效果展示
html
<ul class="navbar">
<li><a href="#">1首頁</a></li>
<li><a href="#">2產品</a></li>
<li><a href="#">3服務</a></li>
<li><a href="#">4關於</a></li>
</ul>
複製程式碼
css
.navbar {
list-style: none;
}
.navbar>li {
float: left;
margin-left: 15px;
}
/*?當然我們用 inline-block 也可以實現效果,
但不同方式需要注意的問題不一樣:
使用浮動我們需要注意撐開容器;而用 inline-block 我們需要注意它的縫隙。
*/
複製程式碼
3.3.2 “導航條”靠右
?原始碼及效果展示
html
<body>
<ul class="navbar">
<li><a href="#">1首頁</a></li>
<li><a href="#">2產品</a></li>
<li><a href="#">3服務</a></li>
<li><a href="#">4關於</a></li>
</ul>
</body>
複製程式碼
css
.navbar {
float: right;
/*?把 ul 整體進行右浮動*/
list-style: none;
}
.navbar>li {
float: left;
/*?但 ul 裡邊的東西都是靠左的*/
margin-left: 15px;
}
複製程式碼
?對比:
?原始碼及效果展示
html
<ul class="navbar">
<li><a href="#">1首頁</a></li>
<li><a href="#">2產品</a></li>
<li><a href="#">3服務</a></li>
<li><a href="#">4關於</a></li>
</ul>
複製程式碼
css
.navbar {
list-style: none;
}
.navbar>li {
float: right;
/*?直接改這裡是不行的,因為站在瀏覽器的立場是按文件順序來渲染的*/
margin-left: 15px;
}
複製程式碼
4 清除“浮動”
4.1 為什麼要清除浮動?
因為任何東西有利有弊。
4.1.1 第一,浮動對後續元素位置產生影響(渲染時,因為塊元素看不見,但裡邊的文字看的見)
?原始碼及效果展示
html
<div id="content">
<div class="menu">側邊欄固定寬度</div>
<div class="aside">側邊欄固定寬度</div>
<div class="main">內容區塊自適應寬度</div>
</div>
<div id="footer">我是 footer,但我的樣式出現了問題</div>
複製程式碼
css
.menu {
color: #fff;
width: 150px;
height: 300px;
background: red;
float: left;
}
.aside {
color: #fff;
width: 150px;
height: 300px;
background: red;
float: right;
}
.main {
color: #fff;
margin-right: 160px;
margin-left: 160px;
background: blue;
height: 200px;
}
#footer {
color: #fff;
background: grey;
}
複製程式碼
4.1.2 第二,父容器高度計算出現問題
?原始碼及效果展示
html
<ul class="navbar">
<li><a href="#">1首頁</a></li>
<li><a href="#">2產品</a></li>
<li><a href="#">3服務</a></li>
<li><a href="#">4關於</a></li>
</ul>
複製程式碼
css
.navbar {
list-style: none;
border: 1px solid #ccc;
/*加一個背景色也沒效果:
background: pink;*/
}
.navbar>li {
float: left;
margin-left: 15px;
}
/*?由於浮動元素脫離了文件流,所以他的父元素是看不見他的。
這裡對於 navbar 來說,他認為裡邊沒有什麼 li 來把它撐開,
因為 li 已經浮動了,那沒有東西撐開它,它就會認為高度為 0。*/
複製程式碼
4.2 清除浮動的方法
4.2.1 清除浮動實現的原理和方法
?原始碼及效果展示
html
<ul class="navbar">
<li><a href="#">1首頁</a></li>
<li><a href="#">2產品</a></li>
<li><a href="#">3服務</a></li>
<li><a href="#">4關於</a></li>
<li class="clear"></li>
<!-- ?想解決這個沒辦法撐開的問題,
那麼就要求這個源文件中要有一個沒有被浮動的的元素——普通元素。-->
</ul>
複製程式碼
css
.navbar {
list-style: none;
border: 1px solid #ccc;
}
.navbar>li {
float: left;
margin-left: 15px;
}
.navbar .clear {
float: none;
clear: left;
}
/*?通過清除浮動來獲得一個普通元素,進而撐開這個父容器*/
複製程式碼
- 清除浮動
clear: left;
——這個 clear 可以用在任何元素上,不管你是不是浮動元素。要求該盒的 top 、border 邊位於源文件(就是 html 文件結構中)中在此之前的元素形成的所有左浮動盒的 bottom 外邊下方(如果沒有左浮動盒,那你清除左浮動也就沒有意義)。 - 清除浮動
clear: right;
——要求該盒的 top border 邊位於源文件中在此之前的元素形成的所有右浮動盒的 bottom 外邊下方。 - 清除浮動
clear: both;
——只要源文件中該盒前邊有浮動元素,那麼就在這個浮動元素下方。
1. ?對比
我們上邊是用一個造了一個 li
來實體化普通元素,那我們可否有更簡化的方法——偽元素(偽元素的一個作用就是去代替標籤)。
?原始碼及效果展示
html
<ul class="navbar">
<li><a href="#">1首頁</a></li>
<li><a href="#">2產品</a></li>
<li><a href="#">3服務</a></li>
<li><a href="#">4關於</a></li>
</ul>
複製程式碼
css
.navbar {
list-style: none;
border: 1px solid #ccc;
}
.navbar>li {
float: left;
margin-left: 15px;
}
.navbar::after {
content: '';
/*?寫了一個元素,你必須要有 content */
display: block;
/*?注意這裡如果沒有這個 block ,是不會生效的,
因為寫了 after ,只是表示是一個匿名的行盒,即一個字串。
然而他必須是塊級元素,他才會下去。*/
clear: both;
}
/*?用偽元素這樣寫就是表示:
我在源文件 navbar 的最後生成了一個 block 元素,
然後清除浮動,他就會位於浮動盒子的下方,
進而撐開了 navbar 這個父容器。*/
複製程式碼
2. ?再對比
?原始碼及效果展示
為了通用性,我們常常 .clearfix::after;
——就是為了修復浮動所產生的問題。
html
<ul class="navbar clearfix">
<!--?凡是需要清除浮動的地方我們都可以加一個這個樣式就可以通用-->
<li><a href="#">1首頁</a></li>
<li><a href="#">2產品</a></li>
<li><a href="#">3服務</a></li>
<li><a href="#">4關於</a></li>
</ul>
複製程式碼
css
.navbar {
list-style: none;
border: 1px solid #ccc;
}
.navbar>li {
float: left;
margin-left: 15px;
}
.clearfix::after {
/*?為了通用性,我們直接 clearfix ,然後在 HTML 文件中,
哪裡需要清除浮動,就直接加一個這個類名進去就可以了。*/
content: '';
display: block;
clear: both;
}
複製程式碼
4.2.2 解決上邊由“浮動”帶來的問題
?原始碼及效果展示
html
<div id="content" class="clearfix">
<!--?意思就是:這三個元素下邊還有一個元素,
然後這個元素會在這三個元素的下方,進而就會撐開這個 content 。-->
<div class="menu">側邊欄固定寬度</div>
<div class="aside">側邊欄固定寬度</div>
<div class="main">內容區塊自適應寬度</div>
</div>
<div id="footer">我是 footer,但我的樣式出現了問題</div>
複製程式碼
css
.menu {
color: #fff;
width: 150px;
height: 300px;
background: red;
float: left;
}
.aside {
color: #fff;
width: 150px;
height: 300px;
background: red;
float: right;
}
.main {
color: #fff;
margin-right: 160px;
margin-left: 160px;
background: blue;
height: 200px;
}
#footer {
color: #fff;
background: grey;
}
.clearfix::after {
/*?為了通用性,我們直接 clearfix ,
然後在 HTML 文件中,哪裡需要清除浮動,就直接加一個這個類名進去就可以了。*/
content: '';
display: block;
clear: both;
}
複製程式碼
?小總結:
所以以後我們想去實現一個水平佈局,就有了兩種方法:
- 第一,inline-block——不需要清除浮動,簡單,在設定居中時更方便,適合子內容不多的元素水平排列。但要注意縫隙問題,以及對齊(上對齊);
- 第二,float——沒縫隙問題,適合稍大的佈局。但需要解決的問題是父元素不會被撐開而導致的很多問題。
5 浮動和負 margin
兩個浮動元素,如果因放不下導致其中一個下移,對下移的元素設定負 margin 值大於自身的寬度可將其上移。
?原始碼及效果展示
html
<div class="container">
<div class="box box1">box1</div>
<div class="box box2">box2</div>
</div>
複製程式碼
css
* {
margin: 0
}
.container {
width: 400px;
height: 400px;
border: 1px solid red;
}
.box1 {
width: 300px;
height: 100px;
background: pink;
float: left;
}
.box2 {
width: 110px;
height: 100px;
background-color: red;
float: left;
margin-left: -10px;
/*?瀏覽器計算的時候就相當於寬度減去這個 10 ,然後就是 100,那就正好放上去。*/
}
複製程式碼
後記: 下篇我們將討論與“浮動”對應的“定位”是怎樣讓“盒子”動起來的。後續文章都是重中之重,每一篇都乾貨滿滿!
加油!