Flex佈局常用屬性詳解

2023-07-05 15:00:54

1. Flex佈局與響應式佈局

1.1 為什麼需要響應式佈局?

在電腦PC端,使用浮動,定位同時使用畫素px單位就可以完成大部分佈局,而且佈局完之後不會有大問題,但是到了行動端,移動裝置的螢幕尺寸多種多樣,從小螢幕的智慧手機到大螢幕的平板電腦,甚至是可穿戴裝置,簡單地運用和PC端一樣的方式就會出現一些佈局和排列的問題。

這裡用PC端的縮放瀏覽器來舉個例子,當瀏覽器縮小的時候,百度就只顯示了一部分,無法在縮小的螢幕(瀏覽器視窗)中完全顯示。

 

 

 

移動前端中常說的 viewport (視口)就是瀏覽器中用於呈現網頁的區域。視口通常並不等於螢幕大小,特別是可以縮放瀏覽器視窗的情況下,為了確保在不同裝置上都能夠提供良好的使用者體驗,需要使用響應式佈局來適應不同的螢幕尺寸。

1.2 響應式佈局的解決方案

響應式佈局有多種方案,比如:

  1. 媒體查詢:它允許根據裝置的特性(如螢幕寬度、裝置型別等)應用不同的樣式規則。通過使用媒體查詢,可以針對不同的螢幕尺寸和裝置型別應用不同的樣式,從而實現響應式佈局。
  2. 流式佈局(百分比佈局):它是一種基於相對單位(如百分比)進行設計的佈局方式。在流式佈局中,元素的寬度和高度相對於父元素或視口進行計算,使得它們可以根據可用空間的大小進行自適應調整。流式佈局可以使頁面在不同螢幕尺寸下保持比例和流動性。
  3. Flex佈局:Flexbox是CSS3中的一種彈性盒子佈局模型,它提供了強大的排列和對齊功能,可以實現靈活的響應式佈局。通過使用Flexbox屬性和值,可以輕鬆地控制元素在容器中的位置、順序和大小。
  4. 柵格系統:柵格系統是一種將頁面劃分為多個網格列的佈局方式,通過定義網格列數和間距來佈局頁面內容。柵格系統通常與媒體查詢和流式佈局結合使用,以實現在不同螢幕尺寸下的響應式佈局。流行的柵格系統包括Bootstrap的柵格系統和Foundation的柵格系統。

本文主要介紹Flex佈局

1.3 Flex佈局的優越性

排列靈活,樣式簡單:Flex佈局在響應式解決方案中具有靈活的排列和對齊、自適應的彈性性質、自動換行和調整順序以及容器和專案的靈活性等優點,可以通過簡單的CSS屬性設定來控制元素在容器中的位置和佈局。通過設定容器的flex-direction、justify-content和align-items等屬性,可以輕鬆實現水平或垂直方向上的排列和對齊需求。這種靈活性使得在不同裝置上適應不同佈局要求變得容易。相比起針對不同螢幕來設定的媒體查詢,相同的樣式設定就可以適配多種螢幕尺寸,Flex佈局非常的方便。

自動換行,調整順序:在移動裝置上,螢幕空間有限,需要在有限的空間中合理佈局元素。Flex佈局可以通過設定flex-wrap屬性實現自動換行,使得專案可以在一行排列不下時自動換行到下一行。此外,還可以使用order屬性調整專案的顯示順序,以便在移動裝置上優先顯示重要內容。這種自動換行和調整順序的特性使得在小螢幕裝置上實現良好的使用者體驗變得簡單。

除了響應式佈局外,在PC端也可以利用Flex佈局來替代浮動和定位,完成很好的元素排列,讓開發者免去使用float,position來佈局的不便。最常見的八股文面試題,垂直水平居中就可以用flex佈局輕鬆完成,這也是工作中較為常用的方式。

2. Flex佈局定義

Flex佈局對於元素的內聯(行內)或塊級的性質是不關心的。在Flex佈局中,元素會根據容器和專案的屬性進行排列,無論元素是行內元素還是塊級元素。採用Flex佈局的元素,稱為Flex容器(flex container),簡稱」容器」。Flex容器的所有子元素自動成為容器成員,稱為Flex專案(flex item),簡稱」專案」。

容器預設存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)。主軸的開始位置(與邊框的交叉點)叫做main start,結束位置叫做main end;交叉軸的開始位置叫做cross start,結束位置叫做cross end。

專案預設沿主軸排列。單個專案佔據的主軸空間叫做main size,佔據的交叉軸空間叫做cross size。

3. Flex容器屬性

3.1 開啟flex佈局display:flex

元素寫了這個屬性之後,就變成了一個flex的容器,就可以通過flex佈局相關的方式去操作排列子元素。

  <style>
    .parent{
      display: flex;
      width: 400px;
      height: 200px;
      background-color:blueviolet;
    }
    .child{
      width: 100px;
      height: 50px;
      background-color: aqua;
      border: 1px solid black;
    }
  </style>
</head>
<body>
  <div class="parent">
    <div class="child">1</div>
    <div class="child">2</div>
  </div>
</body>

 

 

開啟flex佈局之後,沒有進行其他的設定,可以看到這個排列和沒有開啟flex佈局的時候是不一樣的,2個塊級元素,並沒有上下排列,而是已經排列在左右。開啟flex佈局後,容器中的專案預設會沿著主軸進行排列,此時沒有對容器和專案進行其他的設定,主軸也按照預設的方向水平放置,所以2個子盒子都沿著主軸水平排列了。

3.2 改變主軸的方向flex-direction屬性

flex-direction屬性決定了主軸的方向,所有容器中的專案都會根據主軸方向來排列。

flex-direction 屬性有四個可能的取值:

  1. row(預設值):Flex 專案水平排列,起點在左端,終點在右端。主軸從左到右。
  2. row-reverse:Flex 專案水平排列,起點在右端,終點在左端。主軸從右到左。
  3. column:Flex 專案垂直排列,起點在頂部,終點在底部。主軸從上到下。
  4. column-reverse:Flex 專案垂直排列,起點在底部,終點在頂部。主軸從下到上。

圖中顯示flex-direction的值為row時元素按順序從左往右橫向排列,子元素貼著父元素的左側

 1  .parent{
 2       display: flex;
 3       flex-direction: row;
 4       width: 400px;
 5       height: 200px;
 6       background-color:blueviolet;
 7     }

 

圖中顯示flex-direction的值為row-reverse時元素按順序從右往左橫向排列,子元素貼著父元素的右側(程式碼同上)

圖中顯示flex-direction的值為column時元素按順序從上往下豎向排列,子元素貼著父元素的頂部,這一點類似於常規的檔案流中塊級元素的排列(程式碼同上)

圖中顯示flex-direction的值為column-reverse時元素按順序從下往上豎向排列,子元素貼著父元素的底部(程式碼同上)

 

總的來說,flex-direction屬性雖然簡單,但是有重要的作用,可以

  1. 控制主軸方向:flex-direction 屬性決定了主軸的方向,即 Flex 專案在水平方向或垂直方向上的排列。通過設定不同的取值,我們可以實現水平排列(左到右或右到左)或垂直排列(從上到下或從下到上)的佈局。
  2. 確定起點和終點:flex-direction 屬性的取值影響了 Flex 專案在主軸上的起點和終點的位置。在 row 值下,起點位於左端,終點位於右端;在 row-reverse 值下,起點位於右端,終點位於左端;在 column 值下,起點位於頂部,終點位於底部;在 column-reverse 值下,起點位於底部,終點位於頂部。這種控制起點和終點的能力對於設計佈局非常有用。
  3. 影響專案排列順序:flex-direction 屬性還決定了 Flex 專案在主軸上的排列順序。在預設的 row 值下,Flex 專案按照其在 HTML 結構中的順序從左到右排列;在 row-reverse 值下,專案按照相反的順序從右到左排列;在 column 值下,專案按照結構順序從上到下排列;在 column-reverse 值下,專案按照相反的順序從下到上排列。通過改變專案的排列順序,我們可以調整 Flex 佈局的外觀和行為。

 

3.3 改變換行方式flex-wrap屬性

flex-wrap屬性決定了換行相關的策略。它決定了當彈性容器的寬度不足以容納所有子元素時,是否允許子元素換行並如何排列。

它有幾個常用的屬性值:

  1. nowrap(預設值):子元素不換行,儘可能地將它們放在一行內,即使溢位彈性容器的邊界。
  2. wrap:如果子元素在一行內放不下,將它們進行換行,從新行開始排列。
  3. wrap-reverse:與 wrap 相同,但換行時的排列順序與正常順序相反。

 

當沒有寫flex-wrap屬性時,所有元素會預設沿著主軸在一行(或一列)排列。這也就和寫了flex-wrap: nowrap是等效的

在已經給子專案設定了100px的寬度的情況下,6個專案仍然會排在同一行,而此時父元素的寬度也只有400px,說明此時子專案的寬度已經被壓縮了變成了小於100px。

 1 <style>
 2     .parent {
 3         display: flex;
 4         width: 400px;
 5         height: 200px;
 6         background-color: blueviolet;
 7     }
 8 
 9     .child {
10         width: 100px;
11         height: 50px;
12         background-color: aqua;
13         border: 1px solid black;
14     }
15 </style>
16 <body>
17     <div class="parent">
18         <div class="child">1</div>
19         <div class="child">2</div>
20         <div class="child">3</div>
21         <div class="child">4</div>
22         <div class="child">5</div>
23         <div class="child">6</div>
24     </div>
25 </body>

 

當希望子專案完成換行的時候可以設定flex-wrap: wrap

明顯可以看到,圖片已經完成了換行效果,但是這裡上下兩行元素出現了空隙,似乎與預期效果不符合,這是由於多行對齊時的align-content的預設值導致的,具體align-content用法會在後文解釋。

 

 1     .parent {
 2         display: flex;
 3         flex-wrap: wrap;
 4         width: 400px;
 5         height: 200px;
 6         background-color: blueviolet;
 7     }
 8 
 9     .child {
10         width: 100px;
11         height: 50px;
12         background-color: aqua;
13         border: 1px solid black;
14     }

 

當換行屬性設定為flex-wrap: wrap-reverse,也會完成換行,但是換行的順序與前面相反,第一行會在最下面,最後一行在上面

 

 

3.4 主軸對齊方式justify-content屬性

justify-content是flex佈局中的重要屬性之一,用於定義和調整彈性容器中專案在主軸上的對齊方式。它控制專案沿著主軸的分佈方式,包括專案之間的間距、對齊和對齊方式的調整。

這個屬性常用的有以下幾個值

  1. flex-start(預設值):將專案對齊到彈性容器的起始位置。專案靠主軸起始端對齊。
  2. flex-end:將專案對齊到彈性容器的末尾位置。專案靠主軸末尾端對齊。
  3. center:將專案在主軸上居中對齊。專案在主軸上平均分佈,兩端留有相同的空白。
  4. space-between:將專案在主軸上平均分佈,並使專案之間的間距相等。首個專案對齊到主軸起始端,最後一個專案對齊到主軸末尾端。
  5. space-around:將專案在主軸上平均分佈,並使專案之間的間距相等。首尾兩端的間距是相鄰專案間距的一半。
  6. space-evenly:將專案在主軸上平均分佈,並使專案之間的間距相等。首尾兩端和相鄰專案之間的間距相等。

 不寫justify-content或者justify-content的值為flex-start時,flex容器內部的專案會按順序沿著主軸排列,也就是當主軸是水平的時候就橫過來排列,主軸是豎直的就豎過來排列。

以較常見的flex-direction取預設值row的時候舉例,有類似於float:left的效果,但是不會出現子元素浮動後脫離檔案流導致父元素高度塌陷的問題。

1 .parent {
2         display: flex;
3         justify-content: flex-start;
4         width: 400px;
5         height: 200px;
6         background-color: blueviolet;
7     }

justify-content的值為flex-end時,子元素也就是flex容器會靠主軸的終點處對齊,與前面的flex-start呈現相反的對齊排列效果。

以較常見的flex-direction取預設值row的時候舉例,類似於float:right的效果,但是與右浮動不同的是右浮動會導致元素倒序排列而flex-end會保持元素的順序,元素的排列順序仍然是1,2,3。

1     <div class="parent">
2         <div class="child">1</div>
3         <div class="child">2</div>
4         <div class="child">3</div>
5     </div>

 

對於右浮動會出現倒序的原因,這裡進行簡單的解釋:

浮動的元素直到碰到邊緣或另一個浮動元素的邊緣為止,而程式碼又是從上往下執行,對於第一個child會優先進行浮動,碰到父盒子右邊緣,結束,第二個child再開始浮動,碰到第一個child的左邊緣再結束,第三個child在第二個child浮動結束後再浮動,就貼著第二個child左邊緣。

解決右浮動倒序的方法可以有以下幾種:

  1. 利用flex佈局的flex-end,如上圖所示
  2. 倒序書寫元素,這樣就可以正序排列了。
  3. 對於多個右浮動的child,再在外面加一層div包裹,先讓外層的div右浮動(只有一個盒子,不會出現順序問題的同時又能靠右對齊),然後讓每個child左浮動(左浮動不會導致順序出現問題,又可以實現浮動效果),程式碼和圖片如下
    <style>
        .parent {
            width: 400px;
            height: 200px;
            background-color: blueviolet;
        }
    
        .wrapper {
            float: right;
        }
    
        .child {
            float: left;
            width: 100px;
            height: 50px;
            background-color: aqua;
            border: 1px solid black;
        }
    </style>
    </head>
    <body>
        <div class="parent">
            <div class="wrapper">
                <div class="child">1</div>
                <div class="child">2</div>
                <div class="child">3</div>
            </div>
        </div>
    </body>

     

 

 

justify-content的值為center時,flex容器內的元素在主軸上居中對齊,向兩邊平均分佈

以較常見的flex-direction取預設值row的時候舉例,圖中利用flex佈局的justify-content:center 可以非常方便地實現塊級元素的居中對齊

 justify-content的值為space-between時,專案會在主軸兩端對齊,中間平均排列,讓不同的專案之間的間距相等

這裡將每個child的寬度調成50px讓多個盒子都能呈現在父容器內(同時避免尺寸發生變化)以展示space-between的效果。

這種佈局形式在真實開發中也較為常用,有許多場景都需要兩端對齊後,中間均分空隙。

以較常見的flex-direction取預設值row的時候舉例,可以看到子專案中的間距都是相同的。在沒有設定任何margin的情況下,元素也可以完成分離。

 1     .parent {
 2         display: flex;
 3         justify-content: space-between;
 4         width: 400px;
 5         height: 200px;
 6         background-color: blueviolet;
 7     }
 8 
 9     .child {
10         width: 50px;
11         height: 50px;
12         background-color: aqua;
13         border: 1px solid black;
14     }

justify-content的值為space-around時,每個專案自身的左右間距會相等,類似於設定了左右兩邊相同的margin值

以較常見的flex-direction取預設值row的時候舉例,看起來首尾元素間距更窄,是因為對於中間元素一共有2份間距,前一個元素的右間距+後一個元素的左間距,所以中間的間距是首尾的兩倍。

justify-content的值為space-evenly時,所有專案的間距都會相等,前面提到的space-around會讓每個專案自身都具有相同左右邊距,導致中間的間距疊加成立首尾的2倍。而space-evenly中會讓所有的間距都相等,包括剛才所提到的首尾和中間。

以較常見的flex-direction取預設值row的時候舉例,所有間距都相同。

 

3.5 交叉軸單行對齊align-items屬性

 與justify-content對應的,align-items用於定義和調整彈性容器中專案在交叉軸上的對齊方式,它同樣也控制專案沿著交叉軸的分佈方式,包括專案之間的間距、對齊和對齊方式的調整。

這個屬性有以下幾個常用的值

  1. stretch(預設值):將專案在交叉軸上拉伸以填充整個彈性容器。專案將沿交叉軸方向拉伸至與容器的交叉軸尺寸相等。
  2. flex-start:將專案對齊到彈性容器的交叉軸起始位置。專案靠交叉軸起始端對齊。
  3. flex-end:將專案對齊到彈性容器的交叉軸末尾位置。專案靠交叉軸末尾端對齊。
  4. center:將專案在交叉軸上居中對齊。專案在交叉軸上平均分佈,上下留有相同的空白。
  5. baseline:將專案在交叉軸上與其基線對齊。專案的基線與其他專案的基線對齊。

這裡先從預設不寫這個屬性來看,雖然align-items裡也有和justify-content相同的flex-start值,但是這裡的預設值並不是flex-start而是stretch,stretch的意思是伸展、延伸,也就是說寫了stretch之後(或者直接不寫align-items讓他取預設值),專案會在交叉軸上伸展。

以沒有寫高度的專案舉例

 1     .parent {
 2         display: flex;
 3         justify-content: stretch;
 4         width: 400px;
 5         height: 200px;
 6         background-color: blueviolet;
 7     }
 8 
 9     .child {
10         width: 50px;
11         background-color: aqua;
12         border: 1px solid black;
13     }

 

 

注意,以上程式碼中,子元素沒有設定高度,所以flex專案完成拉伸並且在交叉軸上填滿整個父容器的高度(或寬度),當然如果專案分多行排列,也會撐滿整個父容器,每個專案的高度會被拉伸到:父元素高度/行數。

如果子專案已經設定了高度,那麼這個屬性就不會生效,不會再去拉伸專案。同樣的如果主軸是垂直的,專案沒有寫寬度,也會橫向撐滿整個容器

 1     .parent {
 2         display: flex;
 3         align-items: stretch;
 4         width: 400px;
 5         height: 200px;
 6         background-color: blueviolet;
 7     }
 8 
 9     .child {
10         width: 50px;
11         height: 50px;
12         background-color: aqua;
13         border: 1px solid black;
14     }

align-items為flex-start時,子專案都沿著交叉軸靠著交叉軸的起點對齊

這裡因為只有一行(沒有設定換行屬性,也沒有一行排列不下),整個容器的上端也就是交叉軸的起點, 所以看起來和上面的圖沒什麼區別。

align-items為flex-end時,子專案都沿著交叉軸靠著交叉軸的終點對齊

和上圖相反的是,設定了這個屬性,一行的專案就來到了容器底部,因為預設情況下交叉軸從上往下,容器的底部也就是整個交叉軸的終點

align-items為center時,子專案都沿著交叉軸靠著交叉軸居中對齊,往兩邊平均分佈

設定了center後,子專案來到居中的位置。這也是在flex佈局中最常用的居中技巧之一。如果需要垂直方向的居中,可以直接使用flex佈局並且寫上align-items: center。

align-items為baseline時,專案會按照文字的基線對齊

先針對第二個專案設定了一個padding,這樣第二個專案的文字就會被擠下去,所以文字就不會在同一條基線上了

 1 <style>
 2     .parent {
 3         display: flex;
 4         width: 400px;
 5         height: 200px;
 6         background-color: blueviolet;
 7     }
 8 
 9     .child {
10         width: 50px;
11         height: 50px;
12         background-color: aqua;
13         border: 1px solid black;
14     }
15 
16     #two {
17         padding-top: 10px;
18     }
19 </style>
20 <body>
21     <div class="parent">
22         <div class="child">1</div>
23         <div class="child" id="two">2</div>
24         <div class="child">3</div>
25         <div class="child">4</div>
26         <div class="child">5</div>
27         <div class="child">6</div>
28     </div>
29 </body>

 如果設定align-items: baseline之後,專案明顯都在同一條基線上。

 

 

3.6 交叉軸多行對齊align-content屬性

在上文的flex-wrap中,換行顯示的盒子出現了一些空隙,這就和align-content有關係,align-content是CSS中用於控制flex容器中多行專案的對齊方式的屬性。它適用於具有多行內容的flex容器,並決定了這些行在容器中的專案在交叉軸上的對齊方式。

 

 以下是align-content的一些常用的取值:

  1. flex-start:將多行專案對齊到容器的起始位置。第一行將與容器的頂部對齊。
  2. flex-end:將多行專案對齊到容器的結束位置。最後一行將與容器的底部對齊。
  3. center:將多行專案在容器中垂直居中對齊。
  4. space-between:在容器中平均分佈多行專案,使第一行在容器的頂部,最後一行在容器的底部,剩餘的行平均分佈在中間。
  5. space-around:在容器中平均分佈多行專案,使每行周圍具有相等的空間,包括頂部和底部。
  6. space-evenly:在容器中平均分佈多行專案,使每行之間和周圍都具有相等的空間。
  7. stretch(預設值):在容器中平均分佈多行專案,專案將被拉伸以填充整個容器的高度。

需要注意的是,align-content只在有多行的情況下才會生效,而在只有一行的情況下是不會產生任何效果的,所以以下的範例全部會涉及到flex-wrap換行。

 

 

當預設不寫align-content時,align-content的值預設取stretch,也就是會把每一個專案都會拉伸來撐滿整個容器,這裡最多2行,所以每個專案的高度都被拉伸到了容器高度/2。

當對子專案設定高度的時候,專案不會被拉伸,但是原來拉伸後的空間會有間距填充

 1     .parent{
 2       display: flex;
 3       flex-wrap: wrap;
 4       /* 預設值,也可以不寫 */
 5       align-content: stretch;
 6       width: 400px;
 7       height: 200px;
 8       background-color:blueviolet;
 9     }
10     .child{
11       width: 100px;
12       background-color: aqua;
13       border: 1px solid black;
14     }

 當align-content的值取flex-start時,第一行會靠著交叉軸起點,也就是頂部對齊,不會留有上圖那樣的間距

當align-content的值取flex-end時,最後一行會靠著交叉軸終點,也就是底部對齊,也不會留有上圖那樣的間距

當align-content的值取center時,專案會在交叉軸上居中對齊,向兩邊平均分佈,這個與之前的align-items和justify-content相似

當align-content的值取space-between時,專案會在交叉軸上貼著兩端,中間間距相同

當align-content的值取space-around時,每個專案的上下間距相同,和justify-content一樣,因為中間的間距疊加,首尾的間距是中間間距的一半

 當align-content的值取space-evenly時,所有交叉軸上的間距相同

 

 

4. Flex專案屬性

4.1 改變專案的顯示順序order屬性

order屬性用於控制Flex容器中子元素的排序。預設情況下,Flex容器中的子元素按照它們在HTML原始碼中的順序進行排列,但是使用order屬性,我們可以改變這個順序

每個Flex專案的order屬性預設值是0。你可以為專案設定任意整數值,數值可以是正數、0或者負數。具有較小order值的元素將被優先排列,具有相同order值的元素將按照它們在HTML原始碼中的原始順序排列。

 1     .parent{
 2       display: flex;
 3       flex-wrap: wrap;
 4       align-content: flex-start;
 5       width: 400px;
 6       height: 200px;
 7       background-color:blueviolet;
 8     }
 9     .child{
10       width: 100px;
11       height: 50px;
12       background-color: aqua;
13       border: 1px solid black;
14     }
15     #two{
16       order: -1;
17     }
18     #three{
19       order: -2;
20     }

 

4.2 子專案擴張flex-grow屬性

flex-grow用於設定或檢索flex容器中的flex子專案的能力,以根據其在flex容器中的空間比例來伸展和佔用空間。

flex-grow屬性的預設值為0,表示子專案將不會伸展以填充容器。

flex可以取的值是所有非負數,數值不帶單位,表示當容器有剩餘空間的時候,子專案按比例去增大,佔滿容器。子專案擴張的演演算法如下:比如剩餘空間為 x,三個元素的 flex-grow 分別為 a,b,c。設 sum 為 a + b + c。那麼三個元素將得到剩餘空間分別是 x * a / sum, x * b / sum, x * c / sum

對第三個子專案進行設定flex-grow:1,表示的意思是:有剩餘空間的時候,第三個專案會擴張,佔一份,因為只有一個元素設定了flex-grow,所以第三專案佔滿了所有剩餘空間。

此時如果對第三個專案設定flex-grow:2/3/4/5....都不會使他變得更大,因為剩餘空間只有那麼多,其他的元素也都是flex-grow:0。

對多個專案設定flex-grow時,它們就按照比例來佔滿剩餘空間,第二個子專案佔1份(四分之一),第三個子專案佔3份(四分之三)

 1     .parent {
 2       display: flex;
 3       width: 400px;
 4       height: 200px;
 5       background-color: blueviolet;
 6     }
 7 
 8     .child {
 9       width: 50px;
10       height: 50px;
11       background-color: aqua;
12       border: 1px solid black;
13     }
14 
15     #two {
16       flex-grow: 1;
17     }
18 
19     #three {
20       flex-grow: 3;
21     }

前面有說到,flex-grow可以設定所有非負的值,當所有的子專案flex-grow的值之和小於1時,計算擴張的演演算法會發生改變,不再只是將所有的剩餘空間的按flex-grow的比例分配,而是將剩餘空間*sum(三個元素的 flex-grow 分別為 a,b,c設 sum 為 a + b + c)按flex-grow的比例分配。也可以等效地理解為按上面講的演演算法x * a / sum, x * b / sum, x * c / sum,當sum<1時,分母直接使用1。

如下圖,第二個子專案獲得剩餘空間的20%,第三個子專案獲得剩餘空間的60%,剩下的20%仍然空出。

 1     .parent {
 2       display: flex;
 3       width: 400px;
 4       height: 200px;
 5       background-color: blueviolet;
 6     }
 7 
 8     .child {
 9       width: 50px;
10       height: 50px;
11       background-color: aqua;
12       border: 1px solid black;
13     }
14 
15     #two {
16       flex-grow: 0.2;
17     }
18 
19     #three {
20       flex-grow: 0.6;
21     }

簡單案例:之前在開發中遇到一個需求,後端會給前端傳許多一段一段的標籤,每個標籤的寬度都不一樣長,這些標籤要換行排列。每一行的標籤要貼著左右邊緣,中間間距相等(justify-content: space-between)。最後一行標籤一般都會數量較少,如果僅僅使用justify-content: space-between而不對最後一行專門處理,最後一行的間距就會特別大,影響最後頁面效果的呈現。

為了解決最後一行標籤數量較少的問題,可以在容器末尾加一個看不見的盒子,讓那個盒子佔滿剩餘的空間,也就是利用flex-grow: 1

以下用簡單的程式碼模擬了一下上述開發場景

 1 <style>
 2     .parent {
 3         display: flex;
 4         flex-wrap: wrap;
 5         justify-content: space-between;
 6         width: 400px;
 7         height: 200px;
 8         background-color: blueviolet;
 9     }
10 
11     .child {
12         width: 100px;
13         height: 40px;
14         background-color: aqua;
15         border: 1px solid black;
16         font-size: 18px;
17     }
18 
19     .hidden {
20         flex-grow: 1;
21         visibility: hidden;
22     }
23 </style>
24 <body>
25     <div class="parent">
26         <div class="child">1</div>
27         <div class="child" style="width: 120px;">2</div>
28         <div class="child" style="width: 30px;">3</div>
29         <div class="child">4</div>
30         <div class="child" style="width: 150px;">5</div>
31         <div class="child">6</div>
32         <div class="child">7</div>
33         <div class="child">8</div>
34         <div class="child">9</div>
35         <div class="hidden"></div>
36     </div>
37 </body>

 

 

 

 

4.3 子專案收縮flex-shrink屬性

 flex-shrink用於指定專案在容器中縮小的能力,當 flex 容器空間不足時候,單個元素的收縮比例。當父元素的寬度小於子元素寬度之和並且超出了父元素的寬度時,flex-shrink 就會按照一定的比例進行收縮:將子元素寬度之和與父元素寬度的差值按照子元素 flex-shrink 的值分配給各個子元素,每個子元素原本寬度減去按比例分配的值,其剩餘值為實際寬度。

flex-shrink的預設值是1,也就是說,當子元素寬度的和超出父容器的時候,所有子專案都等比例的縮小

下圖中所有子專案的flex-shrink都取1,但是子專案的寬度是有不同的,第二個子專案寬度為120px,第三個子專案寬度為150px,其他所有子專案的寬度都是100px,他們寬度的和是100*4+120+150 = 670px,但是父容器寬度只有400px,也就是說超出了270px。此時要等比例縮小,要計算每個盒子要縮小的寬度,演演算法是:子專案寬度/(每個子專案的寬度*對應shrink的值)之和 * 超出的寬度。對於寬度為100的子專案要縮小的寬度是 (100*1)/(100*4*1+120*1+150*1)*270 = 40.29px,對於第二個寬度為120px的子專案要縮小的寬度是(120*1)/(100*4*1+120*1+150*1)*270 = 48.36px,對於第三個寬度為150px的子專案要縮小的寬度是(150*1)/(100*4*1+120*1+150*1)*270 = 60.48px

所有盒子在收縮後,最後的寬度=原來寬度-要縮小的寬度

 1     .parent {
 2         display: flex;
 3         width: 400px;
 4         height: 200px;
 5         background-color: blueviolet;
 6     }
 7 
 8     .child {
 9         width: 100px;
10         height: 50px;
11         flex-shrink: 1;
12         background-color: aqua;
13         border: 1px solid black;
14     }
15     #two{
16         width: 120px;
17     }
18     #three{
19         width: 150px;
20     }

 

 

當flex-shrink為0的時候,該子專案不會收縮

以第三個150px的盒子舉例,讓它的flex-shrink為0,它就不會收縮,其他盒子按比例收縮,寬度為100px的專案flex-shrink為1,要縮小的寬度為 (100*1)/(100*4*1+120*1.5+150*0)*270 = 46.55px, 寬度為120px的專案flex-shrink為1.5,要縮小的寬度為 (120*1.5)/(100*4*1+120*1.5+150*0)*270 = 83.79px

 1     .parent {
 2         display: flex;
 3         width: 400px;
 4         height: 200px;
 5         background-color: blueviolet;
 6     }
 7 
 8     .child {
 9         width: 100px;
10         height: 50px;
11         flex-shrink: 1;
12         background-color: aqua;
13         border: 1px solid black;
14     }
15     #two{
16         width: 120px;
17         flex-shrink: 1.5;
18 
19     }
20     #three{
21         width: 150px;
22         flex-shrink: 0;
23 
24     }

 

 

4.4 子專案初始尺寸flex-basis屬性

flex-basis用於設定flex容器中專案的初始大小。它定義了一個專案在主軸上的初始尺寸,即在專案沒有被放大或縮小之前的大小。flex-basis可以接受多種單位值,如畫素(px)、百分比(%)、視口寬度(vw)、視口高度(vh)等。

flex-basis常用的值有

  1. <length>:可以是畫素值(px)、百分比(%)等,表示專案的初始尺寸。
  2. auto(預設值):專案的初始尺寸由其內容決定。如果專案沒有設定尺寸或具有固定的尺寸,則自動計算尺寸。
  3. content:專案的初始尺寸由專案內容決定。

在Flex佈局中,子項設定width是沒有直接效果的,之前所有設定寬度並且生效是因為沒有寫flex-basis屬性,也就是說flex-basis屬性取了預設值auto,當flex-basis取auto的時候,容器的寬度就由子項自身的尺寸(比如width,max-width等)去渲染。

 1 .parent {
 2       display: flex;
 3       width: 400px;
 4       height: 200px;
 5       background-color: blueviolet;
 6     }
 7 
 8     .child {
 9       width: 50px;
10       height: 50px;
11       flex-basis: auto;
12       background-color: aqua;
13       border: 1px solid black;
14     }

 在同時用長度設定flex-basis和width時,width將無效,根據flex-basis的值決定尺寸

 在設定flex-basis為content時,子專案的尺寸根據內容的大小決定

 

 

4.5 聯合寫法flex屬性

flex屬性是flex-grow,flex-shrink,flex-basis三個屬性的簡寫,用於控制子專案的縮放行為和初始尺寸。

flex的完整寫法是 flex:<flex-grow>  <flex-shrink> <flex-basis>,也就是一共有3個值要去設定,分別按順序對應flex-grow,flex-shrink,flex-basis,而在日常工作中並不會經常寫完整的寫法,而較常用的是flex:1或者50%這種寫法。

flex-grow和flex-shrink可以同時設定,但是對於一個元素,同時只會有其中一者生效,因為flex-grow需要有剩餘空間才能進行拉伸分配而flex-shrink需要子元素寬度之和超過父元素(溢位)才會收縮,一個盒子要麼空間不足,要麼就空間超出,不可能既有剩餘空間又寬度之和超出父元素

flex屬性的常用值有

  1. flex: auto: 此值表示元素可以根據可用空間進行伸縮,可以擴充套件也可以收縮。
  2. flex: initial: 此值將 flex-grow、flex-shrink 和 flex-basis 設定為預設值。flex-grow 為 0,flex-shrink 為 1,flex-basis 為 auto。
  3. flex: none: 此值表示元素不應該伸縮。flex-grow 和 flex-shrink 均為 0,flex-basis 為其本來的大小。
  4. flex: 數位/百分比/長度

 

flex:auto代表的是 flex:1 1 auto(flex-grow:1, flex-shrink: 1, flex-basis: auto) ,表示的是根據具體空間來進行擴充套件或者收縮

 flex:initial(預設值)代表的是 flex:0 1 auto(flex-grow:0, flex-shrink: 1, flex-basis: auto) ,表示子專案不會在有剩餘空間時候擴張,但是超出時會要收縮。

flex:none 代表的是 flex:0 0 auto(flex-grow:0, flex-shrink: 0, flex-basis: auto),表示子專案不會擴張也不會收縮,保持原有尺寸

在超出父容器的時候,也會繼續保持原有的尺寸

其他值:

如果只寫一個值,類似於flex: 1 這種,分2種情況

  1. 如果寫的是數位比如,flex: 1,flex: 2,flex: 3這種那設定的是flex-grow的值,其他2個值取預設
  2. 如果寫的是百分比(flex: 20%)或者是長度(flex: 100px),就是設定的flex-basis屬性,其他2個值取預設

如果只寫兩個值,第一個值對應的是flex-grow,第二個值對應2種情況

  1. 如果第二個值寫的是數位比如,flex: 1,flex: 2,flex: 3這種那設定的是flex-shrink的值
  2. 如果寫的是百分比(flex: 20%)或者是長度(flex: 100px),就是設定的flex-basis屬性

如果寫三個值,對應地去設定flex-grow、flex-shrink 和 flex-basis 

 

簡單案例:

場景1:簡單實現一個兩欄佈局,左列定寬,右邊自適應

這裡用到flex: 1 讓右邊的專案自動根據剩餘空間擴張

 1   <style>
 2     .parent {
 3       display: flex;
 4       width: 400px;
 5       height: 200px;
 6       background-color: blueviolet;
 7     }
 8 
 9     .child1 {
10       width: 100px;
11       height: 50px;
12       background-color: aqua;
13       border: 1px solid black;
14     }
15     .child2 {
16       height: 50px;
17       background-color: aqua;
18       flex: 1;
19       border: 1px solid black;
20     }
21   </style>
22 
23 <body>
24   <div class="parent">
25     <div class="child1">1111</div>
26     <div class="child2">2</div>
27   </div>
28 </body>

 

場景2:讓多個盒子分行排列,每行要三個盒子,同時寬度自適應

這裡要對父容器設定flex-wrap:wrap,對子專案設定,flex:33%來讓它們每行排列3個

 1 <style>
 2   .parent {
 3     display: flex;
 4     justify-content: space-between;
 5     flex-wrap: wrap;
 6     width: 400px;
 7     height: 200px;
 8     background-color: blueviolet;
 9   }
10 
11   .child {
12     box-sizing: border-box;
13     flex: 33%;
14     height: 50px;
15     background-color: aqua;
16     border: 1px solid black;
17   }
18 </style>
19 
20 <body>
21   <div class="parent">
22     <div class="child">1</div>
23     <div class="child">2</div>
24     <div class="child">3</div>
25     <div class="child">4</div>
26     <div class="child">5</div>
27     <div class="child">6</div>
28   </div>
29 </body>

 

 

4.6 子專案單獨對齊align-self屬性

 

align-self屬性用於調整Flex容器中單個專案(Flex項)的垂直對齊方式。它允許你為單個專案指定不同於其它專案的垂直對齊方式。align-self屬性可以應用於任何Flex項,並覆蓋容器級別的垂直對齊設定(通過align-items屬性設定)

 常用的值有:

  1. auto(預設值):繼承自父容器的align-items屬性。
  2. flex-start:專案與容器的頂部對齊。
  3. flex-end:專案與容器的底部對齊。
  4. center:專案在容器的垂直中心對齊。
  5. baseline:專案與容器的基線對齊。
  6. stretch:專案被拉伸以填充整個容器的高度。

這些取值都在前面的align-items中介紹過了,這裡只用一些案例來演示align-self的效果

針對第二個子專案,設定了align-self: center,第三個子專案設定了align-self: flex-end

這裡是單行的align-self效果

 1   .parent {
 2     display: flex;
 3     align-items: flex-start;
 4     width: 400px;
 5     height: 200px;
 6     background-color: blueviolet;
 7   }
 8 
 9   .child {
10     box-sizing: border-box;
11     width: 100px;
12     height: 50px;
13     background-color: aqua;
14     border: 1px solid black;
15   }
16 
17   #two{
18     align-self: center;
19   }
20   #three{
21     align-self: flex-end;
22   }

如果在父容器中加入換行,效果如下