前端不得不瞭解的 Flex 佈局

zs4336發表於2019-11-14

Mt837Q

背景

又雙叒叕被老大拉來頂替前端小姐姐擼程式碼,接觸到了Flex佈局,以前只聽過沒用過,碰巧這次要揭露她的面紗,就記錄一下。接觸前端的同學都應該知道網頁佈局是CSS的一個重點,佈局的傳統方案都是基於盒模型的,依賴於 displaypositionfloat等屬性進行網頁佈局。然而對於那些複雜特殊的佈局實現起來不是很方便,比如讓文字行內垂直居中,我們需要容器高度height和行高line-height一樣。Flex佈局呼之欲出,它可以簡便、完整、響應式的實現各種佈局,下面就介紹下Flex佈局。

瞭解一些基礎知識

什麼是 Flex 佈局

Flex 是 Flexible Box,字面意思理解為彈性盒子。
任何一個容器都可以指定為Flex佈局

    .box{
      display:flex;
    }
    .box{
      display: -webkit-inline-flex;
      display:inline-flex; /*行內 flex 佈局*/
    }
    .box{
      display:-webkit-flex;
      display:flex; /*Webkit 核心的瀏覽器,必須加上-webkit字首*/
    }

基本概念

在使用Flex佈局之前,我們需要知道,什麼是容器,什麼是專案,什麼是主軸、交叉軸,主軸開始位置,主軸結束位置,交叉軸開始位置,交叉軸結束位置,單個專案佔據的主軸空間和交叉軸空間。

  • 容器:採用 Flex 佈局的元素,簡稱容器(flex container)
  • 專案:容器所有子元素自動成為容器成員,簡稱專案(flex item)
  • 容器預設存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)
  • 主軸的開始位置叫做 main start,結束位置叫做 main end;交叉軸的開始位置叫做 cross start,結束位置叫做 cross end
  • 單個專案佔據的主軸空間叫做 main size,佔據的交叉軸空間叫做 cross size

MtQrWV

容器的屬性

有6個屬性可以設定在容器上,分別是flex-directionflex-wrapflex-flowjustify-contentalign-itemsalign-content

1、flex-direction 屬性決定主軸的方向(即專案的排列方向)

    .box {
      flex-direction: row | row-reverse | column | column-reverse;
      /*水平方向,起點在左端|水平方向,起點在右端|垂直方向,起點在上沿|垂直方向,起點在下沿*/
    }

2、flex-wrap 屬性預設情況下,專案都排在一條線(又稱"軸線")上。它定義,如果一條軸線排不下,如何換行

    .box{
      flex-wrap: nowrap | wrap | wrap-reverse;
      /*不換行|換行,第一行在上方|換行,第一行在下方*/
    }

3、flex-flow 屬性是 flex-direction 屬性和 flex-wrap 屬性的簡寫形式,預設值為 row nowrap

    .box{
      flex-flow: flex-direction | flex-wrap;
    }

4、justify-content 屬性定義了專案在主軸上的對齊方式

    .box {
      justify-content: flex-start | flex-end | center | space-between | space-around;
      /*
          左對齊|右對齊|居中對齊|兩端對齊,專案之前的間隔都相等|每個專案兩側的間隔相等。
          所以,專案之間的間隔比專案與邊框的間隔大一倍
      */
    }

5、align-items 屬性定義專案在交叉軸上如何對齊

    .box {
      align-items: flex-start | flex-end | center | baseline | stretch;
      /*
          起點對齊|終點對齊|中點對齊|專案的第一行文字的基線對齊|如果專案未設定高度或設為auto,
          將佔滿整個容器的高度
      */
    }

6、align-content 屬性定義了多根軸線的對齊方式。如果專案只有一根軸線,該屬性不起作用

    .box {
      align-content: flex-start | flex-end | center | space-between | space-around | stretch;
    }
    /*
      與交叉軸的起點對齊|與交叉軸的終點對齊|與交叉軸的中點對齊|與交叉軸兩端對齊,軸線之間的間隔平均分佈|
      每根軸線兩側的間隔都相等。所以,軸線之間的間隔比軸線與邊框的間隔大一倍|軸線佔滿整個交叉軸
    */

自己理解的,僅供參考:
主要配置容器的屬性:主軸方向,換行方式,專案對齊方式,簡稱方杭琪(諧音像朋友的名字)

專案的屬性

有6個屬性設定在專案上,分別是orderflex-growflex-shrinkflex-basisflexalign-self
1、order 屬性定義專案的排列順序。數值越小,排列越靠前,預設為0

    .item {
      order: <integer>;
    }

2、flex-grow 屬性定義專案的放大比例,預設為0,即如果存在剩餘空間,也不放大

    .item {
      flex-grow: <number>;; /* default 0 */
    }

3、flex-shrink 屬性定義了專案的縮小比例,預設為1,即如果空間不足,該專案將縮小

    .item {
      flex-shrink: <number>;; /* default 1 */
    }

4、flex-basis 屬性定義了在分配多餘空間之前,專案佔據的主軸空間(main size)。瀏覽器根據這個屬性,計算主軸是否有多餘空間。它的預設值為auto,即專案的本來大小

    .item {
      flex-basis: <length> | auto; /* default auto */
    }

5、flex 屬性是 flex-grow, flex-shrink 和 flex-basis 的簡寫,預設值為0 1 auto。後兩個屬性可選

    .item {
      flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
    }

6、align-self 屬性允許單個專案有與其他專案不一樣的對齊方式,可覆蓋 align-items 屬性。預設值為 auto ,表示繼承父元素的 align-items 屬性,如果沒有父元素,則等同於 stretch

    .item {
      align-self: auto | flex-start | flex-end | center | baseline | stretch;
    }

實踐一下

  <!DOCTYPE html>
  <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link href="/css/style.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
      <div class="first-face">
        <span class="pip"></span>
      </div>
      <div class="second-face">
        <span class="pip"></span>
        <span class="pip"></span>
      </div>
      <div class="third-face">
        <span class="pip"></span>
        <span class="pip"></span>
        <span class="pip"></span>
      </div>
      <div class="fourth-face">
        <div class="column">
          <span class="pip"></span>
          <span class="pip"></span>
        </div>
        <div class="column">
          <span class="pip"></span>
          <span class="pip"></span>
        </div>
      </div>
      <div class="fifth-face">
        <div class="column">
          <span class="pip"></span>
          <span class="pip"></span>
        </div>
        <div class="column">
          <span class="pip"></span>
        </div>
        <div class="column">
          <span class="pip"></span>
          <span class="pip"></span>
        </div>
      </div>
      <div class="sixth-face">
        <div class="column">
          <span class="pip"></span>
          <span class="pip"></span>
          <span class="pip"></span>
        </div>
        <div class="column">
          <span class="pip"></span>
          <span class="pip"></span>
          <span class="pip"></span>
        </div>
      </div>
    </body>
  </html>

樣式檔案 css/style.css

.first-face {
    display: flex;
    justify-content: center;
    align-items: center;
}

.second-face {
    display: flex;
    justify-content: space-between;
}

.second-face .pip:nth-of-type(2) {
    align-self: flex-end;
}

.third-face {
    display: flex;
    justify-content: space-between;
}

.third-face .pip:nth-of-type(2) {
    align-self: center;
}

.third-face .pip:nth-of-type(3) {
    align-self: flex-end;
}

.fourth-face, .sixth-face {
    display: flex;
    justify-content: space-between;
}

.fourth-face .column, .sixth-face .column {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

.fifth-face {
    display: flex;
    justify-content: space-between;
}

.fifth-face .column {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

.fifth-face .column:nth-of-type(2) {
    justify-content: center;
}

/* OTHER STYLES */

* {
    box-sizing: border-box;
}

html, body {
    height: 100%;
}

body {
    display: flex;
    align-items: center;
    justify-content: center;
    vertical-align: center;
    flex-wrap: wrap;
    align-content: center;
    font-family: 'Open Sans', sans-serif;

    background: linear-gradient(top, #222, #333);
}

[class$="face"] {
    margin: 16px;
    padding: 4px;

    background-color: #e7e7e7;
    width: 104px;
    height: 104px;
    object-fit: contain;

    box-shadow:
      inset 0 5px white, 
      inset 0 -5px #bbb,
      inset 5px 0 #d7d7d7, 
      inset -5px 0 #d7d7d7;

    border-radius: 10%;
}

.pip {
    display: block;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    margin: 4px;

    background-color: #333;
    box-shadow: inset 0 3px #111, inset 0 -3px #555;
}

實踐結果展示

MtQTSK

備註:感謝阮一峰大神的文章【Flex佈局教程

趁還沒掉光,趕緊給每根頭髮起個名字吧~

相關文章