CSS 3中彈性盒佈局的最新版

html5online發表於2015-04-23

 CSS 3中彈性盒佈局的最新版概述

  在CSS 3中,CSS Flexible Box模組為一個非常重要的模組,該模組用於以非常靈活的方式實現頁面佈局處理。

  雖然可以使用其他CSS樣式屬性來實現頁面佈局處理,但是如果使用CSS Flexible Box模組中定義的彈性盒佈局技術,可以根據螢幕尺寸或瀏覽器視窗尺寸自動調整頁面中各區域性區域的顯示方式,即實現非常靈活的佈局處理。

  雖然CSS Flexible Box模組已經被公佈了好幾年,但是自開始公佈以來,該模組中所定義的內容已經經過了幾次重大修改。目前公佈的正式版本為◦CSS Flexible Box Layout Module - W3C Candidate Recommendation, 18 September 2012

  目前為止,Opera 12.10版本以上,IE 11版本以上、Chrome 21版以上、Firefox 22版本以上的瀏覽器均支援該最新版本。

 從示例頁面開始學習最新版本的彈性盒佈局

  接下來開始通過一個示例頁面開始學習最新版本的彈性盒佈局。該示例頁面中的body元素中的程式碼如下所示。

<body>
<div id="main">
    <div class="content">
        <section>
            <h1>section 1</h1>
            <p>示例文字</p>
        </section>
        <section>
            <h1>section 2</h1>
            <p>示例文字</p>
        </section>
        <section>
            <h1>section 3</h1>
            <p>示例文字</p>
        </section>
        <section>
            <h1>section 4</h1>
            <p>示例文字</p>
        </section>
    </div>
    <div class="content">
        <section>
            <h1>section 5</h1>
            <p>示例文字</p>
            <section>
                <h1>section 6</h1>
                <p>示例文字</p>
            </section>
            <section>
                <h1>section 7</h1>
                <p>示例文字</p>
            </section>
            <section>
                <h1>section 8</h1>
                <p>示例文字</p>
            </section>
    </div>
    <div class="content">
        <section>
            <h1>section 9</h1>
            <p>示例文字</p>
        </section>
        <section>
            <h1>section 10</h1>
            <p>示例文字</p>
        </section>
        <section>
            <h1>section 11</h1>
            <p>示例文字</p>
        </section>
        <section>
            <h1>section 12</h1>
            <p>示例文字</p>
        </section>
    </div>
</div>
</body>

  接下來,首先對該頁面中各div元素及section元素指定邊框樣式,程式碼如下所示。

<style>
#main {
    border: 1px dotted #f0f;
    padding: 1em;
}
.content {
    border: 1px dotted #0ff;
    padding: 1em;
}
section {
    border: 1px dotted #f00;
    padding: 1em;
}
</style>

  在瀏覽器中開啟目前為止的示例頁面,頁面中各元素從上往下縱向排列,如下圖所示。

CSS 3中彈性盒佈局的最新版

 對示例頁面使用彈性盒佈局

  彈性盒佈局的指定方法為:對需要佈局的元素的容器元素使用display:flex;樣式屬性。在CSS Flexible Box模組中,該容器元素中的每一個元素均被稱為“Flex item”,將該容器元素稱為“Flex container”。

  彈性盒佈局方式與使用float等樣式屬性進行的佈局方式的一個主要區別為,當使用float等樣式屬性時,需要對容器中每一個元素指定樣式屬性,當使用彈性盒佈局時,只需對容器元素指定樣式屬性。

  接下來,我們首先對所有樣式類名為content的div元素使用彈性盒佈局,這些div元素的容器元素為id屬性值為main的div元素,修改該元素的樣式程式碼如下所示:

#main {
    border: 1px dotted #f0f;
    padding: 1em;
    display: flex;
}

  在瀏覽器中開啟示例頁面,頁面中所有樣式類名為content的div元素的排列方式被修改為橫向排列,如下圖所示。

CSS 3中彈性盒佈局的最新版

 設定元素排列方向

  可以通過flex-direction樣式屬性的使用來控制容器中所有子元素的排列方向,可指定值如下所示。

  • row:橫向排列(預設值)
  • row-reverse:橫向反向排列
  • column:縱向排列
  • column-reverse:縱向反向排列

  修改id屬性值為main的div元素的樣式程式碼如下所示:

#main {
    border: 1px dotted #f0f;
    padding: 1em;
    display: flex;
    flex-direction: row-reverse;
}

  在瀏覽器中開啟示例頁面,頁面中所有樣式類名為content的div元素的排列方式被修改為從容器元素,即id屬性值為main的div元素的右端開始橫向反向排列,如下圖所示。

CSS 3中彈性盒佈局的最新版

  接下來首先恢復所有樣式類名為content的div元素的排列方式為橫向正向排列,修改id屬性值為main的div元素的樣式程式碼如下所示:

#main {
    border: 1px dotted #f0f;
    padding: 1em;
    display: flex;
}

  然後對所有樣式類名為content的div元素指定flex-direction: column-reverse;樣式屬性,程式碼如下所示:

.content {
    border: 1px dotted #0ff;
    padding: 1em;
    display: flex;
    flex-direction: column-reverse;
}

  在瀏覽器中開啟示例頁面,頁面中所有content的div元素的所有section子元素的排列方式被修改為縱向反向排列(不包含section子元素中的section孫元素),如下圖所示。

CSS 3中彈性盒佈局的最新版

 使用order樣式屬性指定排列順序

  使用彈性盒佈局的時候,可以通過order屬性來改變各元素的顯示順序。可以在每個元素的樣式中加入order屬性,該屬性使用一個表示序號的整數屬性值,瀏覽器在顯示的時候根據該序號從小到大來顯示這些元素。

  接下來首先設定所有樣式類名為content的div元素的所有section子元素的排列方式為縱向正向排列,修改所有樣式類名為content的div元素的樣式程式碼如下所示:

.content {
    border: 1px dotted #0ff;
    padding: 1em;
    display: flex;
    flex-direction: column;
}

  接下來通過將所有樣式類名為content的div元素中的第2個section子元素的order樣式屬性值設定為-1的方法設定這些section子元素被優先顯示在其他section子元素之前,程式碼如下所示:

.content section:nth-child(2) {
    order: -1;
}

  在瀏覽器中開啟示例頁面,頁面中所有樣式類名為content的div元素中的第2個section子元素被顯示在其他section子元素之前,如下圖所示。

CSS 3中彈性盒佈局的最新版

 設定元素寬度及高度

  接下來首先介紹如何設定被橫向排列的每一個元素的寬度。

  可以通過flex屬性值的使用使所有子元素的總寬度等於容器寬度。

  接下來通過將所有樣式類名為content的div元素的flex屬性值設定為1的方法使所有樣式類名為content的div元素的總寬度等於容器元素,即id屬性值為main的div元素的寬度,程式碼如下所示。當所有樣式類名為content的div元素的flex屬性值都被設定為1時,這些div元素的寬度均等。

.content {
    border: 1px dotted #0ff;
    padding: 1em;
    display: flex;
    flex-direction: column;
    flex:1;
}

  在瀏覽器中開啟示例頁面,所有樣式類名為content的div元素的寬度自動增長,這些元素的總寬度等於容器元素,即id屬性值為main的div元素的寬度,每一個樣式類名為content的div元素的寬度均等,如下圖所示。

CSS 3中彈性盒佈局的最新版

  接下來,我們設定第二個樣式類名為content的div元素的flex屬性值為2,程式碼如下所示。

.content:nth-child(2) {
    flex:2;
}

  為了更清晰地計算元素寬度,我們取消所有元素的邊框設定及內邊距設定,修改後的完整樣式程式碼如下所示。

<style>
#main {
    display: flex;
}
.content {
    display: flex;
    flex-direction: column;
    flex:1;
}
.content section:nth-child(2) {
    order: -1;
}
.content:nth-child(2) {
    flex:2;
}
</style>

  在瀏覽器中開啟示例頁面,第二個樣式類名為content的div元素寬度為其他樣式類名為content的div元素寬度的兩倍,假設這些元素的容器元素,即id屬性值為main的div元素的寬度等於600px,則第一個與第三個樣式類名為content的div元素寬度的寬度均等於150px,第二個樣式類名為content的div元素寬度的寬度等於300px。

  可以使用flex-grow屬性來指定元素寬度,但是該樣式屬性對於元素寬度的計算方法與flex樣式屬性對於元素寬度的計算方法有所不同。

  接下來指定所有樣式類名為content的div元素的flex-grow樣式屬性值為1,寬度為150px,指定第二個樣式類名為content的div元素的flex-grow樣式屬性值為為3。修改後的完整樣式程式碼如下所示。

<style>
#main {
    display: flex;
}
.content {
    display: flex;
    flex-direction: column;
    width:150px;
    flex-grow:1;
}
.content section:nth-child(2) {
    order: -1;
}
.content:nth-child(2) {
    flex-grow:3;
}
</style>

  在瀏覽器中開啟示例頁面,假設這些元素的容器元素,即id屬性值為main的div元素的寬度等於600,則第一個與第三個樣式類名為content的div元素寬度的寬度均等於180px,第二個樣式類名為content的div元素寬度的寬度等於240px。對於每個樣式類名為content的div元素寬度的計算步驟如下所示:

  1. 600(容器寬度)-150*3(三個樣式類名為content的div元素寬度的總寬度)=150
  2. 150/5(三個樣式類名為content的div元素寬度的flex-grow樣式屬性值的總和)=30
  3. 第一個與第三個樣式類名為content的div元素寬度的寬度均等於150(其width樣式屬性值+)+30*1(其flew-grow樣式屬性值)=180px
  4. 第二個樣式類名為content的div元素寬度的寬度等於150(其width樣式屬性值+)+30*3(其flew-grow樣式屬性值)=240px

  可以使用flex-shrink屬性來指定元素寬度,該樣式屬性與flex-grow樣式屬性的區別在於:當子元素的width樣式屬性值的總和小於容器元素的寬度值時,必須通過flex-grow樣式屬性來調整子元素寬度,當子元素的width樣式屬性值的總和大於容器元素的寬度值時,必須通過flex-shrink樣式屬性來調整子元素寬度。

  接下來指定所有樣式類名為content的div元素的flex-shrink樣式屬性值為1,寬度為250px,指定第二個樣式類名為content的div元素的flex-shrink樣式屬性值為為3。修改後的完整樣式程式碼如下所示。

<style>
#main {
    display: flex;
}
.content {
    display: flex;
    flex-direction: column;
    width:250px;
    flex-shrink:1;
}
.content section:nth-child(2) {
    order: -1;
}
.content:nth-child(2) {
    flex-shrink:3;
}
</style>

  在瀏覽器中開啟示例頁面,假設這些元素的容器元素,即id屬性值為main的div元素的寬度等於600,則第一個與第三個樣式類名為content的div元素寬度的寬度均等於220px,第二個樣式類名為content的div元素寬度的寬度等於160px。對於每個樣式類名為content的div元素寬度的計算步驟如下所示:

  1. 250*3(三個樣式類名為content的div元素寬度的總寬度)-600(容器寬度)=150
  2. 150/5(三個樣式類名為content的div元素寬度的flex-shrink樣式屬性值的總和)=30
  3. 第一個與第三個樣式類名為content的div元素寬度的寬度均等於250(其width樣式屬性值+)-30*1(其flew-shrink樣式屬性值)=220px
  4. 第二個樣式類名為content的div元素寬度的寬度等於250(其width樣式屬性值+)-30*3(其flew-grow樣式屬性值)=160px

  在使用flex-grow樣式屬性或flex-shrink樣式屬性調整子元素寬度時,也可以使用flex-basis樣式屬性指定調整前的子元素寬度,該樣式屬性與width樣式屬性的作用完全相同。

  可以將flex-grow、flex-shrink以及flex-basis樣式屬性值合併寫入flex樣式屬性中,方法如下所示。

flex:flex-grow樣式屬性值 flex-shrink樣式屬性值 flex-basis樣式屬性值;

  在使用flex樣式屬性值時,flex-grow、flex-shrink以及flex-basis樣式屬性值均為可選用樣式屬性值,當不指定flex-grow、flex-shrink樣式屬性值時,預設樣式屬性值均為1,當不指定flex-basis樣式屬性值時,預設樣式屬性值為0px。

  修改本示例中的樣式程式碼如下所示:

<style>
#main {
    display: flex;
}
.content {
    display: flex;
    flex-direction: column;
    width:250px;
    flex:250px;
}
.content section:nth-child(2) {
    order: -1;
}
.content:nth-child(2) {
    flex:1 3 250px;
}
</style>

  在瀏覽器中開啟示例頁面,假設這些元素的容器元素,即id屬性值為main的div元素的寬度等於600,則第一個與第三個樣式類名為content的div元素寬度的寬度均等於220px,第二個樣式類名為content的div元素寬度的寬度等於160px。

  在子元素為橫向排列時,flex、flex-grow、flex-shrink以及flex-basis樣式屬性均用於指定或調整子元素寬度,當子元素為縱向排列時,flex、flex-grow、flex-shrink以及flex-basis樣式屬性均用於指定或調整子元素高度。

 單行佈局與多行佈局

  可以使用flex-wrap樣式屬性來指定單行佈局或多行佈局,可指定樣式屬性值如下所示:

  • nowrap:不換行
  • wrap:換行
  • wrap-reverse:雖然換行,但是換行方向與使用wrap樣式屬性值時的換行方向相反

  接下來首先恢復頁面內各div元素的邊框與內邊距(padding)的指定,同時指定所有樣式類名為content的div元素的寬度為250px,程式碼如下所示。

<style>
#main {
    border: 1px dotted #f0f;
    padding: 1em;
    display: flex;
}
.content {
    border: 1px dotted #0ff;
    padding: 1em;
    display: flex;
    flex-direction: column;
    flex:250px;
}
section {
    border: 1px dotted #f00;
    padding: 1em;
}
.content section:nth-child(2) {
    order: -1;
}
</style>

  然後指定容器元素,即id屬性值為main的div元素的flex-wrap樣式屬性值為wrap,以指定允許對所有樣式類名為content的div元素進行換行佈局,程式碼如下所示。

#main {
    border: 1px dotted #f0f;
    padding: 1em;
    display: flex;
    flex-wrap: wrap;
}

  在瀏覽器中開啟示例頁面,當瀏覽器視窗寬度不足以容納三個樣式類名為content的div元素時,最右邊的樣式類名為content的div元素被換行顯示,如下圖所示。

CSS 3中彈性盒佈局的最新版

  可以將flex-direction樣式屬性值與flex-wrap樣式屬性值合併書寫在flex-flow樣式屬性中。以下兩段程式碼的作用完全相同。

//使用flex-direction樣式屬性與flex-wrap樣式屬性
.content {
    flex-direction: row;
    flex-wrap: wrap;
}
//使用flex-flow樣式屬性
.content {
    flex-flow: row wrap;
}

 彈性盒佈局中的一些專用術語

  接下來首先介紹彈性盒佈局中的一些專用術語,在進行佈局時這些術語的含義如下圖所示。

CSS 3中彈性盒佈局的最新版

  • main axis:進行佈局時作為佈局基準的軸,在橫向佈局時為水平軸,在縱向佈局時為垂直軸。
  • main-start / main-end:進行佈局時的佈局起點與佈局終點。在橫向佈局時為容器的左端與右端,在縱向佈局時為容器的頂端與底端。
  • cross axis:與main axis垂直相交的軸,在橫向佈局時為垂直軸,在縱向佈局時為水平軸。
  • cross-start / cross-end:cross axis軸的起點與終點。在橫向佈局時為容器的頂端與底端,在縱向佈局時為容器的左端與右端。將flex-wrap屬性值指定為wrap且進行橫向多行佈局時,按從cross-start到cross-end方向,即從上往下佈局,將flex-wrap屬性值指定為wrap-reverse且進行橫向多行佈局時,按從cross-end到cross-start方向,即從下往上佈局。

 justify-content屬性

  justify-content屬性用於指定如何佈局容器中除了子元素之外的main axis軸方向(橫向佈局時main axis軸方向為水平方向,縱向佈局時main axis軸方向為垂直方向)上的剩餘空白部分。

  當flex-grow屬性值不為0時,各子元素在main axis軸方向上自動填滿容器,所以justify-content屬性值無效。

  可指定justify-content屬性值如下所示:

  • flex-start:從main-start開始佈局所有子元素(預設值)。
  • flex-end:從main-end開始佈局所有子元素。
  • center:居中佈局所有子元素。
  • space-between:將第一個子元素佈局在main-start處,將最後一個子元素佈局在main-end處,將空白部分平均分配在所有子元素與子元素之間。
  • space-around:將空白部分平均分配在以下幾處:main-start與第一個子元素之間、各子元素與子元素之間、最後一個子元素與main-end之間。

  上述各屬性值的區別如下圖所示(灰色代表空白部分)。

CSS 3中彈性盒佈局的最新版

 align-items屬性與align-self屬性

  align-items屬性與justify-content屬性類似,用於指定子元素的對齊方式,但是align-items屬性指定的是cross axis軸方向(橫向佈局時cross axis軸方向為垂直方向,縱向佈局時cross axis軸方向為水平方向)上的對齊方式,可指定屬性值如下所示。

  • flex-start:從cross-start開始佈局所有子元素(預設值)。
  • flex-end:從cross-end開始佈局所有子元素。
  • center:居中佈局所有子元素。
  • baseline:如果子元素的佈局方向與容器的佈局方向不一致,則該值的作用等效於flex-start屬性值的作用。如果子元素的佈局方向與容器的佈局方向保持一致,則所有子元素中的內容沿基線對齊。
  • stretch:同一行中的所有子元素高度被調整為最大。如果未指定任何子元素高度,則所有子元素高度被調整為最接近容器高度(當考慮元素邊框及內邊距時,當邊框寬度與內邊距均為0則等於容器高度)。

  上述各屬性值的區別如下圖所示(灰色代表空白部分)。

CSS 3中彈性盒佈局的最新版

  align-self屬性與align-items屬性的區別在於:align-items被指定為容器元素的樣式屬性,用於指定所有子元素的對齊方式,而align-self屬性被指定為某些子元素的樣式屬性,用於單獨指定這些子元素的對齊方式。例如將容器元素的align-items屬性值指定為center(居中對齊)後,可以將第一個子元素的align-self屬性值指定為flex-start(對齊在cross-start端)。可指定值如下所示:

  • auto:繼承父元素的align-items屬性值
  • flex-start
  • flex-end
  • center
  • baseline
  • stretch

 align-content屬性

  當進行多行佈局時,可以使用align-content屬性來指定各行對齊方式。該屬性與align-items屬性的區別在於:align-items屬性用於指定子元素的對齊方式,而align-content屬性用於指定行對齊方式。可以指定的屬性值如下所示:

  • flex-start:從cross-start開始佈局所有行。
  • flex-end:從cross-end開始佈局所有行。
  • center:居中佈局所有行。
  • space-between:將第一行佈局在cross-start處,將最後一行佈局在cross-end處,將空白部分平均分配在各行之間。
  • space-around:將空白部分平均分配在以下幾處:cross-start與第一行之間、各行與行之間、最後一行與cross-end之間。

  上述各屬性值的區別如下圖所示(灰色代表空白部分)。

CSS 3中彈性盒佈局的最新版

相關文章