深度解析 CSS Flexbox 佈局 - 2020年最新版

在 CSS flexbox 佈局出現之前,若是要控制 HTML 元素的佈局,要用到不少種奇葩的方式。在水平方向上得用float控制左右對齊,稍一不注意,就會有浮動的元素飛來飛去~。在垂直方向上就更是百家爭鳴了:要麼手動計算高度而後算出中心點,要麼用 line-heightheight 的結合,要麼用十之八九不生效的 vertical-align 屬性等等等等。自從 flex-box 出現之後,一切彷佛就豁然開朗了,水平垂直各類花式對齊,空間分配由你作主。固然,要用好它,用對它也不是一件容易的事,今天就給你說說 flex-box 佈局,看完以後你也能熟練的運用它!css

2 分鐘視頻入門版:2 分鐘掌握 CSS Grid 佈局html

真實 HTML 代碼(非圖片)示例版:請點此訪問(示例都是真實的 HTML 代碼,可使用 chrome 開發者工具查看屬性。chrome

開啓 Flexbox 佈局

假設有下邊這麼一個 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

控制主軸(即水平方向)對齊方式使用justify-content屬性,它有下邊幾種對齊方式:flexbox

flex-start

flex-start 是默認值,若是是從左到右的文字閱讀習慣(LTR),就是靠左對齊。由於默認的對齊方式,因此跟上邊的例子沒有什麼區別:spa

justify-content: flex-start;
複製代碼

center

居中對齊,此時整個 flex 容器被居中到了頁面中間:

flex-end

靠右對齊:

space-between

兩端對齊,這種對齊方式是第一個和最後一個元素貼邊,中間的元素平分剩餘的空間:

space-evenly

分散對齊,全部的元素都平分空間:

space-around

space-evenly相似,可是左右兩邊的留白爲平分空間的 1/2.

align-items

控制交叉軸方向(即垂直方向)上的對齊方式使用align-items屬性,有下邊幾種對齊方式:

stretch

stretchalign-items 的默認值,它會自動把子元素拉伸成容器的高度,因此以前的例子裏子元素在垂直方向上都佔滿了容器,只要改變容器的align-items的值,它就會變成內容的高度。stretch 對齊效果以下:

flex-start

靠上對齊,在交叉軸開始的最上方,能夠看到子元素再也不佔滿容器寬度:

center

居中對齊:

flex-end

靠下對齊:

baseline

基線對齊,若是子元素文字尺寸和行高不一樣,則子元素會按照文字的基線進行對齊:

.flex2 {
  font-size: 24px;
}
複製代碼

若是是 flex-start 對齊方式:

align-content

本小節在下邊講到折行時再介紹

子元素覆蓋對齊方式

子元素能夠經過設置 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

在介紹 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-grow,這個屬性是說 flex 容器在有剩餘空間的時候,子元素佔據剩餘空間的佔比。例如,給.flex2子元素設置:

.flex2 {
  flex-grow: 1;
}
複製代碼

其它的元素保持默認的寬度(即內容的寬度,flex-basis 爲 auto),那麼 .flex2 就會自動增加並佔據整個剩餘空間:

若是把三個元素所有設置成 1,那麼全部元素都會自動增加,並各自佔據 1/3 的空間:

使用 flex-grow 就可以自由的調整元素的空間佔比了,很是適合一些浮動的佈局。

flex-shrink

子元素的收縮是說:當它們的寬度超過 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 屬性

說完flex-growflex-shrinkflex-basis 以後,再來看一下這個 flex 屬性,它實際上是前邊三個屬性的縮寫,默認值是 0 1 auto,即不增加,但收縮,收縮比例爲 1,flex-basis 爲 auto,即取自用戶定義的寬度或內容的寬度。

flex 的值能夠是下邊幾種:

  • 指定一個數字 - 例如flex: 1,就等同因而flex: 1 1 0,即自動縮放,比例爲 1,flex-basis 爲 0。
  • auto - 等同於flex: 1 1 auto
  • 指定兩個數字 - 第一個爲flex-grow,第二個,若是是數字則認爲是 flex-shrink,若是是寬度,則是flex-basis
  • 指定三個值 - 分別爲flex-growflex-shrinkflex-basis

因此說,經過flex屬性能夠方便的同時設置flex-growflex-shrinkflex-basis 這三個值。

折行

若是子元素有固定寬度,而且超出了容器的寬度,還不容許收縮的話,那麼可使用flex-wrap屬性來讓元素進行折行排列,使得每行的元素都不超過容器的寬度。這裏跟 css grid 佈局的主要區別是,它沒法控制單獨控制行、列的佔比,好比跨行、誇列,也不能自由定位元素到特定的位置。下邊的示例新增了 2 個元素,一共 5 個,每一個元素的 main size 爲 300px,而後超出寬度後折行:

.flex {
  flex-wrap: wrap;
}

.flex > * {
  flex-shrink: 0;
  flex-basis: 300px;
}
複製代碼

align-content

若是 flex 容器開啓了折行,那麼兩行及以上的內容能夠經過align-content屬性來控制各行之間在交叉軸上的排列規則,它的取值和 justify-content基本相同,這裏演示其中幾個,仍是使用以前三個元素的 flex 容器,每一個容器寬度爲 300px,超出後換行:

.flex {
  display: flex;
  flex-wrap: wrap;
}
.flex > * {
  flex-basis: 300px;
}
複製代碼

center

垂直居中:

space-between

兩端對齊:

嵌套的 flex 容器的問題

若是 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 佈局就介紹完了,仍是有很多東西的,但不難。相信經過實例你必定能夠掌握它的用法,下邊總結一下要點:

  • 開啓 flex 佈局使用display: flex屬性。
  • flex 佈局有主軸和交叉軸,分別使用justify-contentalign-items控制對齊方式。
  • 支持按行或列進行排列,使用flex-direction,另外也支持row-reversecolumn-reverse反向排列。
  • 子元素能夠經過flex簡寫形式,或者flex-growflex-shrinkflex-basis 來調整元素的空間佔比和縮放。
  • 經過flex-wrap能夠設置 flex 子元素折行顯示。
  • 嵌套flex容器的縮放問題。

你學會了嗎?若是有問題,請留下評論吧。

相關文章
相關標籤/搜索