2016年5月7日 星期六

CSS3 Flex Box - Part 1

CSS3 Flex Box - Part 1

簡介

CSS3 的規範裡提供了一個新的 box model,稱為「彈性盒」(flexible or flex box),讓網頁設計師在設計時更容易排版。當某元件的 display 屬性值定為 flex 或 inline-flex 時,該元件便成為一個彈性盒的元件。設定值為 flex 時,彈性盒在許多基礎的設定及行為模式都和一般區塊級 (block-level) 的區塊相同,width 和 height 的預設值都是 auto;除非有明確的設定,否則都是由計算而來。在彈性盒元件的後面也會自動換行。雖然和一般的區塊元件極為雷同,但彈性盒還是有些特別的地方,例如:float, clear, vertical-align, column-* 這些屬性在彈性盒的排版中都不起作用。彈性盒依據數個屬性的設定,對其子元件有其自己的排版方式。當 display 設定值為 inline-flex 時,則產生一個行內級 (inline-level) 的元件,在彈性盒元件之後不自動換行。

首先介紹一些名詞及術語以方便未來的解釋之用。下方是一幅由 W3C 文件中所擷取的圖片。

參與彈性 (flex) 排版的元件分成兩大類:

flex container
當元件的 display 屬性值定為 flex 或 inline-flex 時,該元件便成為一個「彈性容器」(flex container)。每一個彈性容器都具有兩條軸線:主軸 (main axis) 及側軸 (cross axis),各軸又各具有起點 (start) 及終點 (end) 用以決定在容器中各彈性元件在排版時的走向。主軸的走向並非固定,而側軸的走向則永遠和主軸垂直。主軸的走向是由 flow-direction 屬性的設定值所決定,當設定值為 row 或 row-reverse 時,主軸成水平走向,預設為由左至右;側軸則為垂直走向,預設為由上至下。當設定值為 column 或 column-reverse 時,主軸成垂直走向,預設走向為從上至下;側軸成水平走向,預設為為從左至右。當設定值為 *-reverse 時,主軸的起點和終點的位置互換,主軸的走向會反轉,側軸的走向不變;也就是說 flow-direction 的 *-reverse 設定值只會反轉主軸的走向。
flex item
flex container 元件中的子元件,都稱為「彈性元件」(flex item)。彈性盒的模式可以形成結構式的方式存在,也就是說,一個彈性元件可以再行定義成一個彈性容器以包含其它的彈性元件,以此類推,以形成多層式的結構。

以下為 flex-direction 及 flex-wrap 兩個屬性的設定值及意義:

flex-direction
設定彈性容器主軸的走向。
row
定義主軸為水平走向,預設為由左至右。此為預設值。
row-reverse
定義主軸為水平走向,但將預設的起點和終點互換,反轉主軸的預設走向為由右至左。
column
定義主軸為垂直走向,預設為由上至下。
column-reverse
定義主軸為垂直走向,但將預設的起點和終點互換,反轉主軸的預設走向為由下至上。
flex-wrap
設定主軸長度不足以容納所有彈性元件時,是否要換行。
nowrap
設定為不換列,壓縮各彈性元件以擠入同一列或同一欄。此為預設值。
wrap
設定為換列,在剩餘空間不足以容納下一個彈行元件時換列。
wrap-reverse
將側軸的起點和終點互換,反軸側軸的走向。

以下的解說及圖均以 display:row 為例,略去 column 及 *-reverse 的部份。在預設的情形下,彈性容器的排版以單「列」(row) 或單「欄」(column) 為主,彈性容器會試圖將所有的彈性元件排在同一列或同一欄中。在主長度足夠容納所有的彈性元件時,如下圖所示:

當主長度不足以容納所有的彈性元件時,彈性容器會平均壓縮每一彈性元件,盡可能將所有的彈性元件擠在同一列中,如下圖所示:

flex-direction 設定為 row-reverse,則反轉主軸的走向,結果如下圖所示:

如果在主長度不足,卻又希望能保持彈性元件的原形,則可以設定 flex-wrap 的屬性值為 wrap,將在同列排不下的元件,排到下一列去,彈性容器會在剩餘空間不足以完全容納下一個彈性元件時,便移至下一列開始排起,若此時彈性容器的 height 值為 auto,彈性容器會計算出最小所需高度,則結果如下圖所示:

若 flex-wrap 設定為 wrap-reverse,則會反轉側軸的走向,結果如下圖所示:

若彈性容器的 height 值有明確設定的值時,這個值等於側軸長度;彈性容器會將 height 值除以所需的列數做為每列的高度,此時結果會如下圖所示,若設定的高度不足以容納,則彈性元件會超出彈性容器的範圍。

範例

在範例中,設定一個具有七個正方形彈性元件的彈性容器。每個彈性元件都有標號,可以看清主軸的走向。範例中的圖像只顯示橫向排列的結果,直向排列的結果就不顯示了。最重要的是把排列的邏輯理清楚。

CSS

<style>
html {
    width:100%;
    height:auto;
    font:normal normal normal 1em Arial, '文泉驛正黑', 'WenQuanYi Zen Hei', '儷黑 Pro', 'LiHei Pro', '微軟正黑體', 'Microsoft JhengHei';
}
body {
    margin: 0 auto;
    width: 800px;
    padding:20px;
}
.container {
    display: flex;
    flex-direction:row;
    /* flex-wrap:wrap; */  /* unmark this line to wrap */
    width: 200px;
    /* height:150px; */    /* unmark to set height */
    padding:20px;
    background-color: lightgreen;
}
.center {
    display:flex;
    justify-content: center;
    align-items:center;
}
.item {
    width:40px;
    height:40px;
    border:1px solid black;
    background-color: coral;
    font-size:2em;
}
</style>

.container{} 設定彈性容器的屬性: display: flex; ,設定為區塊級的彈性容器。 flex-direction: row; 設定子元件的排列以列方向前行,此時主軸走向為水平,排列方式為從左到右。width: 400px; 將寬度設為 400px 足以容納七個長寬各為 40px 的正方形子元件;稍後,將寬度改成 200px,同時取消flex-wrap:wrap; 這行的註解,彈性容器便會壓繪各彈性元件以便擠入一列之中。
height 屬性則先註解掉,彈性容器會自行計算足夠的高度。取消註解後,上下兩列就會分的比較開。
.center{} 也是定義元件為彈性容器,因為每個彈性元件又同時具有 .center 類別,所以每個彈性元件同時又是彈性容器,成為一個兩層式的結構。 justify-content:center 設定將內容於主軸走向置中, align-item:center 設定將子元件於副軸走向置中。兩個屬性都設定為 center 時,會將所有子元件集合而成的內容置於 flex container 的正中央。這兩個屬性以後再討論。

HTML

<body>
1
2
3
4
5
6
7
</body>

沒有留言:

張貼留言