天天看點

flexbox基本原理 基本原理 container items

新版的flexbox規範分兩部分:一部分是container,一部分是 items。

flexbox是一整套布局規範,包含了多個css屬性,是以學習起來比`float: left;` 這樣簡單的布局要複雜很多。

flexbox基本原理 基本原理 container items

容器上有 主軸和縱軸的概念,預設主軸(main-axis)是橫向,從左到右,縱軸是豎向,從上到下。其中所有的孩子的布局都會受到這兩個軸的影響。後面會講到,有很多相關的css屬性就是通過改變主軸和縱軸的方向來實作不同的布局效果的。

div上設定 `display: flex` 或者 `display: inline-flex` 來變成一個flex容器。然後給其中的每一個孩子設定 `flex: [number]` 來讓他們按比例配置設定容器的寬度。

比如三個item分别設定了 `flex: 1` `flex: 2` `flex: 1` 則他們是按照 1-2-1 的比例來配置設定寬度的。

如果有item沒有設定 `flex` 而是設定了寬度,比如 `width: 100px` 那麼它的寬度就不受flex容器的影響,但是其他的設定了 `flex: [number]` 的容器會按比例平分剩下的部分。即使通過 `width: 100px` 的方式定死寬度,除了和 flex: 1 的寬度計算方式不同之外,其他并沒有不同。

其實應該說,如果一個孩子沒有通過 flex: 1的方式來定義寬度,那麼會根據非flex的方式來優先計算它的寬度,然後其他的聲明了flex的孩子再按比例配置設定剩下的寬度。

如下圖所示,其中隻有第一個孩子聲明了 `flex:1` ,後面的都沒有申明寬度,那麼在flexbox容器中,後面的7個孩子都是由他們中的文字撐開的寬度,剩餘的寬度全部配置設定給第一個孩子。

flexbox基本原理 基本原理 container items

後面還會仔細講 `flex: 1` 定義孩子寬度的細節。

display

`display: flex` 或者 `display: inline-flex` 來聲明一個flexbox容器

flex-direction

flexbox基本原理 基本原理 container items
flexbox基本原理 基本原理 container items

items的排列方向,其實就是改變了上面所說的 主軸方向,是以這個屬性會其他屬性産生影響,因為整個flexbox的布局都是由主軸和縱軸決定的。

row: 從左到右

row-reverse: 從右到左

colum: 從上到下

colum-reverse: 從下到上

下面分别是這四個值的結果

flexbox基本原理 基本原理 container items

flex-wrap

當内容超出之後是否折行。

nowrap:不換行,而是通過收縮每一個孩子的寬度來擠在一行。

wrap: 換行。

wrap-inverse: 換行,但是折行方向相反,(比如預設是折到下一行,但是這個屬性會導緻折到上一行)。

如下圖所示,分别是上述的三個值的效果,其中每一個孩子寬度為 40px,8個孩子已經超出了容器的 200px寬度。

flexbox基本原理 基本原理 container items

flex-flow

flex-direction 和 flex-wrap 的組合寫法。

justify-content

不知道如何準确翻譯 justify 這個詞。它的作用是定義了如何配置設定剩餘的空白區域。

flex-start:主軸方向

flex-end: 主軸反方向

center: 擠在中間

space-between: 中間有空白。

space-around: 中間和兩邊都有空白。其中兩側的空白是中間的一半寬度,可以了解為每個孩子兩側都有相同寬度的空白,并且空白不合并。

上面說過,flex-direction 會改變主軸方向,下面我們看看 flex-direction 為預設情況下(從左到右)這五個不同值的差別:

flexbox基本原理 基本原理 container items

發現一個bug,在chrome下,在調試器下直接切換space-between  space-around 是不生效的。

然後我們設定一下 `flex-direction: column`,會發現他們的主軸已經變成從到上下了:

flexbox基本原理 基本原理 container items

align-items

孩子的對齊方式,這個比較好了解。就是孩子的對齊方式。

注意,這裡的“對齊”指的是縱軸上的對齊方式,是以,這個屬性也是受 `flex-direction` 影響的。

比如我有一個高度為100 px的容器,那麼預設情況下,是scratch,就是在縱軸上填滿容器。

flexbox基本原理 基本原理 container items

如上圖所示,隻定義了容器高度,預設情況下孩子的高度就會填滿容器。

如果我改成`align-items: flexstart`  就會是這樣

flexbox基本原理 基本原理 container items

align-items 所有屬性值如下:

flex-start: 縱軸開始

flex-end: 縱軸結束

center: 縱軸居中

baseline: 縱軸的baseline

scratch: 填滿容器。

align-content

當有多行内容的時候,這個屬性決定了如何對多行内容進行對齊。

注意,上面的每一個屬性都是以每一個item為機關進行布局,而這個屬性是以一行為機關進行布局。感覺這個屬性應該叫 align-lines 比較合适。

如果隻有一行的話,這個屬性是不生效的,是以一定要配合 `flex-wrap: wrap` 來使用。

flexbox基本原理 基本原理 container items

order

很簡單,排列順序,沒什麼好講的。

flex-grow

定義了主軸上,孩子配置設定剩餘空白區域的比例。

比如現在有三個孩子,寬度是 40px,并且`margin: 2px`,容器寬度 200px,那麼預設情況下,有 `(200-44)/3=68` 空白的寬度。

flexbox基本原理 基本原理 container items

如果你給每個孩子都定義了 `flex-grow: 1`,那麼他們平分剩餘的空白區域,就是這樣:

flexbox基本原理 基本原理 container items

這時候,如果我給第二個孩子定義 `flex-grow: 2`,那麼它的寬度是怎麼計算的?

其實就是把 68px 的空白按照`1:1:2` 的比例配置設定給他們,也就是 `17:17:34` 的大小來配置設定,是以三個孩子的寬度分别為 `57,57,74`:

flexbox基本原理 基本原理 container items

如果你給一個孩子設定為 `flex-grow: 0` 那麼它不會參與剩餘空白的配置設定。

flex-shrink

如果孩子的總寬度超過了容器寬度(主軸),那麼這個屬性定義了如何把超過的那部分平分到每個孩子身上,然他們按比例來縮小一定的寬度進而可以在容器中裝得下。

假設我們現在有一個容器,寬度為 `200px`,有三個孩子寬度為 `100px`,并且每個海澤有 `margin: 2px`,那麼三個孩子總寬度 `(100+2*2)*3 = 312px` ,超過了 112px。

是以我們從這三個孩子身上砍下 `112px` 寬度,以讓他們能裝進容器中。

預設情況下,是 按 `1:1:1` 的比例來砍,也就是每個孩子各砍下 “112/3=37.3“,是以預設每個孩子寬度是 100-37.3=62.7。

那麼現在我們定義第二個孩子 `flex-shrink: 2`,其他兩個為 1,那麼他們會把 `112px` 的寬度按 `1:2:1` 來平分。于是第二個孩子寬度為 `100-(112/4*2)=44px` 寬度,另外兩個為`100-(112/4*1)=72px`:

flexbox基本原理 基本原理 container items

flex-basis

在配置設定空白之前,孩子的寬度,預設是 `auto`,也就是孩子本身的寬度,如果你定義了 `flex-basis: 50px;` ,那麼它就會覆寫掉孩子的寬度。

flex

他是 flex-grow, flex-shrink, flex-basis三個屬性的快捷方式。預設是 0, 1, auto。

強烈建議用這個屬性,而不是分别設定三個屬性,因為這個屬性可以“聰明地”設定三個屬性來達到你要的效果。

你可以認為 flex 屬性就是定義了每個孩子分隔父容器寬度的比例。

比如容器 200px,三個孩子設定了 flex 分别是 1-2-1,那麼他們實際上寬度是 50px 100px 50px。

如果你比較較真,這個flex屬性到底是如何工作的?

實際上他是自動設定了三個屬性:flex-grow, flex-shrink, flex-basis。

而且為什麼強烈推薦用flex,而不是分别設定三個屬性,是因為 flex 屬性會自動計算 flex-basis 屬性的值。

比如容器寬度為 200px,然後你給三個孩子分别設定了

.item1 { flex: 1;}

.item2 { flex: 2;}

.item3 { flex: 1;}

那麼他們的寬度将是 50-100-50

如果你想單獨設定每一個孩子的三個屬性,你會發現竟然無法按照 1-2-1 的比例平分了。

因為flexbox的計算每個孩子的寬度分兩部分:

1,計算出孩子本身的寬度

2,将剩餘的空白按比例平分給每一個孩子。

是以你如果這樣定義:

.item1 { flex-grow: 1;flex-shrink:1;}

.item2 { flex-grow: 2;flex-shrink:2;}

.item3 { flex-grow: 1;flex-shrink:1;}

你會發現孩子不是 50-100-50 的寬度,因為他們是按照 1-2-1 平分了剩餘的空白。

假設每個孩子本身是 20px 寬度,那麼這麼定義之後,他們其實按 1-2-1 平分了 140px 的空白。加上自身寬度之後比例 顯然不是 1-2-1。

是以你還需要把它們的flex-basis也設定成 1-2-2,這麼寫才行:

.item1 { flex-grow: 1;flex-shrink:1;flex-basis: 20px;}

.item2 { flex-grow: 2;flex-shrink:2;flex-basis: 40px;}

.item3 { flex-grow: 1;flex-shrink:1;flex-basis: 20px;}

而這樣就很麻煩,不如直接用 flex 屬性來定義。而事實上,你可以認為 flex 屬性就是幫你做了上面的計算。

align-self

單獨在目前孩子上覆寫了 align-items 屬性。

下一篇: Hibernate入門

繼續閱讀