CSS 定位機制
CSS 有三種基本的定位機制:普通流、浮動和絕對定位。
普通流
除非專門指定,否則所有框都在普通流中定位。也就是說,普通流中的元素的位置由元素在 (X)HTML 中的位置決定。
塊級框從上到下一個接一個地排列,框之間的垂直距離是由框的垂直外邊距計算出來。
行內框在一行中水平佈置。可以使用水平內邊距、邊框和外邊距調整它們的間距。但是,垂直內邊距、邊框和外邊距不影響行內框的高度。由一行形成的水平框稱為行框(Line Box),行框的高度總是足以容納它包含的所有行內框。不過,設定行高可以增加這個框的高度。
浮動
float 屬性定義元素在哪個方向浮動。浮動元素會生成一個塊級框,而不論它本身是何種元素。
float: left|right|none|inherit;
position定位
任何元素都可以定位,不過絕對或固定元素會生成一個塊級框,而不論該元素本身是什麼型別。相對定位元素會相對於它在正常流中的預設位置偏移。
float: absolute|fixed|relative|static|inherit;
什麼是塊級格式化上下文(BFC)
“BFC即 Block Formatting Contexts (塊級格式化上下文), 是 W3C CSS2.1 規範中的一個概念。它是頁面中的一塊渲染區域,並且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關係和相互作用。”
如何觸發BFC
- body 根元素
- 浮動元素:float 除 none 以外的值
- 絕對定位元素:position (absolute、fixed)
- display 為 inline-block、table-cells、flex、inline-flex、flow-root(沒有副作用的方案,但需注意相容性)、grid、inline-grid等
- overflow 除了 visible 以外的值 (hidden、auto、scroll)
BFC的特性
1、內部的Box會在垂直方向上一個接一個的放置
2、垂直方向上的距離由margin決定。(完整的說法是:屬於同一個BFC的兩個相鄰Box的margin會發生重疊(塌陷),與方向無關。)
3、每個元素的左外邊距與包含塊的左邊界相接觸(從左向右),即使浮動元素也是如此。(這說明BFC中子元素不會超出他的包含塊,而position為absolute的元素可以超出他的包含塊邊界)
4、BFC的區域不會與float的元素區域重疊
5、計算BFC的高度時,浮動子元素也參與計算
6、BFC就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面元素,反之亦然
BFC的應用
清除浮動(同時說明特性3、特性5、特性6)
<style>
.content-box {
background: #fff;
width: 300px;
border: 5px solid #FF4500;
}
.child1 {
width: 200px;
height: 200px;
background: #FFA500;
float: left;
}
</style>
<body>
<div class="content-box">
<div class="child1"></div>
</div>
</body>
複製程式碼
- 子元素浮動,脫離文件流,父元素高度只剩下border
<style>
.content-box {
background: #fff;
width: 300px;
border: 5px solid #FF4500;
overflow: hidden; // 讓父元素觸發BFC
}
.child1 {
width: 200px;
height: 200px;
background: #FFA500;
float: left;
}
</style>
複製程式碼
- 觸發父元素的BFC,父元素高度恢復,故計算BFC的高度時,浮動子元素也參與計算(特性5)
防止元素上下margin摺疊(同時說明特性2、特性6)
<style>
.content-box {
background: #fff;
width: 300px;
border: 5px solid #FF4500;
}
.child {
width: 200px;
height: 200px;
background: #FFA500;
margin: 50px auto;
}
</style>
<body>
<div class="content-box">
<div class="child"></div>
<div class="child"></div>
</div>
</body>
複製程式碼
- 兩個子元素的上下外邊距發生重疊,距離只差50px(應該為第一個子元素的bottom-margin+第二個元素的top-margin=100px)
<style>
.content-box {
background: #fff;
width: 300px;
border: 5px solid #FF4500;
}
.parent {
overflow: hidden; // 將外邊距摺疊的元素放入兩個不同的BFC容器中
}
.child {
width: 200px;
height: 200px;
background: #FFA500;
margin: 50px auto;
}
</style>
<body>
<div class="content-box">
<div class="parent">
<div class="child"></div>
</div>
<div class="parent">
<div class="child"></div>
</div>
</div>
</body>
複製程式碼
- 將發生外邊距重疊的子元素分別放入兩個BFC容器中,每個BFC都是一個獨立的容器
實現兩欄佈局
<style>
.content-box {
background: #fff;
width: 300px;
}
.left {
width: 200px;
height: 200px;
background: #FFA500;
float: left;
}
.right {
background: #FF4500;
color: #fff;
}
</style>
<body>
<div class="content-box">
<div class="left"></div>
<div class="right">
除非專門指定,否則所有框都在普通流中定位。也就是說,普通流中的元素的位置由元素在 (X)HTML 中的位置決定。
塊級框從上到下一個接一個地排列,框之間的垂直距離是由框的垂直外邊距計算出來。
行內框在一行中水平佈置。可以使用水平內邊距、邊框和外邊距調整它們的間距。但是,垂直內邊距、邊框和外邊距不影響行內框的高度。由一行形成的水平框稱為行框(Line
Box),行框的高度總是足以容納它包含的所有行內框。不過,設定行高可以增加這個框的高度。
</div>
</div>
</body>
複製程式碼
- 浮動元素會覆蓋未浮動元素,但文字不會被覆蓋。
<style>
.content-box {
background: #fff;
width: 300px;
}
.left {
width: 200px;
height: 200px;
background: #FFA500;
float: left;
}
.right {
background: #FF4500;
color: #fff;
overflow: hidden; // 右側未浮動元素,觸發BFC
}
</style>
<body>
<div class="content-box">
<div class="left"></div>
<div class="right">
除非專門指定,否則所有框都在普通流中定位。也就是說,普通流中的元素的位置由元素在 (X)HTML 中的位置決定。
塊級框從上到下一個接一個地排列,框之間的垂直距離是由框的垂直外邊距計算出來。
</div>
</div>
</body>
複製程式碼
- 未浮動元素觸發BFC,能避免被浮動元素覆蓋
實現同等高度的兩欄
<style>
.content-box {
background: #fff;
width: 300px;
overflow: hidden;
}
.content-box>div {
/* 注意這裡 */
padding-bottom: 100000px;
margin-bottom: -100000px;
}
.left {
background: #fadc09;
height: 300px;
width: 100px;
float: left;
}
.right {
height: 100px;
background: #faa509;
display: flow-root;
}
</style>
<body>
<div class="content-box">
<div class="left"></div>
<div class="right">
除非專門指定,否則所有框都在普通流
</div>
</div>
</body>
複製程式碼
總結
這讓我想起上一次面試的時候,面試題就是讓我實現這樣的兩欄佈局,然而小菜鳥的我,還不是很理解BFC原理竟然用flex,然後寫了好多樣式,而且還及其不智慧。哈哈哈~
以上三種對於BFC的應用都很普遍,再也不用新增新元素,用clear:both來清除浮動拉~
值得一說的是:就在我看了好多BFC相關的文章,學習了BFC相關的原理之後沒幾天,就有同事問我邊距被壓縮的問題,我一看就是邊距重疊了,都沒想就說你拿一個div包一下加個overflow:hidden啥的。瞬間感覺沒有白學呀,感覺自己挺牛逼呀~雖然我知道我其實還是一個小菜鳥。哈哈哈~
但是我會繼續努力噠~