CSS關於flex佈局

宮商角徵羽發表於2018-04-23

注意: Flexbox佈局最適合應用程式的元件和小規模佈局,而Grid佈局則適用於更大規模的佈局

flex的基本屬性

談flex佈局前先了解下flex的基本屬性

flex的基本屬性有 flex-basisflex-directionflex-wrapflex-flowflex-growflex-shrink 六個


使用到的HTML模板

   <style> 
        #main
        {
        	width:300px;
        	height:200px;
        	border:1px solid black;
        	display:flex;
        }

        #main div{
        	flex:1;
        }
    </style>
    
    <body>
        <div id="main">
          <div class='showDiv' style="background-color:coral;"></div>
          <div class='showDiv' style="background-color:lightblue;"></div>  
          <div class='showDiv' style="background-color:lightgreen;"></div>
        </div>
    
        <p><b>注意:</b> Internet Explorer 9 及更早版本不支援 flex 屬性。</p>
        <p><b>注意:</b> Internet Explorer 10 通過 -ms-flex 屬性來支援。 IE11 及更新版本完全支援 flex 屬性 (不需要 -ms- 字首)。</p>
        <p><b>注意:</b> Safari 6.1 (及更新瀏覽器) 通過 -webkit-flex 屬性支援。</p>
    </body>
    <script>
	   var timer = setInterval(function(){
            var divs=document.getElementsByClassName('showDiv')
            for (var i=0;i<divs.length;i++){
              divs[i].innerHTML=divs[i].clientWidth
            }
        },1000)
        timer();
    </script>

複製程式碼

此時呈現的樣式為:

Markdown

這裡的 #main div{ flex:1; }讓所有彈性盒模型物件的子元素都有相同的長度,忽略它們內部的內容。因此看到的三個div寬度相等


1. flex 屬性用於設定或檢索彈性盒模型物件的子元素如何分配空間。

2. 如果元素不是彈性盒模型物件的子元素,則 flex 屬性不起作用。


[TOC]

flex-basis

flex-basis 用於設定彈性盒子初始大小或伸縮基準值

例如設定第二個彈性盒子元素的初始長度為126畫素,css設定如下:

    #main div:nth-of-type(2) {flex-basis: 40px;}
複製程式碼

此時呈現的樣式為:

Markdown

可以看到第二個背景為藍色的div寬度為126px,其餘兩個div寬度為87px。這是因為上面第二個div設定了flex-basis: 40px;,導致ID為#main的大div(父級盒子)優先分配給第二個div 40px的寬度,剩下的260px寬度再平均分配給三個子級div(因為前面設定了#main div{ flex:1; },所以三個div都擁有相同的長度/寬度)。

簡而言之,flex-basis就是從父級中提前取出一定大小的長度提前分配給指定元素。

flex-direction

flex-direction 用於設定彈性盒子內子元素的排列放向。

flex-direction常用的的屬性值有:row、row-reverse、column、column-reverse,分別對應:按行排列、按行反序排列、按列排列、按列反序排列。

例如設定#main盒子內的元素按行反序排列:

    #main{flex-direction: row-reverse;}
複製程式碼

此時呈現的樣式為:

Markdown
可以看到原來從左至右的div背景為紅藍綠,設定後從左至右的div背景為綠藍紅,順序剛好反過來了。 如果設定如下:

    #main{flex-direction: column-reverse;}
複製程式碼

那麼div將按列反序排列,從上到下依次為背景色是綠藍紅的div,如下圖所示:

Markdown

flex-wrap

flex-wrap 用於規定flex容器是單行或者多行,同時橫軸的方向決定了新行堆疊的方向。

flex-wrap 常用的屬性值有:nowrap、wrap、wrap-reverse。

  1. nowrap為預設值,規定靈活的專案不拆行或不拆列。
  2. wrap規定靈活的專案在必要的時候拆行或拆列。
  3. wrap-reverse規定靈活的專案在必要的時候拆行或拆列,但是以相反的順序。 例如HTML部分設定如下:
<div id="main">
  <div style="background-color:coral;">A</div>
  <div style="background-color:lightblue;">B</div>
  <div style="background-color:khaki;">C</div>
  <div style="background-color:pink;">D</div>
  <div style="background-color:lightgrey;">E</div>
  <div style="background-color:lightgreen;">F</div>
</div>
複製程式碼

CSS部分設定如下:

#main {
  width: 200px;
  height: 150px;
  border: 1px solid #c3c3c3;
  display: flex;
  flex-wrap: wrap;
}
#main div {
  width: 50px;
  height: 50px;
}
複製程式碼

此時,定義了 flex-wrap: wrap; ,六個div寬度總和300px超出了 #main 父元素的寬度,子元素div將自動換行排列。

結果顯示如下:

Markdown

如果將 flex-wrap: wrap; 設定為: flex-wrap: wrap-reverse;,那麼當發生換行(列)時,將會反序排列。 效果如下:

Markdown

如果將 flex-wrap: wrap; 設定為:flex-wrap:nowrap;,那麼子元素div將不會換行排列(不是超出部分不顯示了,而是子元素div的寬度將改變以適應父元素寬度),效果如下:

Markdown

flex-flow

flex-flow 屬性是 flex-direction 和 flex-wrap 屬性的複合屬性。flex-flow 屬性用於設定或檢索彈性盒模型物件的子元素排列方式。flex-direction 屬性規定靈活專案的方向。 flex-flow 預設值為:flex-flow:row nowrap; CSS語法為:

flex-flow: flex-direction flex-wrap | initial | inherit;

flex-grow

flex-grow 屬性用於設定或檢索彈性盒的擴充套件比率。 例如在最初的模板中給CSS設定:

#main div{flex-basis:50px;}

#main div:nth-of-type(1) {flex-grow: 1;}
#main div:nth-of-type(2) {flex-grow: 3;}
#main div:nth-of-type(3) {flex-grow: 1;}
複製程式碼

同時去掉#main div{flex:1;},效果如下:

Markdown

此處設定了每個div的flex-basis:50px;,即每個div基礎寬度為50px;而容器總寬度為300px,超出div總寬度150px。剩下的寬度按照 flex-grow 分配的1、3、1這樣將150px平均分成五份再根據各自的份數加上div基礎寬度,所以第一個div寬度為: 50+(150/5)* 1 = 80 px ; 類似的第二個div寬度為: 50 + (150/5) * 3 = 140px。

flex-shrink

flex-shrink 屬性用於設定或檢索彈性盒的收縮比率。

但是,flex-shrink 計算收縮量的演算法並不同於 flex-growflex-shrink 計算收縮量的演算法使用的是一種加權平均數的演算法。

例如在最初的模板中給CSS設定:

#main div:nth-of-type(1) {flex-shrink: 1;flex-basis:200px;}
#main div:nth-of-type(2) {flex-shrink: 3;flex-basis:100px;}
#main div:nth-of-type(3) {flex-shrink: 1;flex-basis:100px;}
複製程式碼

此時顯示如下:

Markdown
可以看到三個div的寬度分別是:167px、50px、83px。

具體演算法如下:

  1. 先算出超出的寬度:a=200+100+100-300=100px

    超出的100px將按照收縮比1:3:1收縮。

  2. 在算出每個元素的乘積(用自身寬度乘以分配的權重(flex-shrink)):

  • div1 :b1=200*1=200
  • div2 :b2=100*3=300
  • div3 :b3=100*1=100
  • 總和為 c=600
  1. 計算每個元素收縮量
  • div1 :d1=(b1/c)*a=33.3 px
  • div2 :d2=(b2/c)*a=50 px
  • div3 :d3=(b3/c)*a=16.7 px
  1. 計算每個元素實際寬度
  • div1 :w1=200-33.3=166.7px
  • div2 :w2=100-50=50px
  • div3 :w3=100-16.7=83.3px

相關文章