Flex佈局

上一期我整理介紹了grid佈局方式,若是想看的同窗,能夠直接點擊此文章:
Grid佈局css

這期我把flex佈局方式筆記也整理出來了,內容是我本身在根據別人視頻學習過程當中整理的資料。html

目前不少css的框架都使用Flexbox做爲基礎。瀏覽器大部分也都兼容。前端

接下來直接看代碼演示,咱們先準備一個素材,準備5個div元素,定義爲 ABCDE。由於div默認狀況下display是block塊級元素,因此默認狀況下會獨佔一行。因此咱們獲得以下圖的排版。這就是咱們準備的素材。segmentfault

<div class="box A">A</div>
<div class="box B">B</div>
<div class="box C">C</div>
<div class="box D">D</div>
<div class="box E">E</div>
html {
    font-size: 12px;
}

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
}

.A {
    background-color: #6dd98f;
}

.B {
    background-color: #0c7899;
}

.C {
    background-color: #961375;
}

.D {
    background-color: #bb7e38;
}

.E {
    background-color: #cfec9f;
}

image.png

Flex Container和Flex Items

Flex佈局方式主要就分爲2個角色,Flex Container和Flex Items,也就是父容器和子項目。咱們先來改寫素材。瀏覽器

<div class="flex-container">
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
</div>

將四個div元素外部包括一個flex-container父容器,而且設置flex-container的display爲flex。那麼咱們便獲得了以下圖的佈局。框架

.flex-container {
    display: flex;
      background-color: #2B34F5;
}

image.png

這裏父容器就是flex-container元素,而裏面五個div則即是flex items子項目。佈局

flex container中屬性

flex-direction

flex-direction這個屬性是定義父容器中子項目,即flex items的排序方向。學習

flex-direction的默認值通常爲 row,便是橫向排序。flex

若是你改爲:spa

flex-direction: column;

這時候即是縱向排序。

image.png

另外還有如下排序方式:

flex-direction: row-reverse;  //橫向倒轉排序。

以下圖:

image.png

flex-direction: column-reverse; //縱向倒轉排序。

以下圖:

image.png

這裏有一個比較重要的知識點:主軸(main-axis)和交叉軸(cross-axis)。當flex屬性不一樣時候,主軸和交叉軸不一樣。這個知識點須要和justify-content和align-items結合起來使用,下面咱們先來介紹justify-content和align-items這2個知識點。

flex-direction屬性 主軸(main-axis) 交叉軸(cross-axis)
row row column
column column row

justify-content和align-items

justify-content是設置主軸的排序方向的。而align-items則是設置交叉軸的排序方向的。

咱們仍是看代碼:

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: row;
    justify-content: center;
}

咱們把flex-direction設置爲row橫向排序,這時候設置justify-content,即主軸方向居中,此時的主軸即是row,那麼咱們能夠獲得以下圖的效果:

image.png

可是當咱們把代碼改成flex-direction: column時候,此時主軸便成了colunm,設置justify-content: center屬性則不會獲得水平方向的居中,以下圖。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: column;
    justify-content: center;
}

image.png

此時,若是咱們要獲得水平方向居中,則應該設置align-items:center,而不是justify-content: center。由於此時row水平方向是屬於交叉軸。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    height: 500px;
}

那咱們便把flex-container父容器高度設置大點,這時候主軸即是column,那麼justify-content: center熟悉會讓子元素垂直居中於父容器內,則align-items: center則會讓子元素水平居中於父容器內。

image.png

從這個舉例來看,是否是很好理解主軸和交叉軸概念。

另外,justify-content除了center外,還有其餘各類屬性

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: row;
      height: 500px;
      align-items: center;
}

咱們把父容器恢復爲flex-direction: row水平佈局。

justify-content: flex-start; //沿着主軸起始方向排版佈局

以下圖:

image.png

justify-content: flex-end;//沿着主軸結束方向排版佈局

以下圖:

image.png

這裏要記住一點:

設置flex-direction: row屬性時候,justify-content屬性設置爲flex-start或flex-end,子元素都是由左至右排序。設置flex-direction: colunm屬性時候,justify-content屬性設置爲flex-start或flex-end,子元素都是由上至下排序。即順序都是ABCDE,不會是EDCBA。

flex-wrap

flex-wrap便是會不會分行的意思。

<div class="flex-container">
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
</div>

咱們在父容器中加入多個子div,這時候咱們縮小瀏覽器的寬度。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    height: 500px;
}

image.png

這時候會發現,子div仍是會被壓縮在水平方向一行,每一個子div寬度會被擠壓。這是由於flex-wrap默認的屬性值是nowrap,即不換行的意思,因此無論怎麼添加子div,都只會在同一行。

若是咱們修改屬性flex-wrap: wrap:

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    height: 500px;
    flex-wrap: wrap;
}

image.png

這時候,超出寬度的子div便會被移到下一行中。這時候咱們再配合justify-content和align-items兩個屬性,就能獲得不同效果,好比下面排版:

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    height: 500px;
    flex-wrap: wrap;
}

image.png

flex-flow

flex-flow是flex-direction和flex-wrap的組合起來的縮寫。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap; 
    justify-content: center;
    align-items: center;
    height: 500px;
}

flex-flow: row wrap; 在這裏即是flex-direction:row,flex-wrap:wrap的縮寫。這個能夠根據我的習慣用此屬性或者分2個屬性編寫。

align-content

align-content這個屬性,是當flex-wrap設定爲wrap的時候,便是有二行以及二行以上時候纔會生效。直接看下圖:

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap;
    justify-content: center;
    align-items: center;
    height: 500px;
}

不設置align-content時候的以下圖:

image.png

align-content: center;

align-content: center時候以下圖:

image.png

align-content: space-between;

align-content: space-between時候以下圖:

image.png

align-content: flex-start;

align-content: flex-start時候以下圖:

image.png

由上面舉例可知道,align-content是設定二行以二行以上時候,行與行之間的對齊方式。

Flex Items中屬性

order

order屬性用於調整flex item的排序位置。咱們看如下參考案例:

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap;
    justify-content: center;
    align-items: center;
    height: 200px;
    width: 500px;
}
<div class="flex-container">
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
</div>

咱們仍是先設定父容器下5個子div,以flex佈局方式,自動換行。

.B {
    background-color: #0c7899;
    order: 1;
}

這時候咱們在B子DIV中加入屬性值order:1,那麼咱們會獲得以下佈局排版方式。

image.png

發現div B已經到了末尾,這是由於flex item的order默認值都是0,當B設定爲1時候,由於flex佈局容器會根據order數字以小到大排序,B便會移動至末尾排序。

.B {
    background-color: #0c7899;
    order: -1;
}

若是咱們把B DIV的order設置爲-1,則會排序到第一個。

image.png

order能夠隨意將個別flex item的位置進行改變。

align-self

align-self是用於覆蓋flex container(父容器)的align-item的設置的

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap;
    justify-content: center;
    align-items: center;
    height: 200px;
    width: 500px;

}

好比父容器中,咱們align-items的值設置了center居中。

.A {
    background-color: #6dd98f;
    align-self: flex-end;
}

如以上代碼,咱們修改DIV A的align-self屬性爲flex-end。那麼咱們會獲得以下圖排版:

image.png

flex-basis

flex-basis是設置flex-item的主軸方向的大小的。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap;
    justify-content: center;
    align-items: center;
    height: 200px;
    width: 500px;
}

好比父容器中,咱們設置主軸爲row,並能夠換行。

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
    flex-basis: 200px;
}

在父容器的子div中添加flex-basis: 200px屬性,此時此屬性即表明子div的寬度爲200px;以下圖:

image.png

而若是咱們將主軸改成column。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: column wrap;
    justify-content: center;
    align-items: center;
    height: 200px;
    width: 500px;
}

此時flex-basis表明的是子div的高度,以下圖:

image.png

要記住一點,在設置flex-basis後,原有的高度或者寬度都會失效,都會改成flex-basis的設定值去計算寬度或高度。若是flex-basis設置爲0,若是沒有overflow的設定,此時容器寬度或高度則取決於子div容器內內容的大小。以下圖:

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap;
    justify-content: center;
    align-items: center;
    height: 200px;
    width: 500px;
}
.box {
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
    flex-basis: 0;
}

image.png

若是子容器再添加overflow屬性,則以下面狀況:

.box {
    overflow: hidden;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
    flex-basis: 0;
}

image.png

overflow: hidden狀況下,不會顯示子div。

flex-grow

flex-grow是指當flex container的主軸方向有剩餘空間的時候,flex item(容器子元素)沿主軸方向擴大的設置。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row wrap;
    justify-content: flex-start;
    align-items: center;
    height: 200px;
    width: 500px;
}
.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
}
<div class="flex-container">
  <div class="box A">A</div>
  <div class="box B">B</div>
  <div class="box C">C</div>
  <div class="box D">D</div>
  <div class="box E">E</div>
</div>

image.png

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
    flex-grow: 1;
}

box屬性中,咱們加入了 flex-grow: 1,這時候原先的排版便會變成如下結果:

image.png

子容器直接平均撐滿整個父容器。這是由於五個div屬性都是flex-grow: 1,那五個div便都是獨佔一份,會各自佔剩餘空間200px中的一份,即40px。

若是咱們不給每一個子div設定flex-grow,只設定其中A DIV元素

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
}
.A {
    background-color: #6dd98f;
    flex-grow: 1;
}

.B {
    background-color: #0c7899;
}

.C {
    background-color: #961375;
}

.D {
    background-color: #bb7e38;
}

.E {
    background-color: #cfec9f;
}

image.png

那麼從上圖排版,咱們會發現A DIV會獨佔剩餘200px的全部空間。也就是A DIV寬度變成了60+200=260px;

而當主軸改成column時候,則是垂直方向A獨佔剩餘空間。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: column wrap;
    justify-content: flex-start;
    align-items: center;
    height: 500px;
    width: 500px;
}

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;

}

.A {
    background-color: #6dd98f;
    flex-grow: 1;
}

.B {
    background-color: #0c7899;
}

.C {
    background-color: #961375;
}

.D {
    background-color: #bb7e38;
}

.E {
    background-color: #cfec9f;
}

image.png

flex-shrink

flex-shrink則與flex-grow相反。是指當flex item子容器主軸方向的大小總和,超出父容器flex container的時候,flex item沿主軸方向如何縮小的設定。

.flex-container {
    display: flex;
    background-color: #2B34F5;
    flex-flow: row nowrap;
    justify-content: flex-start;
    align-items: center;
    height: 300px;
    width: 240px;
}

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
}

咱們將父容器寬度改成240px,主軸爲row方向,不換行。每一個div設定爲60px,那麼理論上5個div應該有300px總和。可是如今父容器只有240px,少了60px。

image.png

咱們發現五個div還在同一行,可是寬度被縮減了。這是由於flex-shrink默認值都是1。

.box {
    width: 60px;
    height: 60px;
    background-color: #eee;
    text-align: center;
    line-height: 60px;
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
    font-size: 2rem;
    flex-shrink: 0;
}

咱們如今每一個div設置flex-shrink: 0。這時候表明當主軸方向空間不足時候,不會去壓縮子容器的寬度。那麼咱們能夠獲得下圖排版:

image.png

.A {
    background-color: #6dd98f;
    flex-shrink: 1;
}

.B {
    background-color: #0c7899;
    flex-shrink: 1;
}

.C {
    background-color: #961375;
    flex-shrink: 1;
}

.D {
    background-color: #bb7e38;
    flex-shrink: 1;
}

.E {
    background-color: #cfec9f;
}

咱們在子DIV A、B、C、D中都加入屬性值flex-shrink: 1,這表明ABCD四個DIV都各自分擔一份被縮小的空間,也就是60/4=15px,那麼ABCD四個div都會縮小爲60-15=45px的寬度,而E由於flex-shrink:0,因此仍然會是60px的寬度。以下圖排版:
image.png

flex

flex的屬性是flex-grow,flex-shrink和flex-basis組合起來的縮寫。相似於父容器屬性flex-flow,根據每一個人寫法習慣不一樣,能夠拆分紅三個屬性分別寫,也能夠組合編寫。這裏很少作介紹。

前端學習過程要感謝B站的CodingStartup的Steven,不過他的講解基本是粵語和視頻,不少筆記我只能在看的過程本身整理,雖然直接我也從事程序開發,可是不少時候只知道要這麼作,殊不知道爲何要這麼作,因此工做幾年後從新回頭鞏固知識,以上是我在學習過程當中本身整理的學習筆記,但願能夠幫到你們。

相關文章
相關標籤/搜索