css_11 | CSS——讓「盒子」動起來:② 「定位」和 BFC

本文推薦 PC 端閱讀~

本文版權歸 「公衆號 | 前端一萬小時」 全部,未經受權,請勿轉載!
複製代碼

獲取編號.png

css_11
複製代碼

涉及面試題.png

1. 有幾種定位方式?分別是如何實現定位的?參考點是什麼?使用場景是什麼?
2. z-index 有什麼做用?如何使用?
3. BFC 是什麼?如何生成 BFC?BFC 有什麼做用?舉例說明。
4. 在什麼場景下會出現外邊距合併?如何合併?如何不讓相鄰元素外邊距合併?給個父子外邊距合併的範例?
複製代碼

前言: 這一篇咱們主要探討「定位」和 BFC 是怎樣讓「盒子」動起來的。
學習方法依然是:打開 JS Bin ,拷貝代碼運行查看效果,而後搞定每一行代碼的前世此生。css



1 什麼是「定位」

「定位」就是經過設置 position 屬性的值來脫離正常的文檔流html

2 「定位」分哪幾類

2.1 相對定位

🔗源碼及效果展現
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;
}
複製代碼

12-012.png

2.2 絕對定位

當你設置爲絕對定位後,文檔流上的其餘元素就看不見你了。就認爲你不存在!若是存在多個絕對定位元素,那麼這些絕對定位元素也互相看不見。
🔗源碼及效果展現
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 。*/
}
複製代碼

2.2.1 ❓絕對定位的值是相對誰來取值作偏移?

🔗源碼及效果展現
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 */
複製代碼

12-02.png

2.2.2 z-index

元素使用了絕對定位後,就如浮動同樣,有了「塊盒子」的特性。post

因爲使用絕對定位以後,產生元素覆蓋的問題,z-index 能夠解決元素之間覆蓋順序的問題,設置它的層疊順序。同級元素,數值越大,越靠近視覺點;不一樣父元素,只要父元素越大,那麼總體就越靠近視覺點,而無論其子元素大小狀況學習

  • 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 誰上誰下?

    • 若是兩個元素都沒有定位發生位置重合現象或者兩個都已定位元素且 z-index 相同發生位置重合現象,那麼 按文檔流順序,後面的覆蓋前面的。
    • 若是兩個元素都沒有設置 z-index ,使用默認值,一個定位一個沒有定位,那麼定位元素覆蓋未定位元素。
  • 父子關係處理:

    • 若是父元素 z-index 有效,那麼子元素不管是否設置 z-index 都和父元素一致,會在父元素上方;
    • 若是父元素 z-index 失效(未定位或者使用默認值),那麼定位子元素的 z-index 設置生效。

2.3 固定定位

position: fixed複製代碼

相對於瀏覽器的窗口進行定位。所以當滾動產生時,固定定位元素依然處於窗口的某個位置不動


3 用「定位」仍是用「浮動」

  • 大布局、自適應,用「浮動」————浮動通常和響應式結合的比較多;

  • 小元素、固定寬高,用「定位」————通常只適用於一些很小的 icon ;

🏆結合實際狀況是關鍵。
好比說,網頁頭像上的未讀消息,咱們通常都是選擇用「定位」才能很好的實現。凡是能蓋住其餘東西的也是「絕對定位」。


4 小實戰:實現 navbar

12-03.gif

🔗源碼及效果展現
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 上的時候再顯示。*/

}
複製代碼

5 BFC

⚠️相關前置知識,請先閱讀文章:
《CSS——CSS 基本視覺格式化:① 「塊盒子」格式化》
《CSS——CSS 基本視覺格式化:② 「行內盒子」格式化》

  • 在正常流中,盒子要麼屬於塊級格式化上下文,要麼屬於內聯格式化上下文。

每一個渲染區域用 fomating context 表示,它決定了其子元素如何去定位,以及和其餘元素的關係和相互做用。
BFC 全稱 Block Formating Context 。

  • BFC 是一個獨立的渲染區域如何佈局**,而且與這個區域外部絕不相關。

5.1 哪些元素會具備 BFC 的條件?

display 屬性爲 block 、list-item 、table 的元素,會產生 BFC 。也就是「塊元素」。

5.2 什麼狀況下可讓元素產生 BFC ?

  • float 屬性不爲 none :

若是一個元素增長了一個屬性叫 float ,那這個元素自己也產生了一個塊級格式化上下文。

  • position 爲 absolute 或 fixed ;
  • display 爲 inline-block、table-cells、flex、或者 inline-flex ;
  • overflow 不爲 visible (爲 hidden、auto、scroll )。

咱們之因此要了解這個 BFC ,是由於咱們但願經過了解它的特性來實現咱們須要的一些效果。或者當出現了某個問題的時候,咱們可以去解釋這個問題,知道是爲何,進而解決它或找到替代方案。

5.3 BFC 佈局規則特性

  • ① 在 BFC 中,盒子從頂部開始垂直地一個接一個的排列。

  • ② 盒子垂直方向的距離由 margin 決定,屬於同一個 BFC 的兩個相鄰盒子的 margin 會發生重疊。

  • ③在 BFC 中,每個盒子的左外邊距應該和包含塊的左邊接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此!

  • ④ BFC 的區域不會與浮動的盒子產生交集,且是緊貼浮動的邊緣。

  • ⑤ 計算 BFC 的高度時,浮動盒子的高度也參與計算。

  • ⑥ BFC 就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素。反之也如此!

5.4 BFC 常見的用途

  • 清除元素內部浮動

對應規則:⑤ 計算 BFC 的高度時,浮動盒子的高度也參與計算。

  • 解決外邊距合併問題

對應規則:② 盒子垂直方向的距離由 margin 決定,屬於同一個 BFC 的兩個相鄰盒子的 margin 會發生重疊。

  • 製做自適應兩欄佈局

對應規則: ③ 在 BFC 中,每個盒子的左外邊距應該和包含塊的左邊接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此! ④ BFC 的區域不會與浮動的盒子產生交集,且是緊貼浮動的邊緣。

5.4.1 清除元素內部浮動

❌問題:
🔗源碼及效果展現

<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。*/
複製代碼

✔️解決方式:

對應規則:⑤ 計算 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;
}
複製代碼

5.4.2 解決外邊距合併問題

❌問題:
在文章《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.png

✔️解決方式:
將垂直方向上的盒子放在不一樣的 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;
}
複製代碼

BFC-margin2.png

5.4.3 製做自適應兩欄佈局

❓問題:
在文章《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!


🏆答讀者問:

讀者提問——BFC.png
相關文章
相關標籤/搜索