本文推薦 PC 端閱讀~
本文版權歸 「公衆號 | 前端一萬小時」 全部,未經受權,請勿轉載!
複製代碼
css_11
複製代碼
1. 有幾種定位方式?分別是如何實現定位的?參考點是什麼?使用場景是什麼?
2. z-index 有什麼做用?如何使用?
3. BFC 是什麼?如何生成 BFC?BFC 有什麼做用?舉例說明。
4. 在什麼場景下會出現外邊距合併?如何合併?如何不讓相鄰元素外邊距合併?給個父子外邊距合併的範例?
複製代碼
前言: 這一篇咱們主要探討「定位」和 BFC 是怎樣讓「盒子」動起來的。
學習方法依然是:打開 JS Bin ,拷貝代碼運行查看效果,而後搞定每一行代碼的前世此生。css
「定位」就是經過設置 position 屬性的值來脫離正常的文檔流。html
🔗源碼及效果展現
html前端
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box1">3</div>
複製代碼
css面試
.box1, .box2 {
width: 50px;
height: 50px;
border: 2px solid;
}
.box2 {
position: relative;
/* 🚀relative 是相對於它本來正常流的位置進行偏移, 視覺上看它是移動了,但它本來所佔用的文檔流的空間是沒有變化的, 對其餘元素來講,它仍是在那裏的,故其餘元素位置是不會有變化的 */
top: 10px;
left: 10px;
}
複製代碼
當你設置爲絕對定位後,文檔流上的其餘元素就看不見你了。就認爲你不存在!若是存在多個絕對定位元素,那麼這些絕對定位元素也互相看不見。
🔗源碼及效果展現
html瀏覽器
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box1">3</div>
複製代碼
cssbash
.box1, .box2 {
width: 50px;
height: 50px;
border: 2px solid;
}
.box2 {
position: absolute;
top: 10px;
left: 10px;
/*❓這個值是相對於誰作偏移呢? 答:首先它會從本身的父元素裏邊去找, 看看本身的父元素裏邊有沒有定位,這個定位包括 relative 、absolute 、fix , 若是有的話就相對於它; 若是沒有的話,就再從父元素的父元素裏邊去找,若是有的話就相對於它; 若是再沒有,就一直找到咱們的 body 。*/
}
複製代碼
🔗源碼及效果展現
htmlide
<div class="container">
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box1">3</div>
</div>
複製代碼
css佈局
html {
border: 3px solid blue;
/*3️⃣最後,若是都沒有,那麼 box2 的絕對定位值就相對於這裏,到頭了。*/
}
body {
margin: 40px;
border: 1px solid red;
/*2️⃣其次,若是下邊 container 沒有 position , 而這裏有定位(relative 、absolute 、fixed), 那麼 box2 的絕對定位值就相對於這裏: position: relative; */
}
container {
margin-top: 40px;
padding: 40px;
background: yellow;
/*1️⃣首先,若是 box2 父元素這裏有定位(relative 、absolute 、fixed), 那麼 box2 的絕對定位值就相對於這裏: position: relative; ⚠️而這裏用 relative 是最好的,由於一個元素自己設置 relative , 卻不設置值的話,就等同於沒設置。 那它就依然在普通流中,它仍是一個普通元素, 那它本身的位置也沒發生變更,卻能夠給其子元素做爲相對的錨點。 */
}
.box1, .box2 {
width: 50px;
height: 50px;
border: 2px solid;
}
.box2 {
position: absolute;
top: 0px;
left: 10px;
}
/*⚠️因此,咱們在使用絕對定位的時候,必定要設置好定位的參考點(錨點)。 通常來講,咱們絕對定位的參考點都是相對於其父容器。 因此原則上是:一個元素設置絕對定位 absolute , 那它的父容器設置定位爲 relative */
複製代碼
元素使用了絕對定位後,就如浮動同樣,有了「塊盒子」的特性。post
因爲使用絕對定位以後,產生元素覆蓋的問題,z-index 能夠解決元素之間覆蓋順序的問題,設置它的層疊順序。同級元素,數值越大,越靠近視覺點;不一樣父元素,只要父元素越大,那麼總體就越靠近視覺點,而無論其子元素大小狀況。學習
顯示器顯示的圖案是一個二維平面,用 x 軸和 y 軸來表示位置屬性。
爲了表示三維立體的概念,如顯示元素的上下層的疊加順序,引入了 z-index 屬性來表示 z 軸上一個元素在疊 加順序上的上下立體關係。
z-index 值較大的元素將疊加在 z-index 值較小的元素之上。對於未指定此屬性的定位對象,z-index 值爲正數的對象會在其之上,而 z-index 值爲負數的對象在其之下。
z-index 屬性適用於定位元素(position 屬性值爲 relative 或 absolute 或 fixed 的對象),用來肯定定位元素 在垂直於顯示屏方向(稱爲 Z 軸)上的層疊順序,也就是說若是元素是沒有定位的,對其設置的 z-index 會是無效的。
相同 z-index 誰上誰下?
父子關係處理:
position: fixed;
複製代碼
相對於瀏覽器的窗口進行定位。所以當滾動產生時,固定定位元素依然處於窗口的某個位置不動。
大布局、自適應,用「浮動」————浮動通常和響應式結合的比較多;
小元素、固定寬高,用「定位」————通常只適用於一些很小的 icon ;
🏆結合實際狀況是關鍵。
好比說,網頁頭像上的未讀消息,咱們通常都是選擇用「定位」才能很好的實現。凡是能蓋住其餘東西的也是「絕對定位」。
🔗源碼及效果展現
html
<nav>
<ul>
<li><a href="#">首頁</a></li>
<li><a href="#">做品</a></li>
<li><a href="#">更多</a>
<ul class="child">
<li><a href="#">GitHub</a></li>
<li><a href="#">博客</a></li>
<li><a href="#">知乎</a></li>
</ul>
</li>
</ul>
</nav>
複製代碼
css
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
a {
color: #333;
text-decoration: none;
}
nav {
width: 500px;
margin: 10px auto 0;
box-shadow: 0px 2px 4px 1px rgba(0,0,0,0.3);
/*🚀這裏邊的這幾個值:第1、二個值表示這個陰影的水平、垂直的偏移; 4px 表示模糊度;1px 是這個模糊的一個延展;rgba 是這個模糊的顏色。*/
}
nav::after {
content: '';
display: block;
clear: both;
}
/*🚀因爲咱們用了浮動,咱們須要清除浮動來撐開父容器。*/
nav>ul>li {
position: relative;
/*🚀🚀🚀給下邊 .child 的絕對定位」偏移值「加一個「錨點」。*/
float: left;
/*🚀把這個選擇器層級裏的 li 水平排列。*/
}
nav>ul>li:hover .child {
display: block;
}
/*🚀🚀 .child 默認是隱藏的,當我鼠標放到「更多」這個 li 上的時候才顯示, 並顯示爲 block 。*/
nav a {
display: block;
padding: 10px 10px;
/*記着,咱們要想點擊的範圍很大,咱們是須要在 a 連接上來加 padding 的。 若是在 li 上加 padding ,那麼點擊範圍依然在字上。*/
/*但要注意,因爲 a 連接是個行內元素,因此若是這裏只單單加 padding , 那其實他的寬高是沒有變化的,只是背景色變大了,它會出現不少諸如「遮擋」的後果。 故,咱們須要讓其顯示爲 block 。*/
/*咱們沒有用 inline-block 是由於:用 inline-block 即它同時仍是有行內特性, 會致使"收縮"——即寬度由文本內容寬度決定。 想要撐開,而不受內容寬度影響,那就須要用 block 。*/
min-width: 50px;
/*這裏加了一個「最小的寬度」的用途是把這個 a 連接裏邊的文字內容撐開, 使任何一個可點擊的文本都不換行。*/
}
nav a:hover {
color: #fff;
background: rgba(0,0,0,0.4);
}
nav .child {
position: absolute;
/*🚀🚀🚀設置了絕對定位,咱們才能夠想把這個 .child 放哪裏就放哪裏, 由於父容器發現不了它。而其餘方式(好比浮動、或不用)是達不到理想的效果的。*/
top: 100%;
/*100% 就表示按照 li 的高度。*/
box-shadow: 0px 2px 4px 1px rgba(0,0,0,0.3);
display: none;
/*🚀🚀 .child 默認是"隱藏"的——display: none , 當我鼠標放到「更多」這個 li 上的時候再顯示。*/
}
複製代碼
⚠️相關前置知識,請先閱讀文章:
《CSS——CSS 基本視覺格式化:① 「塊盒子」格式化》
《CSS——CSS 基本視覺格式化:② 「行內盒子」格式化》
每一個渲染區域用 fomating context 表示,它決定了其子元素如何去定位,以及和其餘元素的關係和相互做用。
BFC 全稱 Block Formating Context 。
display 屬性爲 block 、list-item 、table 的元素,會產生 BFC 。也就是「塊元素」。
若是一個元素增長了一個屬性叫 float ,那這個元素自己也產生了一個塊級格式化上下文。
咱們之因此要了解這個 BFC ,是由於咱們但願經過了解它的特性來實現咱們須要的一些效果。或者當出現了某個問題的時候,咱們可以去解釋這個問題,知道是爲何,進而解決它或找到替代方案。
① 在 BFC 中,盒子從頂部開始垂直地一個接一個的排列。
② 盒子垂直方向的距離由 margin 決定,屬於同一個 BFC 的兩個相鄰盒子的 margin 會發生重疊。
③在 BFC 中,每個盒子的左外邊距應該和包含塊的左邊接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此!
④ BFC 的區域不會與浮動的盒子產生交集,且是緊貼浮動的邊緣。
⑤ 計算 BFC 的高度時,浮動盒子的高度也參與計算。
⑥ BFC 就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素。反之也如此!
對應規則:⑤ 計算 BFC 的高度時,浮動盒子的高度也參與計算。
對應規則:② 盒子垂直方向的距離由 margin 決定,屬於同一個 BFC 的兩個相鄰盒子的 margin 會發生重疊。
對應規則: ③ 在 BFC 中,每個盒子的左外邊距應該和包含塊的左邊接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此! ④ BFC 的區域不會與浮動的盒子產生交集,且是緊貼浮動的邊緣。
❌問題:
🔗源碼及效果展現
<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>
複製代碼
.navbar {
list-style: none;
border: 1px solid #ccc;
/*加一個背景色也沒效果: background: pink;*/
}
.navbar>li {
float: left;
margin-left: 15px;
}
/*🚀因爲浮動元素脫離了文檔流,因此他的父元素是看不見他的。 這裏對於 navbar 來講,他認爲裏邊沒有什麼 li 來把它撐開, 由於 li 已經浮動了,那沒有東西撐開它,它就會認爲高度爲 0。*/
複製代碼
✔️解決方式:
經過「清除浮動」來解決——在文章《CSS——讓盒子動起來:①浮動》中已做解答;
經過給父元素建立 BFC ,添加 overflow: hidden;
樣式:
對應規則:⑤ 計算 BFC 的高度時,浮動盒子的高度也參與計算。
<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>
複製代碼
.navbar {
list-style: none;
border: 1px solid #ccc;
overflow: hidden;
}
.navbar>li {
float: left;
margin-left: 15px;
}
複製代碼
❌問題:
在文章《CSS——CSS 基本視覺格式化:① 塊盒子格式化》中,咱們知道:
垂直格式化的另外一個重要方面是垂直相鄰 margin 的合併。 這種合併行爲只應用於 margin,若是元素有 padding 和邊框,padding 和邊框是不會合並的。當兩個或更多垂直 margin 相遇時,他們將造成惟一一個 margin,這個 margin 的高度等於兩個發生疊加的 margin 的高度中的較大者。
⚠️注意:當一個元素包含在另外一個元素中時,彼此相鄰的 margin-bottom 和 magin-top 也會發生疊加,取較大者。
<div class="box1">1</div>
<div class="box2">2</div>
複製代碼
.box1 {
color: #fff;
width: 100px;
height: 100px;
margin-bottom: 50px;
background: blue;
}
.box2 {
color: #fff;
width: 100px;
height: 100px;
margin-top: 100px;
background: pink;
}
複製代碼
✔️解決方式:
將垂直方向上的盒子放在不一樣的 BFC 中,margin 就不會重疊了。
對應規則:② 盒子垂直方向的距離由 margin 決定,屬於同一個 BFC 的兩個相鄰盒子的 margin 會發生重疊。
<div class="box1">1</div>
<div class="ct">
<div class="box2">2</div>
</div>
<!--🚀咱們在 box2 的外層包裹一層容器,並觸發該容器生成一個 BFC 。 那麼兩個 box 就不屬於同一個 BFC ,就不會發生 margin 重疊了! -->
複製代碼
.ct {
overflow: hidden; /*🚀觸發該容器生成一個 BFC */
}
.box1 {
color: #fff;
width: 100px;
height: 100px;
margin-bottom: 50px;
background: blue;
}
.box2 {
color: #fff;
width: 100px;
height: 100px;
margin-top: 100px;
background: pink;
}
複製代碼
❓問題:
在文章《CSS——讓「盒子」動起來:① 浮動》中,咱們經過加 margin-left
或 margin-right
的方式製做「有縫隙」的兩欄佈局的效果。
❗️但若是要求兩欄佈局中間沒有縫隙,該怎麼辦呢?
❌因爲:
③ 在 BFC 中,每個盒子的左外邊距應該和包含塊的左邊接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此!
<div class="aside">側邊欄固定寬度</div>
<div class="main">Hey guys, 我正在這個平臺發放「前端一萬小時」這個專欄的一系列文章。<br>
這個專欄我已經完成了「從零基礎到就業」相關的文章。<br>
"從零基礎到就業"包含 150+ 篇乾貨文章,300+ 道經典筆試、面試題。<br>
若是你對本系列文章感興趣,歡迎關注 「公衆號:前端一萬小時」,
並點擊菜單欄「獲取所有文章」來加入咱們的「一萬小時計劃」!祝順利^^……
</div>
複製代碼
.aside {
color: #fff;
width: 150px;
height: 100px;
background: red;
float: left;
}
.main {
color: #fff;
background: blue;
height: 200px;
}
複製代碼
✔️解決方式:
④ BFC 的區域不會與浮動的盒子產生交集,且是緊貼浮動的邊緣。
經過觸發 main 生成 BFC ,來實現自適應無縫隙兩欄佈局:
.main {
overflow: hidden; /*🚀觸發 BFC */
}
.aside {
color: #fff;
width: 150px;
height: 100px;
background: red;
float: left;
}
.main {
color: #fff;
background: blue;
height: 200px;
}
複製代碼
後記:經過兩篇兄弟文章,咱們算是讓「盒子」動了起來,接下來 3 篇文章,咱們就讓「這個能夠動的盒子」更優雅的「展現」。
祝好,qdywxs ♥ you!