剖析一些經典的CSS布局問題,為前端開發+面試保駕護航

2021-02-13 前端速報

(給前端速報加星標,提升前端技能)

作者:神三元

https://juejin.im/post/5da282015188257d2a1c9e1d

一、讓一個元素水平垂直居中,到底有多少種方案?
水平居中

width和margin實現。margin: 0 auto;

絕對定位和margin-left: -width/2, 前提是父元素position: relative

table標籤配合margin左右auto實現水平居中。使用table標籤(或直接將塊級元素設值為display:table),再通過給該標籤添加左右margin為auto。

inline-block實現水平居中方法。display:inline-block和text-align:center實現水平居中。

絕對定位+transform,translateX可以移動本身元素的50%。

flex布局使用justify-content:center


垂直居中

利用line-height實現居中,這種方法適合純文字類

通過設置父容器相對定位,子級設置絕對定位,標籤通過margin實現自適應居中

彈性布局flex:父級設置display: flex; 子級設置margin為auto實現自適應居中

父級設置相對定位,子級設置絕對定位,並且通過位移transform實現

table布局,父級通過轉換成表格形式,然後子級設置vertical-align實現。(需要注意的是:vertical-align: middle使用的前提條件是內聯元素以及display值為table-cell的元素)。


二、浮動布局的優點?有什麼缺點?清除浮動有哪些方式?

浮動布局簡介:當元素浮動以後可以向左或向右移動,直到它的外邊緣碰到包含它的框或者另外一個浮動元素的邊框為止。元素浮動以後會脫離正常的文檔流,所以文檔的普通流中的框就變現的好像浮動元素不存在一樣。

優點

這樣做的優點就是在圖文混排的時候可以很好的使文字環繞在圖片周圍。另外當元素浮動了起來之後,它有著塊級元素的一些性質例如可以設置寬高等,但它與inline-block還是有一些區別的,第一個就是關於橫向排序的時候,float可以設置方向而inline-block方向是固定的;還有一個就是inline-block在使用時有時會有空白間隙的問題


缺點

最明顯的缺點就是浮動元素一旦脫離了文檔流,就無法撐起父元素,會造成父級元素高度塌陷。


清除浮動的方式

添加額外標籤

<div>    //添加額外標籤並且添加clear屬性    <div style="clear:both"></div>    //也可以加一個br標籤</div>

父級添加overflow屬性,或者設置高度

<div style="overflow:hidden">//auto 也可以    //將父元素的overflow設置為hidden    <div></div></div>

建立偽類選擇器清除浮動(推薦)

//在css中添加:after偽元素.parent:after{    /* 設置添加子元素的內容是空 */      content: '';      /* 設置添加子元素為塊級元素 */      display: block;      /* 設置添加的子元素的高度0 */      height: 0;      /* 設置添加子元素看不見 */      visibility: hidden;      /* 設置clear:both */      clear: both;}<div>    <div></div></div>


三、 使用display:inline-block會產生什麼問題?解決方法?問題復現

問題: 兩個display:inline-block元素放到一起會產生一段空白。

如代碼:

<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <meta http-equiv="X-UA-Compatible" content="ie=edge">    <title>Document</title>    <style>      .container {        width: 800px;        height: 200px;      }
.left { font-size: 14px; background: red; display: inline-block; width: 100px; height: 100px; }
.right { font-size: 14px; background: blue; display: inline-block; width: 100px; height: 100px; }</style> </head> <body> <div> <div> 左 </div> <div> 右 </div> </div> </body></html>

效果如下:

產生空白的原因

元素被當成行內元素排版的時候,元素之間的空白符(空格、回車換行等)都會被瀏覽器處理,根據CSS中white-space屬性的處理方式(默認是normal,合併多餘空白),原來HTML代碼中的回車換行被轉成一個空白符,在字體不為0的情況下,空白符佔據一定寬度,所以inline-block的元素之間就出現了空隙。


解決辦法1. 將子元素標籤的結束符和下一個標籤的開始符寫在同一行或把所有子標籤寫在同一行
<div>  <div>      左  </div><div>      右  </div></div>


2. 父元素中設置font-size: 0,在子元素上重置正確的font-size
.container{  width:800px;  height:200px;  font-size: 0;}


3. 為子元素設置float:left
.left{  float: left;  font-size: 14px;  background: red;  display: inline-block;  width: 100px;  height: 100px;}//right是同理


四、布局題:div垂直居中,左右10px,高度始終為寬度一半

問題描述: 實現一個div垂直居中, 其距離屏幕左右兩邊各10px, 其高度始終是寬度的50%。同時div中有一個文字A,文字需要水平垂直居中。

思路一:利用height:0; padding-bottom: 50%;
<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <meta http-equiv="X-UA-Compatible" content="ie=edge">    <title>Document</title>    <style>      *{        margin: 0;        padding: 0;      }      html, body {        height: 100%;        width: 100%;      }      .outer_wrapper {        margin: 0 10px;        height: 100%;        /* flex布局讓塊垂直居中 */        display: flex;        align-items: center;      }      .inner_wrapper{        background: red;        position: relative;        width: 100%;        height: 0;        padding-bottom: 50%;      }      .box{        position: absolute;        width: 100%;        height: 100%;        display: flex;        justify-content: center;        align-items: center;        font-size: 20px;      }</style>  </head>  <body>    <div>      <div>        <div>A</div>      </div>    </div>  </body></html>

強調兩點:

padding-bottom究竟是相對於誰的?

答案是相對於父元素的width值。

那麼對於這個out_wrapper的用意就很好理解了。CSS呈流式布局,div默認寬度填滿,即100%大小,給out_wrapper設置margin: 0 10px;相當於讓左右分別減少了10px。

父元素相對定位,那絕對定位下的子元素寬高若設為百分比,是相對誰而言的?

相對於父元素的(content + padding)值, 注意不含border

延伸:如果子元素不是絕對定位,那寬高設為百分比是相對於父元素的寬高,標準盒模型下是content, IE盒模型是content+padding+border。


思路二: 利用calc和vw
<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <meta http-equiv="X-UA-Compatible" content="ie=edge">    <title>Document</title>    <style>      * {        padding: 0;        margin: 0;      }
html, body { width: 100%; height: 100%; }
.wrapper { position: relative; width: 100%; height: 100%; }
.box { margin-left: 10px; /* vw是視口的寬度, 1vw代表1%的視口寬度 */ width: calc(100vw - 20px); /* 寬度的一半 */ height: calc(50vw - 10px); position: absolute; background: red; /* 下面兩行讓塊垂直居中 */ top: 50%; transform: translateY(-50%); display: flex; align-items: center; justify-content: center; font-size: 20px; }</style> </head> <body> <div> <div>A</div> </div> </body></html>


效果如下:

五、CSS如何進行品字布局?第一種
<!doctype html><html>
<head> <meta charset="utf-8"> <title>品字布局</title> <style> * { margin: 0; padding: 0; } body { overflow: hidden; } div { margin: auto 0; width: 100px; height: 100px; background: red; font-size: 40px; line-height: 100px; color: #fff; text-align: center; }
.div1 { margin: 100px auto 0; }
.div2 { margin-left: 50%; background: green; float: left; transform: translateX(-100%); }
.div3 { background: blue; float: left; transform: translateX(-100%); }</style></head>
<body> <div>1</div> <div>2</div> <div>3</div></body>
</html>


效果:

第二種(全屏版)
<!doctype html><html>  <head>    <meta charset="utf-8">    <title>品字布局</title>    <style>      * {        margin: 0;        padding: 0;      }
div { width: 100%; height: 100px; background: red; font-size: 40px; line-height: 100px; color: #fff; text-align: center; }
.div1 { margin: 0 auto 0; }
.div2 { background: green; float: left; width: 50%; }
.div3 { background: blue; float: left; width: 50%; }</style> </head>
<body> <div>1</div> <div>2</div> <div>3</div> </body></html>


效果:

六、CSS如何進行聖杯布局

聖杯布局如圖:

而且要做到左右寬度固定,中間寬度自適應。


1.利用flex布局
<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Document</title>  <style>    *{      margin: 0;      padding: 0;    }    .header,.footer{        height:40px;        width:100%;        background:red;    }    .container{        display: flex;    }    .middle{        flex: 1;        background:yellow;    }    .left{        width:200px;        background:pink;    }    .right{        background: aqua;        width:300px;    }</style></head><body>    <div>這裡是頭部</div>    <div>        <div>左邊</div>        <div>中間部分</div>        <div>右邊</div>    </div>    <div>這裡是底部</div></body></html>


2.float布局(全部float:left)
<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ margin: 0; padding: 0; } .header, .footer { height: 40px; width: 100%; background: red; }
.footer { clear: both; }
.container { padding-left: 200px; padding-right: 250px; }
.container div { position: relative; float: left; }
.middle { width: 100%; background: yellow; }
.left { width: 200px; background: pink; margin-left: -100%; left: -200px; }
.right { width: 250px; background: aqua; margin-left: -250px; left: 250px; }</style></head>
<body> <div>這裡是頭部</div> <div> <div>中間部分</div> <div>左邊</div> <div>右邊</div> </div> <div>這裡是底部</div></body>
</html>

這種float布局是最難理解的,主要是浮動後的負margin操作,這裡重點強調一下。

設置負margin和left值之前是這樣子:

左邊的盒子設置margin-left: -100%是將盒子拉上去,效果:

.left{  /* ... */  margin-left: -100%;}

然後向左移動200px來填充空下來的padding-left部分

.left{    margin-left: -100%;  left: -200px;}

效果呈現:

右邊的盒子設置margin-left: -250px後,盒子在該行所佔空間為0,因此直接到上面的middle塊中,效果:

.right{  /* ... */  margin-left: -250px;}

然後向右移動250px, 填充父容器的padding-right部分:

.right{  /* ... */  margin-left: -250px;  left: 250px;}

現在就達到最後的效果了:

3.float布局(左邊float: left, 右邊float: right)
<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ margin: 0; padding: 0; } .header, .footer { height: 40px; width: 100%; background: red; } .container{ overflow: hidden; }
.middle { background: yellow; }
.left { float: left; width: 200px; background: pink; }
.right { float: right; width: 250px; background: aqua; }</style></head>
<body> <div>這裡是頭部</div> <div> <div>左邊</div> <div>右邊</div> <div>中間部分</div> </div> <div>這裡是底部</div></body>
</html>


4. 絕對定位
<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ margin: 0; padding: 0; } .header, .footer { height: 40px; width: 100%; background: red; } .container{ min-height: 1.2em; position: relative; }
.container>div { position: absolute; }
.middle { left: 200px; right: 250px; background: yellow; }
.left { left: 0; width: 200px; background: pink; }
.right { right: 0; width: 250px; background: aqua; }</style></head>
<body> <div>這裡是頭部</div> <div> <div>左邊</div> <div>右邊</div> <div>中間部分</div> </div> <div>這裡是底部</div></body>
</html>


5.grid布局
<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> body{ display: grid; } #header{ background: red; grid-row:1; grid-column:1/5; }
#left{ grid-row:2; grid-column:1/2; background: orange; } #right{ grid-row:2; grid-column:4/5; background: cadetblue; } #middle{ grid-row:2; grid-column:2/4; background: rebeccapurple } #footer{ background: gold; grid-row:3; grid-column:1/5; }</style></head>
<body> <div id="header">header</div> <div id="left">left</div> <div id="middle">middle</div> <div id="right">right</div> <div id="footer">footer</footer></div>
</body>
</html>

看看grid布局,其實也挺簡單的吧,裡面的參數應該不言而喻了。

另外說一點,到2019年為止,grid現在絕大多數瀏覽器已經可以兼容了,可以著手使用了。

當然,還有table布局,年代比較久遠了,而且對SEO不友好,知道就可以,這裡就不浪費篇幅了。


七、CSS如何實現雙飛翼布局?

有了聖杯布局的鋪墊,雙飛翼布局也就問題不大啦。這裡採用經典的float布局來完成。

<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> *{ margin: 0; padding: 0; } .container { min-width: 600px; } .left { float: left; width: 200px; height: 400px; background: red; margin-left: -100%; } .center { float: left; width: 100%; height: 500px; background: yellow; } .center .inner { margin: 0 200px; } .right { float: left; width: 200px; height: 400px; background: blue; margin-left: -200px; }</style></head>
<body> <article> <div> <div>雙飛翼布局</div> </div> <div></div> <div></div></article></body>
</html>複製代碼


八、什麼是BFC?什麼條件下會觸發?渲染規則?應用場景有哪些?
1.什麼是BFC?

W3C對BFC的定義如下:浮動元素和絕對定位元素,非塊級盒子的塊級容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不為"visiable"的塊級盒子,都會為他們的內容創建新的BFC(Block Fromatting Context, 即塊級格式上下文)。


2.觸發條件

一個HTML元素要創建BFC,則滿足下列的任意一個或多個條件即可:下列方式會創建塊格式化上下文:

根元素()

浮動元素(元素的 float 不是 none)

絕對定位元素(元素的 position 為 absolute 或 fixed)

行內塊元素(元素的 display 為 inline-block)

表格單元格(元素的 display為 table-cell,HTML表格單元格默認為該值)

表格標題(元素的 display 為 table-caption,HTML表格標題默認為該值)

匿名表格單元格元素(元素的 display為 table、table-row、 table-row-group、table-header-group、table-footer-group(分別是HTML table、row、tbody、thead、tfoot的默認屬性)或 inline-table)

overflow 值不為 visible 的塊元素-彈性元素(display為 flex 或 inline-flex元素的直接子元素)

網格元素(display為 grid 或 inline-grid 元素的直接子元素)等等。


3.BFC渲染規則

(1)BFC垂直方向邊距重疊

(2)BFC的區域不會與浮動元素的box重疊

(3)BFC是一個獨立的容器,外面的元素不會影響裡面的元素

(4)計算BFC高度的時候浮動元素也會參與計算


4.應用場景1. 防止浮動導致父元素高度塌陷

現有如下頁面代碼:

<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <meta http-equiv="X-UA-Compatible" content="ie=edge">    <title>Document</title>    <style>      .container {        border: 10px solid red;      }      .inner {        background: #08BDEB;        height: 100px;        width: 100px;      }</style>  </head>  <body>    <div>      <div></div>    </div>  </body></html>

接下來將inner元素設為浮動:

  .inner {    float: left;    background: #08BDEB;    height: 100px;    width: 100px;  }

會產生這樣的塌陷效果:

但如果我們對父元素設置BFC後, 這樣的問題就解決了:

.container {    border: 10px solid red;    overflow: hidden;}

同時這也是清除浮動的一種方式。

2. 避免外邊距摺疊

兩個塊同一個BFC會造成外邊距摺疊,但如果對這兩個塊分別設置BFC,那麼邊距重疊的問題就不存在了。

現有代碼如下:

<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .container { background-color: green; overflow: hidden; }
.inner { background-color: lightblue; margin: 10px 0; }</style></head>
<body> <div> <div>1</div> <div>2</div> <div>3</div> </div></body>
</html>

此時三個元素的上下間隔都是10px, 因為三個元素同屬於一個BFC。現在我們做如下操作:

  <div class="container">    <div class="inner">1</div>    <div class="bfc">      <div class="inner">2</div>    </div>    <div class="inner">3</div>  </div>

style增加:

效果如下:

可以明顯地看到間隔變大了,而且是原來的兩倍,符合我們的預期。

關於CSS布局問題,先分享到這裡,後續會不斷地補充,希望對你有所啟發。如果對你有幫助的話,別忘了幫忙點個讚哦。

本文對你有幫助?請分享給更多人!

關注「前端速報」,提升前端技能!

相關焦點

  • CSS 布局經典問題初步整理
    本文主要對 CSS 布局中常見的經典問題進行簡單說明,並提供相關解決方案的參考連結,涉及到三欄式布局,負 margin,清除浮動,
  • 合格前端開發該了解的css知識
    css在現階段的前端面試中佔得比重確實低,有些公司甚至都只是一筆帶過。
  • web前端開發面試題一之(html,css)
    看全部問題和答案點這裡(https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions/Questions-and-Answers)本文由我收集總結了一些前端面試題,初學者閱後也要用心鑽研其中的原理,重要知識需要系統學習、透徹學習,形成自己的知識鏈。
  • 2020最新Web前端經典面試題試題及答案(持續更新)-開課吧
    Web前端面試題Web前端面試題:說說你對webpack的看法解析:webpack是一個模塊打包工具,可以使用webpack能很好的管理、打包web開發中所用到的HTML、js、css以及各種靜態文件(圖片、字體等),讓開發過程更加高效。對於不同類型的資源,webpack有對應的模塊加載器。webpack模塊打包器會分析模塊間的依賴關係,最後生成了優化且合併後的靜態資源。
  • 2020 年前端面試複習必讀文章【超三百篇】
    5b83cb5ae51d4538cc3ec354[37]當 async/await 遇上 forEach: https://objcer.com/2017/10/12/async-await-with-forEach/[38]Promise 必知必會(十道題): https://juejin.im/post/5a04066351882517c416715d[39]BAT前端經典面試問題
  • 【乾貨】各大網際網路公司前端筆試面試題–HTML,CSS篇
    很多面試題是我自己面試BAT親身經歷碰到的。整理分享出來希望更多的前端er共同進步吧,不僅適用於求職者,對於鞏固複習前端基礎更是大有裨益。而更多的題目是我一路以來收集的,也有往年的,答案不確保一定正確,如有錯誤或有更好的解法,還請斧正。前面幾題是會很基礎,越下越有深度。1.你做的頁面在哪些流覽器測試過?
  • 前端開發必備的CSS命名規範與常用CSS代碼集合
    編輯 | web前端開發來源 | web前端開發我們在用html+css進行網頁的排版布局時,
  • 萬人血書的前端開發自學資料,俺肝出來了!
    寫在前面之前就有不少小夥伴提需求說:以後想從事前端開發崗,能不能整理一波前端開發的自學資料+書籍,正好得空,這個事情還是先安排了吧!不得不說,前端技術棧更新實在太快了,框架的版本發得也是賊勤。這種情況下,除了一些經典的知識可以看書之外,還是得多培養閱讀官方文檔的習慣,這個既是必須,也是賴以生存的技能。」HTML
  • 說說那些經典的web前端面試題-開發及性能優化
    1、規避javascript多人開發函數重名問題命名空間封閉空間js模塊化mvc(數據層、表現層、控制層)seajs4、web前端開發,如何提高頁面性能優化?Image):優化圖片不要在 HTML 中使用縮放圖片使用恰當的圖片格式使用 CSS Sprites 技巧對圖片優化5、前端開發中
  • css布局史 - grid一統天下
    而作為前端三劍客的css呢?似乎css3已經是很久很久的事情了,久到了我們不知道它是否還在更新,css是否還有新的技術產生。雖然各種scss,stylus,less預處理器提高了我們代碼的開發和維護,但是css依然缺少一個一擊致命,一劍封喉的技術。
  • 關於CSS不得不知的9條面試經驗
    本文主要介紹面試中常會遇到的CSS問題,並提供一些建議性的答案。「金三銀四」不可錯過,春節後要換工作的小夥伴們,該準備起來嘍!一、指代不同1、CSS3:是CSS技術的升級版本,於1999年開始制訂,2001年5月23日W3C完成了CSS3的工作草案。
  • 前端html,css基本知識
    上一篇講到過html和css相當於人的身體和衣服的關係,html的歷史發展百度上可以搜到,這裡簡單了解一下,1989年開發出了世界上第一個Web伺服器與Web客戶端,並將這項發明取名為world wide web,也就是我們現在所說的WWW全球資訊網。HTML也因此誕生。
  • 《前端開發》第一節:10天教你學會用Html和CSS寫簡單網頁
    最近粉絲留言很多,有些粉絲想學習編程,我是08年入這個行業,在前端開發和後端開發都有多年相關經驗。一直想分享我的學習心得給大家,感謝有百家號這樣好的平臺。從今天開始我計劃做一些入門型基礎的教程給大家學習。希望給喜歡的人打開編程的大門。
  • 我做前端技術面試官的一些體會
    ,之前的前端老大離職後,自己就扛起了一些前端方面的事務。技能樹上會一點的、懂一點就寫熟悉、精通什麼的,面試時被問到就是大大的減分項。寫了解什麼的,還說明這人比較誠實,但是也可能因為技能看起來不夠而失去面試機會。面試:面試就比較有意思了,會遇到各種各樣的人。先說說我自己的一些特點,因為這個會影響到求職者的態度。
  • 自學web前端怎麼學?web前端學習路線css屬性
    自學web前端技術,如果才能找到一份web前端的工作。按照現在的招聘標準來看,無論你去哪個公司面試,你只需要滿足他們公司的需求就可以。找到一份web前端工作需要掌握的內容如下:首先是html,css這些簡單的靜態布局這是最基本的學習內容,不在多說。
  • 高級前端開發工程師總結:8個不可錯過的CSS開發工具
    CSS是Web開發的基礎之一。但是,我們中的一些人卻感到非常困惑。這是因為我們沒有遵循適當的學習流程,因此我們很難理解CSS的行為。本文旨在通過兩種方式為你提供CSS的學習幫助:藉助專用工具對CSS進行編碼以及通過一些交互環境學習CSS,下面和千鋒廣州小編一起來看看吧!
  • 【推薦收藏】高頻前端開發面試問題及答案整理
    一、該方法中必須為需要清除浮動元素的偽對象中設置 height:0,否則該元素會比實際高出若干像素;浮動元素引起的問題和解決辦法?通過判斷Global對象是否為window,如果不為window,當前腳本沒有運行在瀏覽器中其他問題?你遇到過比較難的技術問題是?你是如何解決的?列舉IE 與其他瀏覽器不一樣的特性?什麼叫優雅降級和漸進增強?
  • 360子公司,華閱文化前端面試 面試題,技術問題,邏輯題詳解
    3.看一段css樣式,寫出div的樣子。4盒子margin10,padding10,border2px盒子高度為px,總高度為100px.css實現!5清除浮動的方法,列舉6對flex布局的了解。實現一下表格。
  • 11 - 前端開發 - CSS 選擇器
    DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>CSS 選擇器</title> <style type="text/css"> li{color: red}</style></head>
  • 好程式設計師web前端培訓分享HTML/CSS部分面試題
    好程式設計師web前端培訓分享HTML/CSS部分面試題。準備參加web前端面試的小夥伴們一起看一看吧,希望能夠對大家有所幫助! 4個部分一起構成了css中元素的盒模型。 2、行內元素有哪些?塊級元素有哪些? 空(void)元素有那些?