在 CSS flexbox 佈局出現之前,若是要控制 HTML 元素的佈局,要用到不少種奇葩的方式。在水平方向上得用float
控制左右對齊,稍一不注意,就會有浮動的元素飛來飛去~。在垂直方向上就更是百家爭鳴了:要麼手動計算高度而後算出中心點,要麼用 line-height
和 height
的結合,要麼用十之八九不生效的 vertical-align
屬性等等等等。自從 flex-box 出現之後,一切彷佛就豁然開朗了,水平垂直各類花式對齊,空間分配由你作主。固然,要用好它,用對它也不是一件容易的事,今天就給你說說 flex-box 佈局,看完以後你也能熟練的運用它!css
2 分鐘視頻入門版:2 分鐘掌握 CSS Grid 佈局html
真實 HTML 代碼(非圖片)示例版:請點此訪問(示例都是真實的 HTML 代碼,可使用 chrome 開發者工具查看屬性。chrome
假設有下邊這麼一個 html 結構:瀏覽器
<div class="flex">
<div class="flex1">Flex 1</div>
<div class="flex2">Flex 2</div>
<div class="flex3">Flex 3</div>
</div>
複製代碼
一個div
容器包含了三個 div
子元素,按照默認的佈局方式進行排列。由於 div
是塊級元素,每一個 div
佔了整個一行的空間:ide
若是要開啓容器的 flex 佈局,只須要在 css 裏邊給 .flex
設置 display: flex
屬性,同時爲了演示效果,我給它加上了 100px 的高度:工具
display: flex;
height: 100px;
複製代碼
能夠看到裏邊的三個元素自動變成了一行,由於 flex 默認是按行進行排列的。Flexbox 佈局是一維佈局方式,要麼按行排列,要麼按列排列。佈局
Flex 佈局有一個隱式的座標空間,水平方向有一條主軸(main-axis),垂直方向上有一條交叉軸(cross-axis):flex
控制主軸(即水平方向)對齊方式使用justify-content
屬性,它有下邊幾種對齊方式:flexbox
flex-start
是默認值,若是是從左到右的文字閱讀習慣(LTR),就是靠左對齊。由於默認的對齊方式,因此跟上邊的例子沒有什麼區別:spa
justify-content: flex-start;
複製代碼
居中對齊,此時整個 flex 容器被居中到了頁面中間:
靠右對齊:
兩端對齊,這種對齊方式是第一個和最後一個元素貼邊,中間的元素平分剩餘的空間:
分散對齊,全部的元素都平分空間:
跟space-evenly
相似,可是左右兩邊的留白爲平分空間的 1/2.
控制交叉軸方向(即垂直方向)上的對齊方式使用align-items
屬性,有下邊幾種對齊方式:
stretch
是 align-items
的默認值,它會自動把子元素拉伸成容器的高度,因此以前的例子裏子元素在垂直方向上都佔滿了容器,只要改變容器的align-items
的值,它就會變成內容的高度。stretch
對齊效果以下:
靠上對齊,在交叉軸開始的最上方,能夠看到子元素再也不佔滿容器寬度:
居中對齊:
靠下對齊:
基線對齊,若是子元素文字尺寸和行高不一樣,則子元素會按照文字的基線進行對齊:
.flex2 {
font-size: 24px;
}
複製代碼
若是是 flex-start
對齊方式:
本小節在下邊講到折行時再介紹
子元素能夠經過設置 align-self
來控制本身在交叉軸上的對齊方式,例如把 .flex3
子元素在垂直方向上靠下對齊:
.flex {
display: flex;
align-items: flex-start;
}
.flex3 {
align-self: flex-end;
}
複製代碼
在水平方向上控制子元素對齊並無justify-self
屬性,而是使用margin
屬性,經過把左或右邊距設置爲auto
來控制水平對齊,好比把 flex3
放到最右邊:
.flex3 {
margin-left: auto;
}
複製代碼
flex 支持按行排布,也支持按列排布。按列排布時,主軸和交叉軸換了方向,可是 align-items 和 justify-content 控制的軸線不變,即 align-items
仍是控制交叉軸,justify-content
控制主軸:
因此說,在水平方向上對齊變成了使用align-items
,垂直方向則用justify-content
。
要使 flex 按列排布,只須要設置:
flex-direction: column;
複製代碼
來看幾個例子:
水平居中對齊
.flex {
display: flex;
flex-direction: column;
align-items: center;
}
複製代碼
垂直居中對齊
.flex {
display: flex;
flex-direction: column;
justify-content: center;
}
複製代碼
另外 flex 佈局也能夠支持反向按行和列布局,至關於按容器中心線進行 180 度翻轉:
row-reverse
.flex {
display: flex;
flex-direction: row-reverse;
}
複製代碼
column-reverse
列模式下會垂直翻轉:
.flex {
display: flex;
flex-direction: column-reverse;
}
複製代碼
子元素能夠經過設置flex
屬性來調整空間的佔比,例如讓 flex2
在水平方向上佔據其餘子元素的 2 倍大小,能夠設置:
.flex1,
.flex3 {
flex: 1;
}
.flex2 {
flex: 2;
}
複製代碼
在介紹 flex-basis 以前,先講一個概念 main size
,即主軸方向的尺寸,那麼,在行排布模式下,也就是水平方向的尺寸,其實就是子元素的寬度,而在列模式下,它是子元素的高度,相對應的也有cross size
,即行模式下是子元素的高度,列模式下是寬度。 而flex-basis
是用來設置main size
的,它的優先級會高於width
。它的默認值是auto
,即在行模式下,若是子元素設置了寬度,它就取自這個寬度值,沒有設置的話,就是內容的寬度。使用 flex-basis
,能夠同時管理行模式下的寬度和列模式下的高度。
來看一個例子,把以前的子元素改爲固定寬度,好比 200px
:
.flex > * {
flex-basis: 200px;
}
複製代碼
這樣每一個子元素寬度變爲了 200px:
若是再添加 width
屬性,發現並不會生效:
.flex > * {
flex-basis: 200px;
width: 250px;
}
複製代碼
min-width
來強制設置最小寬度:
.flex > * {
flex-basis: 200px;
min-width: 250px;
}
複製代碼
同理的,在列模式下,flex-basis
變成了高度,由於容器高度爲 100px
,這裏把子元素高度設置成了 30px
總計 90px
來效果:
.flex {
flex-direction: column;
}
.flex > * {
flex-basis: 30px;
}
複製代碼
一樣的,也能夠用min-height
來控制最小高度。
(後續例子都假設是行模式)以前的小節簡單說了一下 flex 子元素空間的佔比,這裏把縮放單獨拿出來是爲了說明:除了調整 flex 子元素的增加以外,也能夠調整收縮,以及flex
屬性背後的原理(下一小節)。
先看一下增加,flex-grow
,這個屬性是說 flex 容器在有剩餘空間的時候,子元素佔據剩餘空間的佔比。例如,給.flex2
子元素設置:
.flex2 {
flex-grow: 1;
}
複製代碼
其它的元素保持默認的寬度(即內容的寬度,flex-basis 爲 auto),那麼 .flex2
就會自動增加並佔據整個剩餘空間:
若是把三個元素所有設置成 1,那麼全部元素都會自動增加,並各自佔據 1/3 的空間:
使用 flex-grow
就可以自由的調整元素的空間佔比了,很是適合一些浮動的佈局。
子元素的收縮是說:當它們的寬度超過 flex 容器以後,該如何進行收縮。經過 flex-shrink
來設置一個數值,數值越大,收縮程度也越大,好比flex-shrink: 2
的元素會比flex-shrink:1
收縮的值大 2 倍:
.flex1,
.flex3 {
flex-basis: 600px;
flex-shrink: 1;
}
.flex2 {
flex-basis: 600px;
flex-shrink: 2;
}
複製代碼
這裏爲了方便演示,我把全部的 flex 子元素的 main size (寬度) 都設置成了 600px。在個人顯示器下,flex 容器的寬度是 728px,三個子元素總和 1800px,顯然超出了容器的寬度,那麼根據上邊定義的收縮規則,.flex2
將收縮 2 倍於 .flex
和 .flex3
收縮的空間。下邊的例子中,.flex1
和 .flex3
的寬度變成了 332px
,相比於 600px
收縮了 268px
,那麼 .flex2
就要收縮 536px (268px * 2)
的寬度,那麼它最後就會剩下 64px (600px - 536px)
的寬度:
說完flex-grow
、flex-shrink
和 flex-basis
以後,再來看一下這個 flex
屬性,它實際上是前邊三個屬性的縮寫,默認值是 0 1 auto
,即不增加,但收縮,收縮比例爲 1,flex-basis 爲 auto,即取自用戶定義的寬度或內容的寬度。
flex 的值能夠是下邊幾種:
flex: 1
,就等同因而flex: 1 1 0
,即自動縮放,比例爲 1,flex-basis 爲 0。flex: 1 1 auto
。flex-grow
,第二個,若是是數字則認爲是 flex-shrink
,若是是寬度,則是flex-basis
。flex-grow
,flex-shrink
和 flex-basis
。因此說,經過flex
屬性能夠方便的同時設置flex-grow
、flex-shrink
和 flex-basis
這三個值。
若是子元素有固定寬度,而且超出了容器的寬度,還不容許收縮的話,那麼可使用flex-wrap
屬性來讓元素進行折行排列,使得每行的元素都不超過容器的寬度。這裏跟 css grid 佈局的主要區別是,它沒法控制單獨控制行、列的佔比,好比跨行、誇列,也不能自由定位元素到特定的位置。下邊的示例新增了 2 個元素,一共 5 個,每一個元素的 main size 爲 300px,而後超出寬度後折行:
.flex {
flex-wrap: wrap;
}
.flex > * {
flex-shrink: 0;
flex-basis: 300px;
}
複製代碼
若是 flex 容器開啓了折行,那麼兩行及以上的內容能夠經過align-content
屬性來控制各行之間在交叉軸上的排列規則,它的取值和 justify-content
基本相同,這裏演示其中幾個,仍是使用以前三個元素的 flex 容器,每一個容器寬度爲 300px,超出後換行:
.flex {
display: flex;
flex-wrap: wrap;
}
.flex > * {
flex-basis: 300px;
}
複製代碼
垂直居中:
兩端對齊:
若是 HTML 結構複雜,有嵌套的 flex 容器,頗有可能會遇到嵌套的 flex 容器並不能自動收縮的問題,即便設置了flex-shrink
。好比有下邊一個 html 結構:
<div class="flex">
<div class="flex1">Flex 1</div>
<div class="flex2">Flex 2</div>
<div class="flex3">Flex 3</div>
<div class="flex4">
<p>
這是一段很長很長很長很長很長很長很長很長很長很長很長很長長很長很長很長很長很長長很長很長很長很長很長的文本
</p>
</div>
</div>
複製代碼
這裏給以前的 flex 容器添加了一個新的子元素.flex4
,這 4 個子元素都設置成flex: 1
來平分空間,可是 .flex4
本身自己也是一個flex
佈局的容器,裏邊有一長串文本,我想讓它超長以後自動顯示省略號,它的 CSS 代碼:
.flex {
display: flex;
}
.flex > * {
flex: 1;
}
.flex4 {
display: flex;
flex: 1;
}
.flex4 > p {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
複製代碼
能夠看到,最後本應該佔 1/4 空間的.flex4
,由於文本不能換行,直接把 flex 容器撐開了,而且把其餘的三個子元素擠成了最小空間,它本應該把文字截短並顯示省略號,這是爲何呢?原來,flex 容器的 min-width
屬性值爲 auto,是由瀏覽器自行計算的,在這裏它取了<p>
元素的寬度,使得寬度成爲了一整行 <p>
的寬度。那麼要解決這個問題,能夠把.flex4
這個嵌套 flex 容器的 min-width
改成0
,即最小寬度是0
,那麼就能夠正常收縮了:
.flex4 {
display: flex;
flex: 1;
min-width: 0;
}
複製代碼
到這裏,整個 flex 佈局就介紹完了,仍是有很多東西的,但不難。相信經過實例你必定能夠掌握它的用法,下邊總結一下要點:
display: flex
屬性。justify-content
和align-items
控制對齊方式。flex-direction
,另外也支持row-reverse
和column-reverse
反向排列。flex
簡寫形式,或者flex-grow
,flex-shrink
,flex-basis
來調整元素的空間佔比和縮放。flex-wrap
能夠設置 flex 子元素折行顯示。flex
容器的縮放問題。你學會了嗎?若是有問題,請留下評論吧。