Flex屬性你真的搞清楚了嗎?我深表懷疑

背景

在使用彈性布局實現兩側寬度固定,中間寬度自適應的效果時,發現自己理解的和實際效果不一致,所以親自實踐驗證了一個flex屬性的諸多場景的表現,不僅解開了我之前使用過程遇到的疑惑,而且發現了許多自己以前理解有偏差的地方。第一章節有點繞,第二,三章節結論比較清晰。如果啃不動第一章節,建議直接跳到第二章節閱讀,相信你看完之後,也會有收穫的。

1.flex容器下子元素的寬度

1.1 當內容是連續的英文和數字時,內容超出不會自動換行,會溢出到子元素之外,加break-word:break-all;才是我們想要的結果

連續的英文+數字內容會溢出

連續的中文斷行正確,內容不會溢出。

 連續的數字+英文,加上斷詞樣式設置後,內容不再溢出。

1.2 當只有flex-basis屬性時,flex子元素的最小寬度為內容寬度。

1.2.1 flex父容器寬度 > flex子元素內容寬度時,flex子元素的寬度是max(flex-basis,content-size)

flex子元素的flex-basis > content-size時, flex子元素的寬度為flex-basis

flex子元素的flex-basis < content-size, flex子元素的寬度為content-size

1.2.2 flex父容器寬度 < flex子項內容寬度時,flex子項會撐破父容器,flex-basis無法約束flex子項寬度,子項的寬度為子項的content-size

1.3 當同時設置了width和flex-basis時,分兩類情況:

1.3.1 flex父容器寬度 > flex子項內容寬度時,flex子元素的寬度優先順序是 max(flex-basis, width) > content-size

content-size > flex-basis > width, flex子元素寬度為flex-basis

content-size > width > flex-basis ,flex子元素寬度為width

1.3.2 flex父容器寬度 < flex子項內容寬度時,flex子元素的寬度優先順序是 width  > content-size , flex-basis不起作用

 

content-size > width > flex-basis, flex子元素寬度為width

 

 width < flex-basis < content-size, flex子元素寬度為width

 

flex-basis > content-size時,flex子元素的寬度是content-size

 flex-basis < content-size時,flex子元素的寬度是content-size

1.4 當同時設置了max-width, width,flex-basis時,分兩類情況:

1.4.1 flex容器寬度 >  flex子元素內容寬度

 max-width  >  content-size 時, max(flex-basis,width)生效

 

 max-width  >  content-size 時,沒有width屬性時,max(flex-basis, content-size)生效

 max-width  < content-size 時 ,max-wdith生效

1.4.2 flex容器寬度 < flex子元素內容寬度,flex-basis不生效

子元素max-width > flex父元素寬度,flex子元素的寬度是max(子元素的width,flex父元素的寬度)

  flex-basis > 或 < width時,都不起作用。

 沒有width屬性時,起作用的是content-size。flex-basis仍舊不起作用

子元素max-width <  flex父元素寬度,flex子元素的寬度是子元素的max-width

1.5 當同時設置min-width,width,flex-basis屬性時 

1.5.1  flex父容器寬度 > flex子元素的content-size時,子元素的寬度優先順序是 min-width > flex-basis > width > content-size

min-width的優先順序高於flex-basis,width,content-size

 

flex-basis的優先順序高於width,content-size

 

width的優先順序高於content-size

 

 不設置flex-basis,width屬性時,content-size才起作用

1.5.2  flex父容器寬度 < flex子元素的content-size時,子元素的寬度優先順序是 max(min-width,flex父容器寬度),width,flex-basis,content-size都不生效

 

1.6 max-width,min-width,width,flex-basis同時設置時,分兩類情況

1.6.1 flex父容器寬度  >  flex子元素的content-size時,flex子元素的寬度優先順序是 min-width > max-width > flex-basis > width > content-size

min-width與max-width衝突時,min-width生效

flex-basis,width,content-size同時存在時,flex-basis生效

 

width,content-size同時存在時,width生效

 

只有content-size存在時,content-size才生效

 

1.6.2 flex父容器寬度  <  flex子元素的content-size時,子元素的寬度是max(min-width,父容器寬度)

 

父容器寬度  > 子元素min-width,子元素寬度是父容器寬度,width,flex-basis,content-size都不生效

 父容器寬度 < 子元素min-width,子元素寬度是min-width

2.flex子元素伸縮屬性

2.1 當空間充足時,flex子項的寬度計算公式是: 自身的基礎寬度 + 容器剩餘寬度 *(自身伸張比例 / 所有子項伸張比例之和),要注意兩種縮寫

2.1.1 flex:none是flex: 0 0 auto的縮寫。看示例:

<style>
  .item {
    display: flex;
    width: 500px;
    height: 100px;
  }

  .item1 {
    width: 50px;
    flex: none;
    background-color: red;
  }
  .item2 {
    flex: 1 1 50px;
    background-color: green;
  }
  .item3 {
    flex: 2 2 100px;
    background-color: blue;
  }
</style>
<div class="item">
  <div class="item1">xxxxxxxxxxxxxx</div>
  <div class="item2">xxxxxxxxxxxxxx</div>
  <div class="item3">xxxxxxxxxxxxxx</div>
</div>

剩餘寬度 :  500 – 50 – 50 – 100 = 300

item1寬度: 50 + 300*( 0 / (0+1+2)) = 50;

item2寬度: 50  +  300 *  ( 1 /(0+1+2))   = 50+100=150;

item3寬度: 100 + 300 *( 2 /(0+1+2))= 100+200=300

注意:flex子項的內容默認是不換行的,內容超過flex子項寬度,會溢出

 

 

 

2.1.2  flex:number 是flex: number 1 0%的縮寫。

<style>
  .item {
    display: flex;
    width: 500px;
    height: 100px;
  }

  .item1 {
    width: 50px;
    flex: none;
    background-color: red;
  }
  .item2 {
    width: 50px;
    flex: 1;
    background-color: green;
  }
  .item3 {
    width: 100px;
    flex: 1;
    background-color: blue;
  }
</style>
<div class="item">
  <div class="item1">xxxxxxxxxxxxxx</div>
  <div class="item2">xxxxxxxxxxxxxx</div>
  <div class="item3">xxxxxxxxxxxxxx</div>
</div>

剩餘寬度 :  500 – 50 – 0 – 0 = 450

item1寬度: 50 + 450*( 0 / (0+1+1)) = 50

item2寬度: 0  +  450 *  ( 1 /(0+1+1))   = 225

item3寬度: 0  +  450 *( 2 /(0+1+1))= 225

注意:flex-basis的優先順序高於width屬性。item2和item3的flex-basis:0%覆蓋了它們的width屬性。

2.2 當空間充足不足時,flex子項的寬度計算公式是: 自身的基礎寬度 –  超出寬度 *(自身寬度*收縮比例/總權重)

2.2.1 最常見的例子

<style>
  .item {
    display: flex;
    height: 100px;
    width:300px;
  }

  .item1 {
    width: 300px;
    background-color: green;
  }
  .item2 {
    flex:1 1 100px;
    background-color: red;
  }
  .item3{
    flex:2 2 200px;
    background-color: blue;
  }
</style>
<div class="item">
  <div class="item1"></div>
  <div class="item2"></div>
  <div class="item3"></div>
</div>

超出寬度=300+100+200-300=300

總權重=300*1+100*1+200*2=800

item1的寬度=300 –  300 * 300*1/800 =300 – 112.5=187.5;(只有width屬性時,flex的屬性值是0 1 auto,空間不足時也會收縮)

item2的寬度=100 –  300 * 100*1/800 =100 – 37.5=62.5;

item3的寬度=200 –  300 * 200*2 /800 =200-150=50;

2.2.2  注意flex:num這種縮寫寫法,展開相當於flex:num 1 0%,此時的flex-basis是0%,不是設置的width;計算總權重時該項的權重為0

<style>
  .item {
    display: flex;
    height: 100px;
    width: 300px;
  }

  .item1 {
    width: 300px;
    background-color: green;
  }
  .item2 {
    flex: 2;
    width: 100px;
    background-color: red;
  }
  .item3 {
    flex: 2 2 200px;
    background-color: blue;
  }
</style>
<div class="item">
  <div class="item1"></div>
  <div class="item2"></div>
  <div class="item3"></div>
</div>

超出寬度: 300+200 -300=200

總權重:300*1 + 0*1 + 200*2=700

item1的寬度是 300 – 200* 300*1/700=214.29

item2的寬度是 0 – 200* 0*1/700=0

item3的寬度是 200 – 200* 200*2/700=85.71

 

 

2.2.3  非收縮項的寬度佔據整個父容器空間時,收縮項的寬度會變成0

<style>
  .item {
    display: flex;
    height: 100px;
    width:300px;
  }

  .item1 {
    width: 400px;
    flex:none;
    background-color: green;
  }
  .item2 {
    flex:1 1 100px;
    background-color: red;
  }
  .item3{
    flex:2 2 200px;
    background-color: blue;
  }
</style>
<div class="item">
  <div class="item1"></div>
  <div class="item2"></div>
  <div class="item3"></div>
</div>

flex父容器的寬度是300

非收縮項item1的寬度是400

收縮項item2,item3的寬度都是0

 

2.2.4 當flex子項有內容時,flex子項收縮之後的寬度是min(width,content-size),  flex子項會溢出

<style>
  .item {
    display: flex;
    width: 300px;
    height: 100px;
  }

  .item1 {
    width: 150px;
    background-color: red;
  }
  .item2 {
    width: 200px;
    flex: 1;
    background-color: green;
  }
  .item3 {
    width: 100px;
    flex: 2;
    background-color: blue;
  }
</style>
<div class="item">
  <div class="item1">01234567890123456789</div>
  <div class="item2">01234567890123456789</div>
  <div class="item3">01234567890123456789</div>
</div>

item的寬度為300px

item1的寬度為min(150,187.66)=150

item2的寬度為min(200,187.66)=187.66

item3的寬度為min(100,187.66)=100

150+187.66+100=437.66 > 300  flex子項撐破了父容器

 

 

3.flex元素父子高度

3.1 如果父元素設置了高度,則子元素中沒有設置高度的元素將繼承父元素的高度;

<style>
  .item {
    display: flex;
    height: 100px;
    background-color: blue;
  }

  .item1 {
    width: 100px;
    background-color: green;
  }
  .item2 {
    height: 50px;
    width: 100px;
    background-color: red;
  }
</style>
<div class="item">
  <div class="item1">item1</div>
  <div class="item2">item2</div>
</div>

 3.2 但是如果父元素設置了align-items屬性 那麼沒有設置高度的子元素的高度由自身內容決定

 

3.3 如果父元素沒有設置高度,其高度由最高的子元素決定。這個很好理解,不用驗證。

 

Tags: