天天看點

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

本教程案例線上示範

有路網PC端

有路網移動端

免費配套視訊教程

教程配套源碼資源

Flex容器

<ul> <!--parent element-->
  <li></li> <!--first child element-->
  <li></li> <!--second child element-->
  <li></li> <!--third child element-->
</ul>
           

這就是一個無序清單(

ul

)裡有三個清單元素(

li

)。

你可以把

ul

稱為父元素,

li

稱為子元素。

要開始使用Flexbox,必須先讓父元素變成一個Flex容器。

你可以在父元素中顯式的設定

display:flex

或者

display:inline-flex

。這樣你就可以開始使用Flexbox子產品。

實際是顯式聲明了Flex容器之後,一個Flexbox格式化上下文(Flexbox formatting context)就立即啟動了。

使用一個無序清單(

ul

)和一群清單元素(

li

),啟動Flexbox格式化上下文的方式如下:

/* 聲明父元素為flex容器 */
ul {
    display:flex; /*或者 inline-flex*/
}

           

給清單元素(

li

)添加一點基本樣式。

li {
    width: 100px;
    height: 100px;
    background-color: #8cacea;
    margin: 8px;
    list-style: none;
}

           

你将看到的效果如下圖所示:

預設情況下,

li

是塊級元素,在CSS中垂直排布的,也就是說從上到下排列顯示,就像下圖這樣:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

然而,簡單的寫一行代碼

display:flex

,你立即就可以看到布局改變了。

現在清單元素(

li

)水準排列,從左到右。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

Flexbox子產品的開始,正如前面的介紹,在任何父元素上使用

display:flex

一旦你顯式的設定了

display

屬性的值為

flex

,無序清單

ul

就會自動變成Flex容器,而其子元素(在本例中是指清單元素

li

)就變成了Flex項目。

使用了兩個關鍵詞,我們把重點放到他們身上。了解他們對于了解後面的知識至關重要。

  • Flex容器(Flex Container):父元素顯式設定了

    display:flex

  • Flex項目(Flex Items):Flex容器内的子元素

這些隻是Flexbox子產品的基礎。

Flex容器屬性

flex-direction || flex-wrap || flex-flow || justify-content || align-items || align-content

           

通過上面的内容,我們了解了一些基礎知識。知道了Flex容器和Flex項目是什麼,以及如何啟動Flexbox子產品。

有設定一個父元素作為一個Flex容器,幾個對齊屬性可以使用在Flex容器上。

正如你的塊元素的

width

設定了

200px

,有六種不同的屬性可以用于Flex容器。

flex-direction

flex-direction

屬性控制Flex項目沿着主軸(Main Axis)的排列方向。

它具有四個值:

/* ul 是一個flex容器 */
ul {
    flex-direction: row || column || row-reverse || column-reverse;
}

           

簡單點來說,就是

flex-direction

屬性讓你決定Flex項目如何排列。它可以是行(水準)、列(垂直)或者行和列的反向。

從技術上講,水準和垂直在Flex世界中不是什麼方向(概念)。它們常常被稱為主軸(Main-Axis)和側軸(Cross-Axis)。預設設定如下所示。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

通俗的說,感覺Main-Axis就是水準方向,從左到右,這也是預設方向。Cross-Axis是垂直方向,從上往下。

flex-direction

屬性的值是

row

。它讓Flex項目沿着Main-Axis排列(從左向右,水準排列)。這就解釋了本文開始部分時無序清單的表現效果。

盡管

flex-direction

屬性并沒有顯式的設定,但它的預設值是

row

。Flex項目将沿着Main-Axis從左向右水準排列。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

如果把

flex-direction

的屬性值修改成

column

,這時Flex項目将沿着Cross-Axis從上到下垂直排列。不再是從左向右排列。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

flex-wrap

flex-wrap

屬性有三個屬性值:

ul {
    flex-wrap: wrap || nowrap || wrap-reverse;
}

           

我将通過一個例子來解釋如何使用

flex-wrap

屬性。首先在前面的無序清單的HTML結構中多添加幾個清單項

li

<ul> <!--parent element-->
    <li></li> <!--first child element-->
    <li></li> <!--second child element-->
    <li></li> <!--third child element-->
    <li></li>
    <li></li>
    <li></li>
</ul>
           

幸運的是,新添加的Flex項目剛好适合Flex容器大小。也就是Flex項目能剛好填充Flex容器。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

再深入一點。

繼續給Flex容器内添加Flex項目,比如說添加到

10

個Flex項目。這個時候會發生什麼?

<ul> <!--parent element-->
    <li></li> <!--first child element-->
    <li></li> <!--second child element-->
    <li></li> <!--third child element-->
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>
           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

同樣的,Flex容器還是能容納所有的子元素(Flex項目)排列,這是每一個Flex容器的預設行為。Flex容器會在一行内容納所有的Flex項目。這是因為

flex-wrap

屬性的預設值是

nowrap

。也就是說,Flex項目在Flex容器内不換行排列。

ul {
    flex-wrap: nowrap; /*Flex容器内的Flex項目不換行排列*/
}

           

no-wrap

不是不可改變的。我們可以改變。

當你希望Flex容器内的Flex項目達到一定數量時,能換行排列。當Flex容器中沒有足夠的空間放置Flex項目(Flex項目預設寬度),那麼Flex項目将會換行排列。把它(

flex-wrap

)的值設定為

wrap

就有這種可能:

ul {
    flex-wrap: wrap;
}

           

現在Flex項目在Flex容器中就會多行排列。

在這種情況下,當一行再不能包含所有清單項的預設寬度,他們就會多行排列。即使調整浏覽器大小。

就是這樣子。注意:Flex項目現在顯示的寬度是他們的預設寬度。也沒有必要強迫一行有多少個Flex項目。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

除此之外,還有一個值:

wrap-reverse

是的,你猜對了。它讓Flex項目在容器中多行排列,隻是方向是反的。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

flex-flow

flex-flow

flex-direction

flex-wrap

兩個屬性的速記屬性。

你還記得使用

border

的速記寫法?

border: 1px solid red

。這裡的概念是相同的,多個值寫在同一行,比如下面的示例:

ul {
    flex-flow: row wrap;
}

           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

相當于:

ul {
    flex-direction: row;
    flex-wrap: wrap;
}

           

除了這個組合之外,你還可以嘗試一些其它的組合。

flex-flow: row nowrap

flex-flow: column wrap

flex-flow: column nowrap

justify-content

Flexbox子產品真得很好。如果你仍然不相信它的魅力,那麼

justify-content

屬性可能會說服你。

justify-content

屬性可以接受下面五個值之一:

ul {
    justify-content: flex-start || flex-end || center || space-between || space-around
}

           

justify-content

屬性又能給我們帶來什麼呢?提醒你一下,你是否還記得

text-align

屬性。其實

justify-content

屬性主要定義了Flex項目在Main-Axis上的對齊方式。

來看一個簡單的例子,還是考慮下面這個簡單的無序清單:

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>

           

添加一些基本樣式:

ul {
    display:flex;
    border: 1px solid red;
    padding: 0;
    list-style: none;
    background-color: #e8e8e9;
}
li {
    background-color: #8cacea;
    width: 100px;
    height: 100px;
    margin: 8px;
    padding: 4px;
}

           

你将看到的效果是這樣:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

通過

justify-content

屬性,可以讓Flex項目在整個Main-Axis上按照我自己的欲望設定其對齊方式。

可能會有以下幾種類型。

flex-start

justify-content

的預設屬性值是

flex-start

flex-start

讓所有Flex項目靠Main-Axis開始邊緣(左對齊)。

ul {
    justify-content: flex-start;
}

           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

flex-end

flex-end

讓所有Flex項目靠Main-Axis結束邊緣(右對齊)。

ul {
    justify-content: flex-end;
}

           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

center

和你預期的一樣,

center

讓所有Flex項目排在Main-Axis中間(居中對齊)。

ul {
    justify-content: center;
}

           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

space-between

space-between

讓除了第一個和最一個Flex項目的兩者間間距相同(兩端對齊)。

ul {
    justify-content: space-between;
}

           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

你注意到有什麼不同?看看下圖的描述:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

space-around

最後,

space-around

讓每個Flex項目具有相同的空間。

ul {
    justify-content: space-around;
}

           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

space-between

有點不同,第一個Flex項目和最後一個Flex項目距Main-Axis開始邊緣和結束邊緣的的間距是其他相鄰Flex項目間距的一半。看看下圖的描述:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

align-items

align-items

屬性類似于

justify-content

屬性。隻有了解了

justify-content

屬性,才能更好的了解這個屬性。

align-items

屬性可以接受這些屬性值:

flex-start || flex-end || center || stretch || baseline

ul {
    align-items: flex-start || flex-end || center || stretch || baseline
}

           

它主要用來控制Flex項目在Cross-Axis對齊方式。這也是

align-items

justify-content

兩個屬性之間的不同之處。

下面是不同的值對Flex項目産生的影響。不要忘記這些屬性隻對Cross-Axis軸有影響。

首先,讓我們設定ul的高度高于li的高度

ul {
      height: 200px;
    }
           

stretch

align-items

的預設值是

stretch

。讓所有的Flex項目高度和Flex容器高度一樣。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

正如你所希望的

flex-start

讓所有Flex項目靠Cross-Axis開始邊緣(頂部對齊)。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

flex-end

讓所有Flex項目靠Cross-Axis結束邊緣(底部對齊)。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

center

讓Flex項目在Cross-Axis中間(居中對齊)。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

baseline

讓所有Flex項目在Cross-Axis上沿着他們自己的基線對齊。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    ul {
      border: 1px solid red;
      display: flex;
      height: 200px;
      align-items: baseline;
    }
    li {
    width: 100px;
    background-color: #8cacea;
    margin: 8px;
    list-style: none;
    font-size: 28px;
  }
  li:nth-child(2){
    font-size: 12px;
  }
  </style>
</head>
<body>
  <ul> <!--parent element-->
    <li>1</li> <!--first child element-->
    <li>2</li> <!--second child element-->
    <li>333 33333 33 </li> <!--third child element-->
  </ul>
</body>
</html>
           

結果看上去有點像

flex-start

,但略有不同。那“baseline”到底是什麼呢?下圖應該能幫助你更好的了解。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

align-content

還記得前面讨論的

wrap

屬性嗎?我們在Flex容器中添加了更多的Flex項目。讓Flex容器中的Flex項目多行排列。

align-content

屬性用于多行的Flex容器。它也是用來控制Flex項目在Flex容器裡的排列方式,排列效果和

align-items

值一樣,但除了

baseline

屬性值。

align-items

屬性一樣,它的預設值是

stretch

。你現在應該熟悉這些值。那它又是如何影響Flex容器裡的10個Flex項目多行排列方式。

使用

stretch

會拉伸Flex項目,讓他們沿着Cross-Axis适應Flex容器可用的空間。

你看到的Flex項目間的間距,是Flex項目自身設定的

margin

值。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    ul {
      border: 1px solid red;
      display: flex;
      height: 400px;
      flex-wrap: wrap;
      align-content:center;
    }
    li {
    width: 100px;
    background-color: #8cacea;
    margin: 8px;
    list-style: none;
    font-size: 28px;
  }
  li:nth-child(2){
    font-size: 12px;
  }
  </style>
</head>
<body>
  <ul> <!--parent element-->
    <li>1</li> <!--first child element-->
    <li>2</li> <!--second child element-->
    <li>333 33333</li> <!--third child element-->
    <li>1</li> <!--first child element-->
    <li>2</li> <!--second child element-->
    <li>333 33333 33 </li> <!--third child element-->
    <li>1</li> <!--first child element-->
    <li>2</li> <!--second child element-->
    <li>333 33333 33 </li> <!--third child element-->
  </ul>
</body>
</html>
           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

之前你看到過

flex-start

。這次是讓多行Flex項目靠Cross-Axis開始邊緣。沿着Cross-Axis從上到下排列。是以Flex項目在Flex容器中頂部對齊。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

flex-end

剛好和

flex-start

相反,讓多行Flex項目靠着Cross-Axis結束位置。讓Flex項目沿着Cross-Axis從下到上排列,即底部對齊。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

你猜到了,

center

讓多行Flex項目在Cross-Axis中間。在Flex容器中居中對齊。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

這是Flex容器的最後一個屬性。你現在知道如何使用各種Flex容器屬性。你可以在工作中實踐這些屬性。

Flex項目屬性

flex-grow || flex-shrink || flex-basis
           

現在我們把注意力從Flex容器轉移到Flex項目及其對齊屬性。

像Flex容器,對齊屬性也可以用在所有的Flex項目。

flex-grow 和 flex-shrink

flex-grow

flex-shrink

屬性控制Flex項目在容器有多餘的空間如何放大(擴充),在沒有額外空間又如何縮小。

他們可能接受

或者大于

的任何正數。

0 || positive number

接下來闡述它們的使用。使用一個簡單的無序清單做為例子,它隻包含一個清單項。

ul {
    display:flex;
    border: 1px solid red;
    padding: 0;
    list-style: none;

}
li {
    background-color: #8cacea;
    height: 100px;
    margin: 8px;
    padding: 10px;
}
<ul>
    <li>I am a simple list</li>
</ul>
           

添加更多的樣式,看起來像這樣:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

flex-grow

屬性值設定為

。表示Flex項目不會增長,填充Flex容器可用空間。取值為

就是一個開和關的按鈕。表示

flex-grow

開關是關閉的。

flex-grow

的值設定為

1

,會發生:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

現在Flex項目擴充了,占據了Flex容器所有可用空間。也就是說開關打開了。如果你試着調整你浏覽器的大小,Flex項目也會縮小,以适應新的螢幕寬度。

為什麼?預設情況下,

flex-shrink

的值是

1

,也就是說

flex-shrink

開關也是打開的。

可以仔細看看

flex-grow

flex-shrink

屬性在各種情況下的效果,這樣能更好的幫助你了解。

flex-basis

flex-basis

屬性可以指定Flex項目的初始大小。也就是

flex-grow

flex-shrink

屬性調整它的大小以适應Flex容器之前。

flex-basis

預設的值是

auto

flex-basis

可以取任何用于

width

屬性的任何值。比如 

% || em || rem || px

等。

注意:如果

flex-basis

時,也需要使用機關。即

flex-basis: 0px

不能寫成

flex-basis:0

這裡同樣使用隻有一個清單項的清單做為示例。

/* 聲明父元素為flex容器 */
    ul {
    display:flex;
    border: 1px solid red;
    padding: 0;
    list-style: none;

}
li {
    background-color: #8cacea;
    height: 100px;
    margin: 8px;
    padding: 10px;
}
<ul>
    <li>I am a simple list</li>
</ul>

           

預設情況,Flex項目的初始寬度由

flex-basis

的預設值決定,即:

flex-basis: auto

。Flex項目寬度的計算是基于内容的多少來自動計算(很明顯,加上了

padding

值)。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

這意味着,如果你增加Flex項目中的内容,它可以自動調整大小。

<ul>
    <li>I am a simple list AND I am a simple list</li>
</ul>

           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

然而,如果你想将Flex項目設定一個固定的寬度,你也可以這樣做:

li {
    flex-basis: 150px;
}

           

現在Flex項目的寬度受到了限制,它的寬度是

150px

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

flex速記

flex

flex-grow

flex-shrink

flex-basis

三個屬性的速記(簡寫)。

在适當的時候,我建議你使用

flex

,這樣比使用三個屬性友善。

li {
    flex: 0 1 auto;
}

           

上面的代碼相當于:

li {
    flex-grow: 0;
    flex-shrink: 1;
    flex-basis: auto;
}

           

注意它們之間的順序。

flex-grow

第一,然後是

flex-shrink

,最後是

flex-basis

。縮寫成GSB,可以幫助你更好的記憶。

如果

flex

屬性值中少一個值,會發生什麼呢?

如果你隻設定了

flex-grow

flex-shrink

值,

flex-basis

可能是預設值

。這就是所謂的絕對flex項目。隻有當你設定了

flex-basis

,你會得到一個相對flex項目。

/* 這是一個絕對的Flex項目 */
li {
    flex: 1 1; /*flex-basis 預設值為 0*/
}
/* 這是一個相對的Flex項目 */
li {
  flex-basis: 200px; /* 隻設定了flex-basis的值 */
}

           

你肯定想知道相對和絕對的Flex項目是什麼?将在後面回答這個問題。

讓我們看看一些非常有用的

flex

flex: 0 1 auto

li {
    flex: 0 1 auto;
}

           

這相當于寫了

flex

預設屬性值以及所有的Flex項目都是預設行為。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

很容易了解這一點,首先看看

flex-basis

屬性。

flex-basis

設定為

auto

,這意味着Flex項目的初始寬度計算是基于内容的大小。

把注意力放到下一個屬性,

flex-grow

。這意味着

flex-grow

不會改變Flex項目的初始寬度。也就是說,

flex-grow

的開關是關閉的。

flex-grow

控制Flex項目的增長,如果其值設定為

,Flex項目不會放大以适應螢幕(Flex容器大小)。

flex-shrink

1

。也就是說,Flex項目在必要時會縮小。

應用到Flex項目效果就是這樣子:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

注意:Flex項目沒有增長(寬度)。如果有必要,如果調整浏覽器(調小浏覽器寬度),Flex項目會自動計算寬度。

flex: 0 0 auto

li {
    flex: 0 0 auto;
}

           

這個相當于

flex: none

還是老規矩:寬度是被自動計算,不過彈性項目不會伸展或者收縮(因為二者都被設定為零)。伸展和收縮開關都被關掉了。

它基本上是一個固定寬度的元素,其初始寬度是基于彈性項目中内容大小。

看看這個 flex 簡寫是如何影響兩個彈性項目的。一個彈性項目會比另一個容納更多内容。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

應該注意到的第一件事情是,這兩個彈性項目的寬度是不同的。因為寬度是基于内容寬度而自動計算的,是以這是預料得到的。

試着縮放一下浏覽器,你會注意到彈性項目不會收縮其寬度。它們從父元素中突出來了,要看到所有内容,必須橫向滾動浏覽器。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

在縮放浏覽器時,彈性項目不會收縮,而是從彈性容器中突出來了。

flex: 1 1 auto

這與 

flex: auto

 項目相同。

還是按我前面立的規矩。即,自動計算初始化寬度,但是如果有必要,會伸展或者收縮以适應整個可用寬度。

伸展和收縮開關打開了,寬度自動被計算。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

此時,項目會填滿可用空間,在縮放浏覽器時也會随之收縮。剩餘寬度被2個item平均配置設定,一人一半。

flex: "positive number"

一般應用于有多個彈性項目的情形。

這裡正數可以代表任何正數(沒有引号)。這與 

flex: “正數” 1 0

 相同。

flex: 2 1 0

 與寫為 

flex: 2

 是一樣的,

2

 表示任何正數。

li {
    flex: 2 1 0; / *與 flex: 2相同 */
}

           

與前面我立的規矩一樣,即,将彈性項目的初始寬度設定為零(嗯?沒有寬度?),伸展項目以填滿可用空間,并且最後隻要有可能就收縮項目。

彈性項目沒有寬度,那麼寬度該如何計算呢?

這個時候 

flex-grow

 值就起作用了,它決定彈性項目變寬的程度。由它來負責沒有寬度的問題。

當有多個彈性項目,并且其初始寬度 

flex-basis

 被設定為基于零的任何值時,比如 

0px

,使用這種 

flex

 簡寫更實用。

實際發生的是,彈性項目的寬度被根據 

flex-grow

 值的比例來計算。

考慮如下兩個清單項标記及 CSS:

<ul>
    <li>I am One</li>
    <li>I am Two</li>
</ul>

  <style>
    /* 聲明父元素為flex容器 */
    ul {
    display:flex;
    border: 1px solid red;
    padding: 0;
    list-style: none;

}
li {
    background-color: #8cacea;
    height: 100px;
    margin: 8px;
    padding: 10px;
    /* flex-basis: 150px; */
}
/* 第一個彈性項目 */
li:nth-child(1) {
    flex: 2 1 0; /* 與寫成 flex: 2 相同*/
}

/* 第二個彈性項目 */
li:nth-child(2){
    flex: 1 1 0;
    background-color: #8cacea;
}
  </style>

           

記住設定 

flex-grow : 1

,會讓彈性項目填滿可用空間。伸展開關打開了。

這裡有兩個彈性項目。一個的 

flex-grow

 屬性值是 

1

,另一個是 

2

,那麼會出現啥情況呢?

兩個項目上的伸展開關都打開了。不過,伸展度是不同的,

1

 和 

2

二者都會填滿可用空間,不過是按比例的。

它是這樣工作的:前一個占 

1/3

 的可用空間,後一個占 

2/3

 的可用空間。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

即使兩個彈性項目内容一樣大(近似),它們所占空間還是不同。寬度不是基于内容的大小,而是伸展值。一個是另一個的約兩倍。

絕對和相對Flex項目

前面了解了一些基本概念,但重要的是要澄清一些重要的概念。那絕對和相對Flex項目之間到底有啥差別呢?二者之間主要的差別在于間距及如何計算間距。

一個相對Flex項目内的間距是根據它的内容大小來計算的。而在絕對Flex項目中,隻根據 

flex

 屬性來計算,而不是内容。

考慮如下的标記:

<ul>
    <li>
        This is just some random text  to buttress the point being explained.
    Some more random text to buttress the point being explained.
    </li>

    <li>This is just a shorter random text.</li>
</ul>

           

兩個清單項元素,一個比另一個的文本多得多。

加點樣式:

ul {
    display: flex; /*觸發彈性盒*/
}

li {
    flex: auto; /*記住這與 flex: 1 1 auto; 相同*/
    border: 2px solid red;
    margin: 2em;
}

           

如下是結果:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

如果你已經忘了的話,

flex: 1 1 auto

 是與 

flex-grow: 1

flex-shrink: 1

flex-basis: auto

 相同的。

Flex項目的初始寬度是被自動計算的(

flex-basis: auto

),然後會伸展以适應可用空間(

flex-grow: 1

)。

當Flex項目因為被設定為 

flex-basis: auto

,而導緻寬度被自動計算時,是基于Flex項目内包含的内容的大小而計算。

上面示例中Flex項目的内容大小不相同。是以,Flex項目的大小就會不相等。

既然各個寬度開始就不是相等的(它是基于内容的),那麼當項目伸展時,寬度也保持不相等。

可以試試讓兩個li的内容相同再試試。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

上面示例中的Flex項目是相對Flex項目。

下面我們把Flex項目變成絕對的, 就是說這次它們的寬度是基于 

flex

 屬性,而不是内容的大小。一行代碼就可以出奇迹。

li {
    flex: 1 ; /*與 flex: 1 1 0 相同*/
}

           

效果如下:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

這次看到兩個Flex項目的寬度相同了嗎?

Flex項目的初始寬度是零(

flex-basis: 0

),并且它們會伸展以适應可用空間。當有兩到多個Flex項目的 

flex-basis

 取值為

時,它們會基于 

flex-grow

值共享可用空間。

現在寬度不會基于内容大小而計算,而是基于指定的 

flex

 屬性值來計算。

絕對Flex項目的寬度隻基于 

flex

 屬性,而相對Flex項目的寬度基于初始内容大小。

Auto-margin 對齊

當心Flex項目上的 

margin: auto

 對齊。當在Flex項目上使用 

margin: auto

 時,事情看起來就很怪異了。

你需要了解會發生什麼。它會導緻不可預料的結果,不過我打算解釋解釋。

當在Flex項目上使用 

margin: auto

 時,值為 

auto

 的方向(左、右或者二者都是)會占據所有剩餘空間。

這玩意有點難了解。下面我來說明一下。

考慮如下的導航欄标記以及 CSS 樣式:

<ul>
    <li>Branding</li>
    <li>Home</li>
    <li>Services</li>
    <li>About</li>
    <li>Contact</li>
</ul>

  <style>
    /* 聲明父元素為flex容器 */
    ul {
    display:flex;
    border: 1px solid red;
    padding: 0;
    list-style: none;

}
li {
    background-color: #8cacea;
    margin: 8px;
    padding: 10px;
    flex: 0 0 auto;
    border: 2px solid red;
}

  </style>

           

你可以看到如下的效果:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

這裡有幾件事情要注意:

  • flex-grow

     值為設定為 。這就解釋了為什麼清單項不會伸展。
  • Flex項目向Main-Axis的開頭對齊(這是預設行為)。
  • 由于項目被對齊到Main-Axis開頭,右邊就有一些多餘的空間。看到了吧?
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

現在在第一個清單項(branding)上使用 

margin: auto

,看看會出啥情況。

li:nth-child(1) {
    margin-right: auto; /*隻應用到右外邊距*/
}

           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

剛剛發生了什麼?之前的剩餘空間現在已經被配置設定到第一個Flex項目的右邊了。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

還記得我前面說的話吧?當在Flex項目上使用 

margin: auto

auto

如果想讓一個Flex項目的兩邊都用自動外邊距對齊,該怎麼辦呢?

/* 如果願意的話,也可以用 margin 簡寫來設定兩個邊 */
li:nth-child(1) {
    margin-left: auto;
    margin-right: auto
}

           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

現在空白被配置設定到Flex項目的兩邊了。

那麼,這是不是對很酷的自動外邊距對齊的一種折衷方案呢?看起來是。如果沒注意的話,它也可能是受挫之源。當在一個Flex項目上使用自動外邊距(

margin: auto

)時,

justify-content

 屬性就不起作用了。

例如,在上面的Flex容器上通過 

justify-content

 屬性,設定不同的對齊選項時,對布局沒有影響。

ul {
    justify-content: flex-end;
}

           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

Flexbox實戰

導航系統是每個網站或者應用程式的重要組成部分。這個世界上的每個網站都會有某種導航系統。

下面我們看看這些熱門網站,以及它們是如何實作其導航系統的。你看到Flexbox是如何幫助你更高效地建立這些布局嗎?

也仔細看看哪裡會用得上自動外邊距特性。

Bootstrap導航

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

AirBnB PC端導航

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

Twitter PC端導航

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

建議你自己寫代碼。試着自己實作這些導航系統。

切換flex-direction會發生什麼?

還記得我說過預設的Main-Axis方向是從左到右,Cross-Axis方向是從上到下吧?

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

好吧,現在你也可以改變這個方向。

正如在較早的小節中所描述的那樣,用 

flex-direction: column

 時,确實是這樣。

當用 

flex-direction: column

 時,Main-Axis和Cross-Axis會向如下所看到的那樣改變:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

如果曾用英語寫過文字,那麼你就知道英語是從左到右,從上到下來寫的。

Flexbox的預設Main-Axis和Cross-Axis也是采用同樣的方向。

不過,如果将 

flex-direction

 切換為 

column

,它就不再遵循英語的範式,而是日語的範式!

是的,日語。

如果你用日語寫過文字,那麼應該很熟悉了。(鄭重聲明,我從沒用過日語寫過文字)。

日文通常是從上到下寫的!沒那麼怪,對吧?

這就解釋了為嘛這對英語寫作者可能有點惱火。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

看看下面這個例子。标準無序清單(

ul

),帶有 

3

 個清單項(

li

)。不過這次我要改變一下

flex-direction

<ul>
    <li></li>
    <li></li>
    <li></li>
</ul>

 <style>
    /* 聲明父元素為flex容器 */
    ul {
    display:flex;
    border: 1px solid red;
    padding: 0;
    list-style: none;
    flex-direction: column;

}
li {
    background-color: #8cacea;
    margin: 8px;
    padding: 10px;
    flex: 0 0 auto;
    border: 2px solid red;
}
  </style>

           

如下是方向變化之前的樣子:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

如下是方向變化之後的樣子:

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

現在文字是以日語風格寫的:沿Main-Axis從上到下。

你會看到項目的寬度填滿了空間,對吧?

如果在之前要變成這樣子,得處理 

flex-basis

 以及 

flex-grow

 屬性。

下面來看看這些會如何影響新的布局。

li {
    flex-basis: 100px;
}

           

下面是你會得到的。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

什麼?高度是被影響了,但是寬度沒有啊?我之前說過,

flex-basis

 屬性定義每個Flex項目的初始寬度。

在切換 

flex-direction

 時,請注意,影響Main-Axis的每一個屬性現在會影響新Main-Axis。像 

flex-basis

 這種會影響Main-Axis上Flex項目寬度的屬性,現在會影響項目的高度,而不是寬度。

方向已經被切換了!

是以,即使你使用 

flex-grow

 屬性,它也是影響高度。本質上,每個作用于橫向軸(即Main-Axis)上的 flex 屬性,現在都會作用于縱向上的新Main-Axis。它隻是在方向上的一個切換。

這裡再來一個例子。我發誓在這個例子之後你會有更好的了解。減少之前看到過的Flex項目的寬度,它們就不再填滿整個空間了:

li {
    width: 200px;
}

           
HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

如果想把清單項移到螢幕中間該怎麼辦呢?

在英語中,這是你到目前為止處理彈性容器的方式。就是說, 把Flex項目移到Main-Axis的中間 。

是以,你會用 

justify-content: center

。但是這樣做不起作用。因為方向變了,中心是沿着Cross-Axis,而不是Main-Axis。

再來看看:

是以請用日國文字來思考。Main-Axis是從上到下,你不需要這樣。Cross-Axis是從左到右。貌似是你所要的。

你需要 把Flex項目移到Cross-Axis的中間 。這裡想起哪個Flex容器屬性了麼?

是的,

align-items

align-items

 屬性處理Cross-Axis上的對齊。

是以要把這些項目移到中間,得這樣做:

li {
    align-items: center;
}

           

瞧瞧!Flex項目已經居中了吧。

HTML5+CSS3前端入門教程---從0開始通過一個商城執行個體手把手教你學習PC端和移動端頁面開發第8章FlexBox布局

參考:

https://medium.freecodecamp.com/understanding-flexbox-everything-you-need-to-know-b4013d4dc9af#.pr6cltk9j

css