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

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

水平居中

  • 對於行內元素: text-align: center;css

  • 對於肯定寬度的塊級元素:html

  1. width和margin實現。margin: 0 auto;瀏覽器

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

  • 對於寬度未知的塊級元素
  1. table標籤配合margin左右auto實現水平居中。使用table標籤(或直接將塊級元素設值爲display:table),再經過給該標籤添加左右margin爲auto。佈局

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

  3. 絕對定位+transform,translateX能夠移動自己元素的50%。字體

  4. flex佈局使用justify-content:centerflex

垂直居中

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

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

  3. 彈性佈局flex:父級設置display: flex; 子級設置margin爲auto實現自適應居中

  4. 父級設置相對定位,子級設置絕對定位,而且經過位移transform實現

  5. table佈局,父級經過轉換成表格形式,而後子級設置vertical-align實現。(須要注意的是:vertical-align: middle使用的前提條件是內聯元素以及display值爲table-cell的元素)。

2、浮動佈局的優勢?有什麼缺點?清除浮動有哪些方式?

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

優勢

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

缺點

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

清除浮動的方式

  1. 添加額外標籤
<div class="parent">
    //添加額外標籤而且添加clear屬性
    <div style="clear:both"></div>
    //也能夠加一個br標籤
</div>
複製代碼
  1. 父級添加overflow屬性,或者設置高度
<div class="parent" style="overflow:hidden">//auto 也能夠
    //將父元素的overflow設置爲hidden
    <div class="f"></div>
</div>
複製代碼
  1. 創建僞類選擇器清除浮動(推薦)
//在css中添加:after僞元素
.parent:after{
    /* 設置添加子元素的內容是空 */
      content: '';  
      /* 設置添加子元素爲塊級元素 */
      display: block;
      /* 設置添加的子元素的高度0 */
      height: 0;
      /* 設置添加子元素看不見 */
      visibility: hidden;
      /* 設置clear:both */
      clear: both;
}
<div class="parent">
    <div class="f"></div>
</div>
複製代碼

3、 使用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 class="container">
      <div class="left"></div>
      <div class="right"></div>
    </div>
  </body>
</html>
複製代碼

效果以下:

產生空白的緣由

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

解決辦法

1. 將子元素標籤的結束符和下一個標籤的開始符寫在同一行或把全部子標籤寫在同一行

<div class="container">
  <div class="left"></div><div class="right"></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是同理
複製代碼

4、佈局題: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 class="outer_wrapper">
      <div class="inner_wrapper">
        <div class="box">A</div>
      </div>
    </div>
  </body>
</html>
複製代碼

強調兩點:

  1. padding-bottom到底是相對於誰的?

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

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

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

相對於父元素的(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 class="wrapper">
      <div class="box">A</div>
    </div>
  </body>
</html>
複製代碼

效果以下:

5、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 class="div1">1</div>
  <div class="div2">2</div>
  <div class="div3">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 class="div1">1</div>
    <div class="div2">2</div>
    <div class="div3">3</div>
  </body>
</html>
複製代碼

效果:

6、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 class="header">這裏是頭部</div>
    <div class="container">
        <div class="left">左邊</div>
        <div class="middle">中間部分</div>
        <div class="right">右邊</div>
    </div>
    <div class="footer">這裏是底部</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 class="header">這裏是頭部</div>
  <div class="container">
    <div class="middle">中間部分</div>
    <div class="left">左邊</div>
    <div class="right">右邊</div>
  </div>
  <div class="footer">這裏是底部</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 class="header">這裏是頭部</div>
  <div class="container">
    <div class="left">左邊</div>
    <div class="right">右邊</div>
    <div class="middle">中間部分</div>
  </div>
  <div class="footer">這裏是底部</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 class="header">這裏是頭部</div>
  <div class="container">
    <div class="left">左邊</div>
    <div class="right">右邊</div>
    <div class="middle">中間部分</div>
  </div>
  <div class="footer">這裏是底部</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不友好,知道就能夠,這裏就不浪費篇幅了。

7、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 class="container">
    <div class="center">
        <div class="inner">雙飛翼佈局</div>
    </div>
    <div class="left"></div>
    <div class="right"></div>
</article>
</body>

</html>
複製代碼

8、什麼是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 class="container">
      <div class="inner"></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 class="container">
    <div class="inner">1</div>
    <div class="inner">2</div>
    <div class="inner">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增長:

.bfc{
    overflow: hidden;
}
複製代碼

效果以下:

能夠明顯地看到間隔變大了,並且是原來的兩倍,符合咱們的預期。

關於CSS佈局問題,先分享到這裏,後續會不斷地補充,但願對你有所啓發。若是對你有幫助的話,別忘了幫忙點個贊哦。

參考文獻:

如何居中一個元素(終結版)

深刻理解BFC

CSS三欄佈局的4種方法

相關文章
相關標籤/搜索