CSS3彈性盒子

2023-03-23 12:08:07

傳統佈局與flex佈局

  1. 傳統佈局
  • 相容性好
  • 佈局繁瑣
  • 侷限性,不能在行動端很好地佈局
  1. flex 彈性佈局
  • 操作方便,佈局極為簡單,行動端應用很廣泛
  • PC 端瀏覽器支援情況不如行動端

flex 佈局的基本概念

Flexible Box 模型,通常被稱為 flexbox,是一種一維的佈局模型。它給 flexbox 的子元素之間提供了強大的空間分佈和對齊能力。
flexbox 是一種一維的佈局,是因為一個 flexbox 一次只能處理一個維度上的元素佈局,一行或者一列。作為對比的是另外一個二維佈局 CSS Grid Layout,可以同時處理行和列上的佈局。
在 CSS3 中給 display 屬性增加了新的屬性值 flex,如果一個元素被設定 display:flex,說明該元素為彈性佈局,也就是個彈性盒子。
特點:

  • 一維佈局
  • 任何一個容器都可以指定為 flex 佈局
  • 當我們為父盒子設為 flex 佈局以後,子元素的 float、clear 和 vertical-align 屬性將失效。
  • 這些叫法是一個意思,伸縮佈局 = 彈性佈局 = 伸縮盒佈局 = 彈性盒佈局 =flex佈局

當使用 flex 佈局時,首先想到的是兩根軸線 — 主軸(Main Axis)和交叉軸(Cross Axis)。主軸由 flex-direction 定義,另一根軸垂直於它。我們使用 flexbox 的所有屬性都跟這兩根軸線有關,flex 主要用這兩個軸來控制佈局
例如

上圖說明如下:

  • main axis 是主軸,該軸的開始為 main start,結束為 main end。
  • cross axis 是交叉軸,該軸的開始為 cross start,結束為 cross end。
  • flex item 是 flex 容器中的元素。
    在這個彈性盒子中,提供了一些屬性來操作這些元素

Flex 容器

檔案中採用了 flexbox 的區域就叫做 flex 容器。指定一個容器的屬性為display: flex | inline-flex即建立了一個flex 容器。完成這一步之後,容器中的直系子元素就會變為 flex 元素(flex item)。所有 CSS 屬性都會有一個初始值,所以 flex 容器中的所有 flex 元素都會有下列行為:

  • 元素排列為一行 (flex-direction 屬性的初始值是 row)。
  • 元素從主軸的起始線開始。
  • 元素不會在主維度方向拉伸,但是可以縮小。
  • 元素被拉伸來填充交叉軸大小。
  • flex-basis 屬性為 auto。
  • flex-wrap 屬性為 nowrap。
    這會讓你的元素呈線形排列,並且把自己的大小作為主軸上的大小。如果有太多元素超出容器,它們會溢位而不會換行。如果一些元素比其他元素高,那麼元素會沿交叉軸被拉伸來填滿它的大小。

flex 佈局父項常見屬性

常見父項屬性
以下有6個屬性是對父元素設定的

  • flex-direction:設定主軸的方向
  • justify-content:設定主軸上的子元素排列方式
  • flex-wrap:設定子元素是否換行
  • align-items:設定側軸上的子元素排列方式(單行)
  • align-content:設定側軸上的子元素的排列方式(多行)
  • flex-flow:複合屬性,相當於同時設定了 flex-direction 和 flex-wrap

flex-direction

該屬性指定了彈性子元素在父容器中的排列方向和順序。
其語法格式為:
flex-direction: row | row-reverse | column | column-reverse;

屬性值 描述
row 橫向從左到右排列,預設的排列方式。
row-reverse 反轉橫向排列,即從右往左排,最後一項排在最左邊
column 縱向排列,從上往下排
column-reverse 反轉縱向排列,即從下往上排,最後一項排在最上面

flex-direction:row

flex-direction:row-reverse

flex-direction:column

flex-direction:column-reverse

justify-content

justify-content設定主軸上的子元素排列方式
注意: 使用這個屬性之前一定要確定好主軸是哪個

屬性值 說明
flex-start 預設值,元素從容器的起始線排列
flex-end 從終止線開始排列
center 在主軸居中對齊
space-between flex容器除去flex item在主軸所佔的空間後,將剩餘空間平均分配到元素之間,所以元素之間間隔相等,就是兩側的flex item會貼著flex容器的邊
space-around flex容器除去flex item在主軸所佔的空間後,將剩餘空間平均分配到每個元素主軸的兩側,因為兩側空間會相加,所以最邊上的縫隙會比中間的縫隙小

假設flex-direction: row;

  • flex-start
  • flex-end
  • center
  • space-between
  • space-around

flex-wrap

指定彈性盒子的子元素換行方式。
其語法格式為:
flex-wrap: nowrap|wrap|wrap-reverse|initial|inherit;

屬性值 描述
nowrap 預設,不換行,彈性容器為單行。該情況下彈性子項可能會溢位容器,如果一行容納不下預設會等比例壓縮flex item
wrap 彈性容器為多行。該情況下彈性子項溢位的部分會被放置到新行,子項內部會發生斷行
wrap-reverse 反轉 wrap 排列,按從左往右,從下往上的順序排列,會換行,下一行在上一行的上方
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      div {
        width: 100px;
        height: 100px;
        color: black;
      }

      #content {
        width: 240px;
        height: 300px;
        background-color: white;
        border:1px  solid #000;

        display: flex;
        flex-wrap: nowrap;
      }
      .item1 {
        background-color: #ffe5b9;
      }
      .item2 {
        background-color: #eff8ff;
      }
      .item3 {
        background-color: #c9cbff;
      }
    </style>
  </head>
  <body>
    <div id="content">
      <div class="item1">1</div>
      <div class="item2">2</div>
      <div class="item3">3</div>
    </div>
  </body>
</html>

nowrap:由於沒有換行,且是彈性盒模型,一行放不下,所以盒子被壓縮成width:80px

wrap

wrap-reverse

align-items

設定側軸上的子元素排列方式(單行)
該屬性是控制子項在側軸(預設是y軸)上的排列方式 在子項為單項(單行)的時候使用

屬性值 說明
flex-start 貼著側軸起始線
flex-end 貼著側軸尾線
center 側軸上居中
stretch 未給flex item設定側軸上的長度時,將flex item拉伸到與flex容器側軸上的長度一樣長。如果flex item設定了側軸上的長度則stretch

假設flex-direction: row;

  • flex-start
  • flex-end
  • center
  • stretch: 這裡要子元素不設定高度才生效

align-content

設定側軸上的子元素的排列方式(多行)
設定子項在側軸上的排列方式 並且只能用於子項出現 換行 的情況(多行),在單行下是沒有效果的。

屬性值 說明
flex-start 貼著側軸起始線排列
flex-end 貼著側軸尾線排列
center 在側軸居中對齊
space-between flex容器除去flex item在側軸所佔的空間後,將剩餘空間平均分配到元素之間,所以元素之間間隔相等,就是兩側的flex item會貼著flex容器的邊
space-around flex容器除去flex item在側軸所佔的空間後,將剩餘空間平均分配到每個元素側軸的兩側,因為兩側空間會相加,所以最邊上的縫隙會比中間的縫隙小
stretch 拉伸子元素,使得子元素平均佔滿父元素側軸方向的長度,同樣注意子元素不能在側軸方向上設定長度,否則 stretch會失效

假設flex-direction: row;
flex-start

flex-end

center

space-between

space-around

stretch

align-content 和 align-items 區別

  • align-items 適用於單行情況下,對多行也生效,只有上對齊、下對齊、居中和 拉伸這些效果
  • align-content 適應於換行(多行)的情況下(單行情況下無效), 可以設定 上對齊、 下對齊、居中、拉伸以及平均分配剩餘空間等屬性值。
  • 總結就是單行用 align-items 多行用 align-content,判斷是否是單行就看有沒有分行

flex-flow

flex-flow 屬性是 flex-direction 和 flex-wrap 屬性的複合屬性
flex-flow:row wrap;等效於flex-direction: row;flex-wrap: wrap;

flex 佈局子項常見屬性

  • flex 子專案佔的份數
  • align-self 控制子項自己在側軸的排列方式
  • order屬性定義子項的排列順序(前後順序)

flex 屬性

flex是個複合屬性,屬性值只有一個不帶單位的數位時,與flex-grow等效, 父元素主軸長度大於子元素主軸長度總和時,子元素主軸長度=free space*(該元素的flex數位/所有子元素flex數位之和)

/* 關鍵字值 */
flex: auto;
flex: initial;
flex: none;

/* 一個值,無單位數位:flex-grow */
flex: 2;

/* 一個值,width/height: flex-basis */
flex: 10em;
flex: 30px;
flex: min-content;

/* 兩個值:flex-grow | flex-basis */
flex: 1 30px;

/* 兩個值:flex-grow | flex-shrink */
flex: 2 2;

/* 三個值:flex-grow | flex-shrink | flex-basis */
flex: 2 2 10%;

/*全域性屬性值 */
flex: inherit;
flex: initial;
flex: unset;

flex 屬性定義flex item分配剩餘空間(free space),用flex來表示佔多少份數。

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

舉例1: 第1個和第3個子元素都指定了寬度,free space=flex容器寬度-設定了寬度的子元素的寬度。因為只有第二個子元素指定flex:1,且flex容器有剩餘的空間,所以該子元素的寬度=free space*(1/1)=free space, 即它會把剩餘空間佔滿

section {
    display: flex;
    width: 60%;
    height: 150px;
    background-color: pink;
    margin: 0 auto;
}

section div:nth-child(1) {
    width: 100px;
    height: 150px;
    background-color: red;
}

section div:nth-child(2) {
    flex: 1;
    background-color: green;
}

section div:nth-child(3) {
    width: 100px;
    height: 150px;
    background-color: blue;
}
<section>
    <div></div>
    <div></div>
    <div></div>
</section>

舉例2:因為子元素都沒設定寬度,所以剩餘空間就是父元素的寬度。子元素都指定了flex,所以它們的寬度=free space*(本元素flex值/子元素flex值總和), 即flex數位是多少就佔父元素寬度的幾份

p {
    display: flex;
    width: 60%;
    height: 150px;
    background-color: pink;
    margin: 100px auto;
}

p span {
    flex: 1;
}

p span:nth-child(2) {
    flex: 2;
    background-color: purple;
}
<p>
    <span>1</span>
    <span>2</span>
    <span>3</span>
</p>

如果子元素都為flex:1;則子元素均分剩餘空間

p span {
    flex: 1;
}

align-self

控制子項自己在側軸上的排列方式
align-self 屬性允許單個子項有與其他子項不一樣的對齊方式,可覆蓋 align-items 屬性。

  • auto: 預設值,繼承父元素的 align-items 值,如果沒有父元素,則等同於 stretch
  • normal: 效果取決於當前的佈局模式
  • flex-start:flex 元素會對齊到 cross-axis 的首端。
  • flex-end:flex 元素會對齊到 cross-axis 的尾端。
  • center:flex 元素會對齊到 cross-axis 的中間,如果該元素的 cross-size 尺寸大於 flex 容器,將在兩個方向均等溢位。
span:nth-child(3) {
 /* 設定自己在側軸上的排列方式 */
 align-self: flex-end;
}

order

屬性定義專案的排列順序
數值越小,排列越靠近主軸起始線,預設為0。
注意:和 z-index 不一樣。

.item {
 order: <number>;
}