前言:前 10 篇文章,我們基本上都是在用「理論」學習「理論」。從這篇開始,我們試著用「實踐」來學習理論,然後又用於實踐。
一個原則:把代碼拷貝到 JS Bin 上,對照效果搞懂每行代碼「是什麼」、「為什麼」、「怎麼樣」?
1 為什麼需要「浮動」假設我們需要有個東西,然後它的排版不是依照盒模型的定義——從上往下依次排列,而是從左到右這種結構,那麼我們需要考慮到使用「浮動」。
例如一個網站的頭部,一部分在左邊,一部分在右邊。首先,「部分」的表示我們會用 div,而 div 是塊級元素,按理說它會從上到下,佔據一整行,不可能整列排列。那這個時候我們就需要「浮動」。
2 「浮動」是怎麼用的,有什麼表現效果2.1 放不下會換行一個「浮動盒」會向左或向右移動,直到其外邊(outer edge)挨到包含塊邊沿或者另一個浮動盒的外邊。如果沒有足夠的水平空間來浮動,它會向下移動,直到空間合適或者不會再出現其他浮動了。
🔗源碼及效果展示HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>前端一萬小時</title>
</head>
<body>
<div class="ct">
<div class="box box1">①</div>
<div class="box box2">②</div>
<div class="box box3">③</div>
</div>
</body>
</html>
.ct {
width: 280px;
height: 300px;
margin: 100px;
border: 1px solid black;
}
.box {
float: left; /* 🚀直接在你需要浮動的元素上加 float 屬性。 */
width: 100px;
height: 100px;
background: red;
color: #fff;
}
.box1 {
background: blue;
}
.box2 {
background: pink;
}
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="ct">
<div class="box box1">①</div>
<div class="box box2">②</div>
<div class="box box3">③</div>
</div>
</body>
</html>
.ct {
width: 280px;
height: 300px;
margin: 100px;
border: 1px solid;
}
.box {
float: right;
width: 100px;
height: 100px;
background: red;
color: #fff;
}
/* 🚀站在瀏覽器的角度看,它會挨著順序依次渲染。 */
.box1 {
background: blue;
}
.box2 {
background: pink;
}
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="ct">
<div class="box box1">①</div>
<div class="box box2">②</div>
<div class="box box3">③</div>
</div>
</body>
</html>
.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 被卡住了。
所以我們在設置高度不一樣時,會出現一個「卡住」的問題。
*/
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="ct">
<div class="box box1">①</div>
<p>
挨到包含塊邊沿或者另一個浮動盒的外邊。
如果存在行盒,浮動盒的外 top(邊)會與當前行盒的 top(邊)對齊。
如果沒有足夠的水平空間來浮動,它會向下移動,
直到空間合適或者不會再出現其他浮動了。
</p>
<div class="box box2">②</div>
<div class="box box3">③</div>
</div>
</body>
</html>
.ct {
width: 280px;
height: 300px;
margin: 100px;
border: 1px solid black;
}
.box {
float: left;
width: 100px;
height: 100px;
background: red;
color: #fff;
}
.box1 {
width: 140px;
height: 120px;
background: blue;
}
.box2 {
background: pink;
}
🏆可以得到:
普通流中的一個元素,如果沒有設置定位和浮動,那它和浮動元素在一起之後,它會被浮動元素所遮擋。
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="ct">
<div class="box box1">①</div>
<p>
挨到包含塊邊沿或者另一個浮動盒的外邊。
如果存在行盒,浮動盒的外 top(邊)會與當前行盒的 top(邊)對齊。
如果沒有足夠的水平空間來浮動,它會向下移動,
直到空間合適或者不會再出現其他浮動了。
</p>
<div class="box box2">②</div>
<div class="box box3">③</div>
</div>
</body>
</html>
.ct {
width: 280px;
height: 300px;
margin: 100px;
border: 1px solid;
}
.box {
float: left;
width: 100px;
height: 100px;
background: red;
}
.box1 {
width: 140px;
height: 120px;
background: blue;
opacity: 0.5; /* 🚀設置透明度來觀察! */
}
.box2 {
background: pink;
}
/*
🚀但裡邊的文字並沒有被這個浮動元素所遮擋,那它呈現的這個效果是:
這個段落 p 是看不到這個浮動元素的,而文字看得到,並且圍繞這個浮動元素排列。
*/
/*
🚀即展現出來的一個規則就是:
當一個普通元素碰到一個浮動元素後,這個普通元素看不見這個浮動元素,
但普通元素裡邊的文字看得見這個浮動元素。
*/
脫離普通流是指:它的父容器在去計算寬高的時候,發現不了浮動元素。即,父容器不會被裡面的浮動元素撐開;
❗️注意:和 absolute 不一樣。HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>前端一萬小時</title>
</head>
<body>
<div class="ct">
<div class="box box1">①</div>
<div class="box box2">② 塊盒看不見浮動的 box1,但我是文本我能看見!</div>
<div class="box box3">③</div>
</div>
</body>
</html>
.ct {
width: 280px;
height: 300px;
margin: 100px;
border: 1px solid;
}
.box {
width: 100px;
height: 100px;
background: red;
color: #fff;
}
.box1 {
float: left;
background: blue;
opacity: 0.6;
}
.box2 {
width: 110px;
height: 110px;
background: pink;
}
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="box">這是 div</div>
<span>這是 span</span>
</body>
</html>
.box {
float: left;
color: #fff;
background: red;
}
span {
float: left;
width: 100px;
height: 50px;
margin: 10px;
color: #fff;
background: blue;
}
/* 🚀塊級元素設置浮動之後,它就呈現出 inline-block 這種感覺,它的寬度會收縮。 */
/*
🚀行內元素設置為浮動之後,它就呈現了塊級的特性,也有 inline-block 的感覺,
就把行內元素變成可以設置寬高、margin 等,但沒有居中這些東西。
*/
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="aside">側邊欄固定寬度</div>
<div class="main">內容區塊自適應寬度</div>
</body>
</html>
.aside {
float: left;
width: 150px;
height: 400px;
color: #fff;
background: red;
}
.main {
height: 500px;
margin-left: 160px; /* 🚀表示左邊的這 160px 的範圍我不用了! */
color: #fff;
background: blue;
}
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>前端一萬小時</title>
</head>
<body>
<div class="aside">側邊欄固定寬度</div>
<div class="main">內容區塊自適應寬度</div>
</body>
</html>
.aside {
float: right;
width: 150px;
height: 400px;
color: #fff;
background: red;
}
.main {
margin-right: 160px;
/* 🚀表示右邊的這 160px 的範圍我不用了! */
height: 500px;
color: #fff;
background: blue;
}
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>前端一萬小時</title>
</head>
<body>
<div class="menu">側邊欄固定寬度</div>
<div class="aside">側邊欄固定寬度</div>
<div class="main">內容區塊自適應寬度</div>
</body>
</html>
.menu {
float: left;
width: 150px;
height: 400px;
color: #fff;
background: red;
}
.aside {
float: right;
width: 150px;
height: 400px;
color: #fff;
background: red;
}
.main {
height: 500px;
margin-right: 160px;
margin-left: 160px;
/* 🚀加左右 margin 就把位置撐開了! */
color: #fff;
background: blue;
}
HTML
<div class="menu">側邊欄固定寬度</div>
<div class="main">內容區塊自適應寬度</div>
<div class="aside">側邊欄固定寬度</div>
<!-- 順序一旦變了,後邊的 aside 就會跳行,跑到下邊去了。
原因:假設我是瀏覽器,我需要對著 HTML 來畫出對應的圖像。
首先畫 menu,結合其樣式,左浮;
但這裡我們遇到了 main,main 是一個塊級元素,它會佔據一整行的寬度;
那接下來的 aside 就只有在 main 的基礎上往右下流動。 -->
.menu {
float: left;
width: 150px;
height: 400px;
color: #fff;
background: red;
}
.aside {
float: right;
width: 150px;
height: 400px;
color: #fff;
background: red;
}
.main {
height: 500px;
margin-right: 160px;
margin-left: 160px;
/* 加左右 margin 就把位置撐開了! */
color: #fff;
background: blue;
}
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<ul class="navbar">
<li><a href="#">① 首頁</a></li>
<li><a href="#">② 產品</a></li>
<li><a href="#">③ 服務</a></li>
<li><a href="#">④ 關於</a></li>
</ul>
</body>
</html>
.navbar {
list-style: none;
}
.navbar>li {
float: left;
margin-left: 15px;
}
/*
🚀當然我們用 inline-block 也可以實現效果,但不同方式需要注意的問題不一樣:
使用浮動我們需要注意撐開容器;而用 inline-block,我們需要注意它的縫隙。
*/
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>前端一萬小時</title>
</head>
<body>
<ul class="navbar">
<li><a href="#">① 首頁</a></li>
<li><a href="#">② 產品</a></li>
<li><a href="#">③ 服務</a></li>
<li><a href="#">④ 關於</a></li>
</ul>
</body>
</html>
.navbar {
float: right;
/* 🚀把 ul 整體進行右浮動。 */
list-style: none;
}
.navbar>li {
float: left;
/* 🚀但 ul 裡邊的東西都是靠左的。 */
margin-left: 15px;
}
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>前端一萬小時</title>
</head>
<body>
<ul class="navbar">
<li><a href="#">① 首頁</a></li>
<li><a href="#">② 產品</a></li>
<li><a href="#">③ 服務</a></li>
<li><a href="#">④ 關於</a></li>
</ul>
</body>
</html>
.navbar {
list-style: none;
}
.navbar>li {
float: right;
/* 🚀直接改這裡是不行的,因為站在瀏覽器的立場是按文檔順序來渲染的。 */
margin-left: 15px;
}
因為任何東西有利有弊。
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>
.menu {
float: left;
width: 150px;
height: 300px;
color: #fff;
background: red;
}
.aside {
float: right;
width: 150px;
height: 300px;
color: #fff;
background: red;
}
.main {
height: 200px;
margin-right: 160px;
margin-left: 160px;
color: #fff;
background: blue;
}
#footer {
color: #fff;
background: grey;
}
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>前端一萬小時</title>
</head>
<body>
<ul class="navbar">
<li><a href="#">① 首頁</a></li>
<li><a href="#">② 產品</a></li>
<li><a href="#">③ 服務</a></li>
<li><a href="#">④ 關於</a></li>
</ul>
</body>
</html>
.navbar {
list-style: none;
border: 1px solid #ccc;
/*
加一個背景色也沒效果:
background: pink;
*/
}
.navbar>li {
float: left;
margin-left: 15px;
}
/*
🚀由於浮動元素脫離了文檔流,所以它的父元素是看不見他的。
這裡對於 navbar 來說,它認為裡邊沒有什麼 li 來把它撐開。
因為 li 已經浮動了,那沒有東西撐開它,它就會認為高度為 0。
*/
🔗源碼及效果展示
https://jsbin.com/behomudiji/edit?html,css,output
<ul class="navbar">
<li><a href="#">① 首頁</a></li>
<li><a href="#">② 產品</a></li>
<li><a href="#">③ 服務</a></li>
<li><a href="#">④ 關於</a></li>
<li class="clear"></li>
<!-- 🚀想解決這個沒辦法撐開的問題,那麼就要求這個源文檔中要有一個沒有被浮動的的元素——普通元素。-->
</ul>
.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="#">① 首頁</a></li>
<li><a href="#">② 產品</a></li>
<li><a href="#">③ 服務</a></li>
<li><a href="#">④ 關於</a></li>
</ul>
.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 這個父容器。
*/
為了通用性,我們常常 .clearfix::after; ——就是為了修復浮動所產生的問題。
HTML
<ul class="navbar clearfix">
<!-- 🚀凡是需要清除浮動的地方我們都可以加一個這個樣式就可以通用! -->
<li><a href="#">① 首頁</a></li>
<li><a href="#">② 產品</a></li>
<li><a href="#">③ 服務</a></li>
<li><a href="#">④ 關於</a></li>
</ul>
.navbar {
list-style: none;
border: 1px solid #ccc;
}
.navbar>li {
float: left;
margin-left: 15px;
}
.clearfix::after {
/*
🚀為了通用性,我們直接 clearfix。然後在 HTML 文檔中,
哪裡需要清除浮動,就直接加一個這個類名進去就可以了。
*/
content: "";
display: block;
clear: both;
}
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>
.menu {
float: left;
width: 150px;
height: 300px;
color: #fff;
background: red;
}
.aside {
float: right;
width: 150px;
height: 300px;
color: #fff;
background: red;
}
.main {
height: 200px;
margin-right: 160px;
margin-left: 160px;
color: #fff;
background: blue;
}
#footer {
color: #fff;
background: grey;
}
.clearfix::after {
/*
🚀為了通用性,我們直接 clearfix,然後在 HTML 文檔中,哪裡需要清除浮動,
就直接加一個這個類名進去就可以了。
*/
content: "";
display: block;
clear: both;
}
🏆小總結:
所以以後我們想去實現一個水平布局,就有了兩種方法:
兩個浮動元素,如果因放不下導致其中一個下移,對下移的元素設置負 margin 值大於自身的寬度可將其上移。
🔗源碼及效果展示HTML
<div class="container">
<div class="box box1">box1</div>
<div class="box box2">box2</div>
</div>
* {
margin: 0
}
.container {
width: 400px;
height: 400px;
border: 1px solid red;
}
.box1 {
float: left;
width: 300px;
height: 100px;
background: pink;
}
.box2 {
float: left;
width: 110px;
height: 100px;
margin-left: -10px;
/* 🚀瀏覽器計算的時候就相當於寬度減去這個 10,然後就是 100,那就正好放上去。 */
background-color: red;
}