Flexbox詳解





Float詳解

學習Flexbox的曲線

學習Flexbox可不是件頗有趣的事情,由於它將挑戰你所知道的CSS佈局方面的知識。固然這也是很是正常的,由於一切知識都是值得學習的。css

另外你要認值對待Flexbox。由於它是現代Web佈局的主流方式之一,不會很快就消失。它也成爲一個新的W3C標準規範。既然如此,那讓咱們張開雙臂,開始擁抱它吧!html

你將學習

我將帶你先了解Flexbox的一些基礎知識。我想這是開始嘗試學習Flexbox的必經階段。前端

學習基礎知識是件頗有意思的事情,更有意思的是能夠經過學習這些基礎理論知識,在實際的應用程序中使用Flexbox。css3

我將帶您親歷不少「小知識點」以後,在文章末尾,使用Flexbox來作一個音樂應用程序的佈局(UI界面佈局)。git

看上去是否是棒棒的?github

在開始進入學習Flexbox構建音樂應用程序的佈局以前,你還將須要瞭解Flexbox在響應式Web設計中所起的做用。web

我將會把這一切都告訴你。bootstrap

上圖是@Jona Dinges設計的瀏覽器

在你開始構建音樂應用程序界面以前,我將一塊兒陪你作一些練習。這看起來可能很無聊,但這是讓你完全掌握Flexbox必經的過程,只有這樣才能讓你很擅長的使用Flexbox。dom

說了這麼多的廢話,那咱們趕忙的開始吧!(難怪篇幅長,原來開始有這麼的…(^_^))

簡介

CSS在過去的幾年裏已發生了很大的變化。CSS中引入了設計師喜歡的filterstransitionstransforms等。但有些東西已經消失了,但是咱們都渴望這些東西能一直存在。

使用CSS製做智能的、靈活的頁面佈局一直以來都是CSSer想要的,也有很人使用各類不一樣的CSS黑魔法去實現智能的頁面佈局。

咱們老是不得不忍受floatdisplay:table這些佈局方式帶來的痛苦。若是你完寫過一段時間的CSS,你可能有相關體會。若是你沒有寫過CSS,那你是幸運的,在這也歡迎你來到CSS佈局中一個更美好的世界中!

彷佛設計師和前端開發人員的此次祈禱終於被上帝聽到了。並且這一次,在很大的風格上作出了改變。

如今咱們能夠拋棄老司機們經常使用的CSS佈局的黑魔法。也能夠和float以及display:table說拜拜。

是時候去擁抱一個更簡潔的製做智能佈局的現代語法。歡迎CSS Flexbox模塊的到來。

Flexbox是什麼

根據規範中的描述可知道,Flexbox模塊提供了一個有效的佈局方式,即便不知道視窗大小或者未知元素狀況之下均可以智能的,靈活的調整和分配元素和空間二者之關的關係。簡單的理解,就是能夠自動調整,計算元素在容器空間中的大小。

這樣聽起來是否是太官方了,其實我也明白這種感受。

如何開始使用Flexbox

這是每一個人都會問的第一個問題,答案是比你預想的要簡單得多。

開始使用Flexbox時,你所要作的第一件事情就是聲明一個Flex容器(Flex Container)。

好比一個簡單的項目列表,咱們經常看到的HTML形式以下所示:

<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;
}

你將看到的效果以下圖所示:

你可能沒有注意到,但事實上已經發生了變化。如今已是一個Flexbox格式化上下文。

記住,默認狀況下,div在CSS中垂直堆棧的,也就是說從上到下排列顯示,就像下圖這樣:

上面的圖是你但願的結果。

然而,簡單的寫一行代碼display:flex,你當即就能夠看到佈局改變了。

如今列表元素(li)水平排列,從左到右。就像是你使用了float同樣。

Flexbox模塊的開始,正如前面的介紹,在任何父元素上使用display:flex

你可能不明白爲何這一變化就能改變列表元素的排列方式。但我能夠負責任的告訴你,你深刻學習以後就能明白。如今你只須要信任就足夠了。

理解flex display是使用Flexbox的一個開始。

還有一件事情,我須要提醒您注意。

一旦你顯式的設置了display屬性的值爲flex,無序列表ul就會自動變成Flex容器,而其子元素(在本例中是指列表元素li)就變成了Flex項目。

這些術語會一次又一次的提到,我更但願你經過一些更有趣的東西來幫助你學習Flexbox模塊。

我使用了兩個關鍵詞,咱們把重點放到他們身上。瞭解他們對於理解後面的知識相當重要。

  • 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)。默認設置以下所示。

通俗的說,感受Main-Axis就是水平方向,從左到右,這也是默認方向。Cross-Axis是垂直方向,從上往下。

默認狀況下,flex-direction屬性的值是row。它讓Flex項目沿着Main-Axis排列(從左向右,水平排列)。這就解釋了本文開始部分時無序列表的表現效果。

儘管flex-direction屬性並無顯式的設置,但它的默認值是row。Flex項目將沿着Main-Axis從左向右水平排列。

若是把flex-direction的屬性值修改爲column,這時Flex項目將沿着Cross-Axis從上到下垂直排列。再也不是從左向右排列。

flex-wrap

flex-wrap屬性有三個屬性值:

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

我將經過一個例子來解釋如何使用flex-wrap屬性。首先在前面的無序列表的HTML結構中多添加幾個列表項li

將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>
</ul>

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

再深刻一點。

繼續給Flex容器內添加Flex項目,好比說添加到10個Flex項目。這個時候會發生什麼?

一樣的,Flex容器仍是能容納全部的子元素(Flex項目)排列,即便瀏覽器出現了水平滾動條(當Flex容器中添加了不少個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項目。

除此以外,還有一個值:wrap-reverse

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

flex-flow

flex-flowflex-directionflex-wrap兩個屬性的速記屬性。

你還記得使用border的速記寫法?border: 1px solid red。這裏的概念是相同的,多個值寫在同一行,好比下面的示例:

ul {
    flex-flow: row wrap;
}

至關於:

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

除了這個組合以外,你還能夠嘗試一些其它的組合。flex-flow: row nowrapflex-flow: column wrapflex-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;
}

你將看到的效果是這樣:

經過justify-content屬性,可讓Flex項目在整個Main-Axis上按照我本身的慾望設置其對齊方式。

可能會有如下幾種類型。

flex-start

justify-content的默認屬性值是flex-start

flex-start讓全部Flex項目靠Main-Axis開始邊緣(左對齊)。

ul {
    justify-content: flex-start;
}

flex-end

flex-end讓全部Flex項目靠Main-Axis結束邊緣(右對齊)。

ul {
    justify-content: flex-end;
}

center

和你預期的同樣,center讓全部Flex項目排在Main-Axis中間(居中對齊)。

ul {
    justify-content: center;
}

space-between

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

ul {
    justify-content: space-between;
}

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

space-around

最後,space-around讓每一個Flex項目具備相同的空間。

ul {
    justify-content: space-around;
}

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

千萬不要以爲這些練習太多,這些練習能夠幫助熟悉Flexbox屬性的語法。也能更好的幫助你更好的理解它們是如何影響Flex項目沿着Main-Axis的對齊方式。

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-itemsjustify-content兩個屬性之間的不一樣之處。

下面是不一樣的值對Flex項目產生的影響。不要忘記這些屬性只對Cross-Axis軸有影響。

stretch

align-items的默認值是stretch。讓全部的Flex項目高度和Flex容器高度同樣。

flex-start

正如你所但願的flex-start讓全部Flex項目靠Cross-Axis開始邊緣(頂部對齊)。

flex-end

flex-end讓全部Flex項目靠Cross-Axis結束邊緣(底部對齊)。

center

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

baseline

讓全部Flex項目在Cross-Axis上沿着他們本身的基線對齊。

結果看上去有點像flex-start,但略有不一樣。那「baseline」究竟是什麼呢?下圖應該能幫助你更好的理解。

align-content

還記得前面討論的wrap屬性嗎?咱們在Flex容器中添加了更多的Flex項目。讓Flex容器中的Flex項目多行排列。

align-content屬性用於多行的Flex容器。它也是用來控制Flex項目在Flex容器裏的排列方式,排列效果和align-items值同樣,但除了baseline屬性值。

align-items屬性同樣,它的默認值是stretch。你如今應該熟悉這些值。那它又是如何影響Flex容器裏的10個Flex項目多行排列方式。

stretch

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

你看到的Flex項目間的間距,是Flex項目自身設置的margin值。

flex-start

以前你看到過flex-start。此次是讓多行Flex項目靠Cross-Axis開始邊緣。沿着Cross-Axis從上到下排列。所以Flex項目在Flex容器中頂部對齊。

flex-end

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

center

你猜到了,center讓多行Flex項目在Cross-Axis中間。在Flex容器中居中對齊。

這是Flex容器的最後一個屬性。你如今知道如何使用各類Flex容器屬性。你能夠在工做中實踐這些屬性。

Flex項目屬性

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

在前一節中,我解釋了Flex容器及其對齊屬性。

確實漂亮。我想你也找到了感受。如今咱們把注意力從Flex容器轉移到Flex項目及其對齊屬性。

像Flex容器,對齊屬性也能夠用在全部的Flex項目。那咱們開始吧。

order

容許Flex項目在一個Flex容器中從新排序。基本上,你能夠改變Flex項目的順序,從一個位置移動到另外一個地方。

這不會影響源代碼。這也意味着Flex項目的位置在HTML源代碼中不須要改變。order屬性的默認值是0。它能夠接受一個正值,也能夠接受一個負值。

值得注意的是,Flex項目會根據order值從新排序。從底到高。

要說明總得須要一個例子。考慮下面這個無序列表:

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

默認狀況下,全部Flex項目的order值都是0。把前面給列表的樣式運用過來。看到的效果以下:

Flex項目顯示是按HTML源代碼中的順序來顯示,Flex項目1234

若是由於某些緣由,在不改變HTML文檔源碼狀況之下,想把Flex項目一從1變成最後。不能修改HTML文檔源碼意思是你不能把HTML代碼改爲:

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

這個時候就須要order屬性。這個時候你須要把Flex項目一的order值設置比其餘Flex項目值更大。

若是你之前使用過z-index屬性,那你就能更好的理解這個屬性。

li:nth-child(1){
    order: 1; /*設置一個比0更大的值*/
}

Flex項目就從新進行了排列,從低到高排列。不要忘記了,默認狀況下,Flex項目二、三、4的order值爲0。如今Flex項目1的order值爲1

Flex項目二、3和4的order值都是0。HTML源代碼秩序並無修改過。若是給Flex項目2的order設置爲2呢?

是的,你猜對了。它也增長堆棧。如今表明Flex項目的最高的order值。

當兩個Flex項目具備相同的order值呢?在下面的示例中,把Flex項目1和3設置相同的order值。

li:nth-child(1) {
    order: 1;
}
li:nth-child(3) {
    order: 1;
}

如今還是從低到高排列。此次Flex項目3排在Flex項目1後面,那是由於在HTML文檔中Flex項目3出如今Flex項目1後面。

若是兩個如下Flex項目有相同的order值時,Flex項目從新排序是基於HTML源文件的位置進行排序。這個屬性就不作過多的解釋。接下來繼續介紹其餘的屬性。

flex-grow 和 flex-shrink

Flex項目最優秀的一點就是靈活性flex-growflex-shrink屬性容許咱們玩這個靈活性。

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

他們可能接受0或者大於0的任何正數。0 || positive number

接下來闡述它們的使用。使用一個簡單的無序列表作爲例子,它只包含一個列表項。

<ul>
    <li>I am a simple list</li>
</ul>
ul {
    display: flex;
}

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

默認狀況下,flex-grow屬性值設置爲0。表示Flex項目不會增加,填充Flex容器可用空間。取值爲0就是一個開和關的按鈕。表示flex-grow開關是關閉的。

若是把flex-grow的值設置爲1,會發生:

如今Flex項目擴展了,佔據了Flex容器全部可用空間。也就是說開關打開了。若是你試着調整你瀏覽器的大小,Flex項目也會縮小,以適應新的屏幕寬度。

爲何?默認狀況下,flex-shrink的值是1,也就是說flex-shrink開關也是打開的。

能夠仔細看看flex-growflex-shrink屬性在各類狀況下的效果,這樣能更好的幫助你理解。

flex-basis

記得前面我說過,Flex項目是當我沒有的。但咱們也能夠控制。

flex-basis屬性能夠指定Flex項目的初始大小。也就是flex-growflex-shrink屬性調整它的大小以適應Flex容器以前。

前面介紹的是很是生要的,因此咱們須要花一點時間來增強對他們的理解。

flex-basis默認的值是autoflex-basis能夠取任何用於width屬性的任何值。好比 % || em || rem || px等。

注意:若是flex-basis屬性的值是0時,也須要使用單位。即flex-basis: 0px不能寫成flex-basis:0

這裏一樣使用只有一個列表項的列表作爲示例。

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

ul {
    display: flex
}
li {
    padding: 4px; /*some breathing space*/
}

默認狀況,Flex項目的初始寬度由flex-basis的默認值決定,即:flex-basis: auto。Flex項目寬度的計算是基於內容的多少來自動計算(很明顯,加上了padding值)。

這意味着,若是你增長Flex項目中的內容,它能夠自動調整大小。

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

然而,若是你想將Flex項目設置一個固定的寬度,你也能夠這樣作:

li {
    flex-basis: 150px;
}

如今Flex項目的寬度受到了限制,它的寬度是150px

它變得更加有趣。

flex速記

flexflex-growflex-shrinkflex-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-growflex-shrink值,flex-basis多是默認值0。這就是所謂的絕對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項目都是默認行爲。

很容易理解這一點,首先看看flex-basis屬性。flex-basis設置爲auto,這意味着Flex項目的初始寬度計算是基於內容的大小。

明白了?

把注意力放到下一個屬性,flex-grow設置爲0。這意味着flex-grow不會改變Flex項目的初始寬度。也就是說,flex-grow的開關是關閉的。

flex-grow控制Flex項目的增加,若是其值設置爲0,Flex項目不會放大以適應屏幕(Flex容器大小)。

最後,flex-shrink的值是1。也就是說,Flex項目在必要時會縮小。

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

注意:Flex項目沒有增加(寬度)。若是有必要,若是調整瀏覽器(調小瀏覽器寬度),Flex項目會自動計算寬度。

flex: 0 0 auto

li {
    flex: 0 0 auto;
}

這個至關於flex: none

仍是老規矩:寬度是被自動計算,不過彈性項目不會伸展或者收縮(由於兩者都被設置爲零)。伸展和收縮開關都被關掉了。

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

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

應該注意到的第一件事情是,這兩個彈性項目的寬度是不一樣的。由於寬度是基於內容寬度而自動計算的,因此這是預料獲得的。

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

不要着急,稍後我會展現如何處理這種怪異的行爲。

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

flex: 1 1 auto

這與 flex: auto 項目相同。

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

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

此時,項目會填滿可用空間,在縮放瀏覽器時也會隨之收縮。

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>

ul {
    display: flex;
}

/* 第一個彈性項目 */
li:nth-child(1) {
    flex: 2 1 0; /* 與寫成 flex: 2 相同*/
}

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

記住設置 flex-grow : 1,會讓彈性項目填滿可用空間。伸展開關打開了。

這裏有兩個彈性項目。一個的 flex-grow 屬性值是 1,另外一個是 2,那麼會出現啥狀況呢?

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

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

它是這樣工做的:前一個佔 1/3 的可用空間,後一個佔 2/3 的可用空間。

知道是我怎麼獲得這結果的麼?

是根據基本的數學比例。」單項比例 / 總比例」,我但願你沒有漏過這些數學課。

看到出現啥狀況了麼?

即便兩個彈性項目內容同樣大(近似),它們所佔空間仍是不一樣。寬度不是基於內容的大小,而是伸展值。一個是另外一個的約兩倍。

有關於flex-growflex-basisflex-shrink之間的詳細計算,能夠點擊@Chris Wright寫的《Flexbox adventures》博文。譯文能夠點擊這裏

align-self

align-self 屬性更進一步讓咱們更好地控制彈性項目。

你已經看到 align-items 屬性是如何有助於總體對齊彈性容器內的全部彈性項目了。

若是想改變一個彈性項目沿着側軸的位置,而不影響相鄰的彈性項目,該怎麼辦呢?

這是 align-self 屬性大展拳腳的地方了。

該屬性的取值能夠是這些值之一:auto || flex-start || flex-end || center || baseline || stretch

li:first-of-type {
    align-self: auto || flex-start || flex-end || center || baseline || stretch
}

這些值你已經熟悉過了,不過做爲回顧,以下是它們如何影響特定目標項目。這裏是容器內的第一個項目。目標彈性項目是紅色的。

flex-end

flex-end將目標項目(Flex項目)對齊到Cross-Axis的末端。

center

center將目標項目(Flex項目)對齊到Cross-Axis的中間。

stretch

stretch會將目標項目拉伸,以沿着Cross-Axis填滿Flex容器的可用空間(Flex項目高度和Flex容器高度同樣)。

baseline

baseline將目標項目沿着基線對齊。它與flex-start的效果看起來是同樣的,不過我相信你理解了基線是什麼。由於前面已經解釋過。

auto

auto 是將目標Flex項目的值設置爲父元素的 align-items值,或者若是該元素沒有父元素的話,就設置爲 stretch

在下面的狀況下,彈性容器的 align-items 值爲 flex-start。這會把全部彈性項目都對齊到Cross-Axis的開頭。目標Flex項目如今繼承了 flex-start 值,即父元素的 align-item 值。

以下是上面Flex項目的基礎樣式。這樣你能夠對發生的事情理解得更好點。

ul {
    display: flex;
    border: 1px solid red;
    padding: 0;
    list-style: none;
    justify-content: space-between;
    align-items: flex-start;  /* 影響全部彈性項目 */
    min-height: 50%;
    background-color: #e8e8e9;
}

li {
  width: 100px;
  background-color: #8cacea;
  margin: 8px;
  font-size: 2rem;
}

如今你差很少已經爲有趣的部分作好準備了

絕對和相對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;
}

以下是結果:

若是你已經忘了的話,flex: 1 1 auto 是與 flex-grow: 1flex-shrink: 1flex-basis: auto 相同的。

Flex項目的初始寬度是被自動計算的(flex-basis: auto),而後會伸展以適應可用空間(flex-grow: 1)。

當Flex項目由於被設置爲 flex-basis: auto,而致使寬度被自動計算時,是基於Flex項目內包含的內容的大小而計算。

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

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

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

下面咱們把Flex項目變成絕對的, 就是說此次它們的寬度是基於 flex屬性,而不是內容的大小。一行代碼就能夠出奇蹟。

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

效果以下:

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

Flex項目的初始寬度是零(flex-basis: 0),而且它們會伸展以適應可用空間。當有兩到多個Flex項目的 flex-basis 取值爲0時,它們會基於 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>

ul {
    display: flex;
}
li {
    flex: 0 0 auto;
}

你能夠看到以下的效果:

這裏有幾件事情要注意:

  • flex-grow 值爲設置爲0。這就解釋了爲何列表項不會伸展。
  • Flex項目向Main-Axis的開頭對齊(這是默認行爲)。
  • 因爲項目被對齊到Main-Axis開頭,右邊就有一些多餘的空間。看到了吧?

如今在第一個列表項(branding)上使用 margin: auto,看看會出啥狀況。

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

剛剛發生了什麼?以前的剩餘空間如今已經被分配到第一個Flex項目的右邊了。

還記得我前面說的話吧?當在Flex項目上使用 margin: auto 時,值爲 auto 的方向(左、右或者兩者都是)會佔據全部剩餘空間

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

/* 若是願意的話,也能夠用 margin 簡寫來設置兩個邊 */
li:nth-child(1) {
    margin-left: auto;
    margin-right: auto
}

如今空白被分配到Flex項目的兩邊了。

那麼,這是否是對很酷的自動外邊距對齊的一種折衷方案呢?看起來是。若是沒注意的話,它也多是受挫之源。當在一個Flex項目上使用自動外邊距(margin: auto)時,justify-content 屬性就不起做用了。

例如,在上面的Flex容器上經過 justify-content屬性,設置不一樣的對齊選項時,對佈局沒有影響。

ul {
    justify-content: flex-end;
}

Flexbox實戰

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

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

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

Bootstrap導航

AirBnB PC端導航

Twitter PC端導航

建議你本身寫代碼。試着本身實現這些導航系統。如今你已經掌握了所需的全部知識。你所須要的是一點勇氣去開始寫。

下一節再見。希望在你已經完成了導航系統練習以後。

切換flex-direction會發生什麼?

提醒一下:將會有一些奇怪的東東出現

在入手學習Flexbox時,這個部分是最惱火的。我估計不少彈性世界的新手也會發現如此。

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

好吧,如今你也能夠改變這個方向。

正如在較早的小節中所描述的那樣,用 flex-direction: column 時,確實是這樣。

當用 flex-direction: column 時,Main-Axis和Cross-Axis會向以下所看到的那樣改變:

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

Flexbox的默認Main-Axis和Cross-Axis也是採用一樣的方向。

不過,若是將 flex-direction 切換爲 column,它就再也不遵循英語的範式,而是日語的範式!

是的,日語。

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

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

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

看看下面這個例子。標準無序列表(ul),帶有 3 個列表項(li)。不過此次我要改變一下flex-direction

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

ul {
    display: flex;
    flex-direction: column;
}

以下是方向變化以前的樣子:

以下是方向變化以後的樣子:

出啥事了?

如今文字是以日語風格寫的:沿Main-Axis從上到下

我很樂意指出,你會發現一些有趣的事情。

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

若是在以前要變成這樣子,得處理 flex-basis 以及 flex-grow 屬性。

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

li {
    flex-basis: 100px;
}

下面是你會獲得的。

什麼?高度是被影響了,可是寬度沒有啊?我以前說過,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;
}

若是想把列表項移到屏幕中間該怎麼辦呢?

在英語中,這是你到目前爲止處理彈性容器的方式。就是說, 把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項目已經居中了吧。

是有點懸乎,我知道。若是須要,就再複習一遍好了。在研究Flexbox時,我發現不少 CSS 書都略過了這一部分。

用日語文字來思考一下會有很大幫助。咱們有必要了解,全部Flexbox屬性都是基於合適的 flex-direction 起做用。

相信你又學到了一點新東西。我很開心解釋這些,但願你也很開心。

個人天啦,彈性盒解決了那問題了?

不少設計師用 CSS 時遇到的一些典型問題已經被Flexbox垂手可得解決了。

@Philip Walton 在其 Flexbox解決了的問題這個項目 列出了 6 種典型的問題(到本文編寫時)。

他全面討論了以前用 CSS 的限制,以及目前Flexbox提供的解決方案。建議在完成本文後看一看。

在接下來的實踐環節中,在開始用彈性盒建立一個音樂應用佈局時,我會解釋他提出的一些概念。

Flex 不兼容瀏覽器的坑

若是你不是在夢中寫 CSS 的那一類人的話,就可能想看看這個 Github 倉庫

有些比我聰明的人在這裏維護了一個Flexbox的 bug 列表及其變通方法。當有些事情沒有按預期起做用時,這是我看的第一個地方。我也會在後面的實踐環節中帶你踩踩一些顯眼的坑。

@Philip Walton早前專門寫了一篇有關於解決Flexbox跨瀏覽器兼容Bug的文章《Normalizing Cross-browser Flexbox Bugs》,對應的譯文能夠點擊這裏閱讀

用彈性盒建立一個音樂應用的佈局

在學習完了乏味嚴謹的基礎知識以後,該有一些有趣的項目了。是時候玩玩實際的例子,並把剛得到的Flexbox技能用上去。

想出一個好項目花了我好幾天。因爲缺少創造性的選擇,我想出了一個貓玩的音樂應用佈局。我稱它爲 catty music 。

也許到了 2036 年,咱們就能讓貓在火星上的某個地方唱搖滾。以下是完成了的佈局看起來的樣子,而且徹底是用Flexbox佈局的。

能夠在線上看,在這裏

若是在移動設備上看,外觀會稍微有點不一樣。這是在本文響應式設計一節中要解決的問題。

不過,有件事我得坦白。我已經作了許多人認爲是錯誤的事情。我徹底用Flexbox建立整個佈局。

出於多種理由,這樣作可能並不是那麼理想。可是在這種狀況下是故意的。我只是想用一個項目,向你展現全部能夠用Flexbox作的事情。

若是你好奇何時使用Flexbox是對的,何時是錯的,那你能夠讀讀我寫的一篇文章。

Flexbox 很棒,不過它在這裏不受歡迎 Flexbox 毋庸置疑是咱們大多數人遇到的最好的東西(若是你寫 CSS 的話),不過它是否是適合全部狀況呢…

這裏,我內心的石頭終於落地了。如今我相信在讀完這個以後,沒人會對我大呼小叫了。

Catty Musci 中的一切都是用Flexbox佈局, 這是故意儘量地炫技

因此下面咱們開始把這個玩意建成!對於任何稍微合理一點的項目來講,有點規劃對避免效率低下是有幫助的。就讓我帶你看看建立 Catty Music 佈局的規劃方法。

從哪裏開始?

只要用Flexbox建立佈局,就應該從找出佈局中哪個部分會做爲Flex容器開始。而後纔可使用Flexbox提供的強大對齊屬性。

分析

你可讓整個包含體做爲Flex容器(下圖中被包含在紅色邊框內的部分),並把佈局的其它部分分紅Flex項目(Item 1Item 2)。

這樣作徹底說得通,讓 Item 1 包含佈局中除了腳註之外的每一個部分。腳註部分用來包含音樂控制按鈕。

你知道Flex項目也能夠成爲Flex容器嗎?是的,是可能的!

你想嵌套多深就嵌套多深(不過理智的作法是保持一個合理的水平)。因而,根據這個新啓示就有了這個…

Item 1(第一個Flex項目)也能夠弄成一個Flex容器。而後,側邊欄(Item 1b)和主欄目(Item 1a)就成了 Item 1 的Flex項目。

你依然與我同在,對吧?像這樣拆分佈局,會給你一個至關不錯的心理模型來處理。

在用Flexbox開始建立更爲複雜的佈局時,你會看到這有多重要。固然,你並不須要一個像上面那樣高大上的圖像。在紙上畫一個簡單的草圖就足夠了。

記得我說過能夠想嵌套多深就嵌套多深吧?貌似這裏還能夠再來一個嵌套。

看看上面的主欄目(Item 1a)。它也能夠變成一個Flex容器,以容納以下高亮度的部分:Item 1a — AItem 1a — B

可能你會決定不把主欄目(Item 1a)變成Flex容器,只在其內部放入兩個 div 來容納高亮度部分。

是的,這樣作沒問題,由於 「Item 1a — A」 和 「Item 1a — B」 是垂直堆放的。

默認狀況下,div 是垂直堆放的。這是盒模型的工做原理。若是選擇把主欄目變成一個Flex容器,就有了隨時可你供調遣的強大對齊屬性。

Flexbox中的 Flex 是指彈性、靈活。Flex容器默認是彈性的,跟響應式有點相似。這也許是使用Flex容器,而不是普通 div 的另外一個緣由。不過,這取決於實際狀況。

在你建立 Catty Music 時我會論及一些事情事情。你如今應該去寫點代碼了。

HTML結構

從以下的基礎 HTML 設置開始。

<!DOCTYPE html>
<html>
    <head>
        <title>Catty Music</title>
    </head>
    <body>

        <main></main> <!--用來包含應用的主欄目-->

        <footer></footer> <!--用來包含音樂控制按鈕和歌曲細節-->

    </body>
</html>

而後爲它設置樣式:

html,
body {
    height: 100%; /*顯式設置這,是很重要的*/
}

body {
    display: flex; /*flex 超能力被激活了! */
    flex-direction: column; /*垂直而不是水平堆放彈性項目(主欄目和腳註元素)*/
}

使用Flexbox的第一個步驟就是肯定一個Flex容器。

這正好是上面代碼所作的。它將 body 元素的 display 屬性設置爲 flex。如今有了一個Flex容器,即 body 元素。

Flex項目也被定義了(item 1item 2):跟前面分析中所作的同樣。

注意,若是你對這個概念仍是有點模糊,就應該再看看我在以前開始分析時展現的圖像。

盯着最後的圖像,你應該讓彈性項目工做起來。

讓腳註吸附在底部。讓放音樂控制的腳註吸附在頁面的底部,同時讓主欄目填滿剩餘空間。

你怎麼實現?

main {
    flex: 1 0 auto; /*填滿剩餘空間*/
}

footer {
    flex: 0 0 90px; /*不會放大或者收縮 - 只會固定在 90px 高度。*/
}

請看上面列出的代碼中的註釋。多虧了 flex-grow 屬性,它讓主欄目填滿整個空間相對很容易。只需將 flex-grow 屬性的值設置爲 1 便可。還應該把 flex-shrink 屬性設置爲 0。爲何呢?

由於 flex-direction 沒有改變,因此緣由也許不很明顯。

在有些瀏覽器中,會有一個 bug,容許Flex項目收縮後比其內容尺寸小。這是個很古怪的行爲。

解決這個 bug 的變通方案是把 flex-shrink 的屬性值設置爲 0,而不是默認值 1,同時,把 flex-basis 屬性設置爲 auto

就像是說:請自動計算Flex項目的大小,可是不要收縮。有了這個簡寫值,就能夠獲得Flex項目的默認行爲。

Flex項目會隨着瀏覽器縮放那個收縮。縮放不是基於 flex-shrink屬性,而是基於自動對Flex項目的寬度從新計算(flex-basis: auto)。

這會致使Flex項目至少與它的寬度或者高度(若是聲明瞭)或者默認內容尺寸同樣大。請不要忘記我在分析 flex 簡寫屬性時設立的原則。後面會有更多簡寫的東西。

如今事情聚集到一塊兒了,下面咱們放點樣式來定義間距和顏色。

body {
    display: flex;
    flex-direction: column;
    background-color: #fff;
    margin: 0;
    font-family: Lato, sans-serif;
    color: #222;
    font-size: 0.9em;
}

footer {
    flex: 0 0 90px;
    padding: 10px;
    color: #fff;
    background-color: rgba(61, 100, 158, .9);
}

依然沒有啥奇蹟。你將看到的效果以下圖所示:

看看事情是如何開始初具規模,你會讓它變得更好一點。

固定側邊欄

若是你是跟着寫代碼,就更新一下你的 HTML 文檔。

<main>
    <aside> <!--這表明側邊欄,其中包含了來自 font-awesome 的圖標集--> <i class="fa fa-bars"></i> <i class="fa fa-home"></i> <i class="fa fa-search"></i> <i class="fa fa-volume-up"></i> <i class="fa fa-user"></i> <i class="fa fa-spotify"></i> <i class="fa fa-cog"></i> <i class="fa fa-soundcloud"></i> </aside>

    <section class="content"> <!--這一部分會容納除側邊欄之外的全部東西--> </section>
</main>

上面的代碼列表已經解釋的很清楚了。

至於圖標設置,我用了熱門的 Font Awesome 庫。這樣用你想要的圖標就簡單到只需添加一個 CSS 類便可。這就是我在 aside 標記中所作的事情。

正如以前解釋過的,上面的 main 部分也會成爲一個Flex容器。側邊欄(用 aside 標記表示) 以及 section會成爲Flex項目。

main {
  flex: 1 0 auto; /* 變成一個彈性項目*/
  display: flex; /*只包含這一行,如今就有一個彈性容器,帶有彈性項目:側邊欄和主內容區*/
}

很好,愈來愈有意思了,嘿嘿。

如今,主欄目是一個Flex容器了。下面咱們來處理它的Flex項目之一,側邊欄。跟讓腳註吸附到頁面底部同樣,你還會想讓側邊欄吸附到頁面的左邊。

aside {
    flex: 0 0 40px; /*不會放大或者縮小。固定在 40px*/ 
}

側邊欄應該讓圖標垂直堆放。可讓側邊欄變成Flex容器,給它設一個 flex-direction,讓全部圖標垂直堆放。而後應用一個對齊屬性,讓圖標就位。

在下面的代碼列表中,看看你可能會怎麼作。

aside {
    /* ... */
    display: flex; /*如今也是一個彈性容器*/
    flex-direction: column; /*垂直堆放圖標*/

    /*由於方向改變了,以下在垂直方向上起做用。*/
    justify-content: space-around;

    align-items: center; /*方向改變了!這條影響的是水平方向。將圖標居中*/
    background-color: #f2f2f2; /*讓我變漂亮*/
}

aside i.fa {
    font-size: 0.9em;  /*圖標的字體大小*/
}

我已經在上面的代碼中加了不少註釋,如今看看佈局是如何漂亮。很乾淨,只有幾行代碼。合情合理的代碼,沒有亂七八糟的招數。

主內容區目前是空的。不要忘記它是第二個列表項,側邊欄是第一個。給這裏放一下東西。給主內容區添加內容你能夠再看看完工的項目,這樣就不會忘記接下來要發生的事情。

更重要的是,這能幫助你理解下面的代碼。更新 HTML 文檔,在 .content部分添加以下標記:

<section class="content"> <!--這一區是空的,用內容填充它--> <div class="music-head"> <!--第一個列表項:包含音樂詳情--> <img src="images/cattyboard.jpg" /><!--專輯封面--> <section class="catty-music"> <!--專輯的其它細節--> <div> <p>CattyBoard Top 100 Single Charts (11.06.36)</p> <p>Unknown Artist</p> <p>2016 . Charts . 100 songs</p> </div> <div> <!--Music controls--> <i class="fa fa-play">Play all</i> <i class="fa fa-plus">Add to</i> <i class="fa fa-ellipsis-h">More</i> </div> </section> </div> <!--end .music-head--> <!--第二個列表項:包含專輯中的歌曲列表--> <ul class="music-list"> <li> <p>1. One Dance</p> <p>Crake feat CatKid & Cyla</p> <p>2:54</p> <p><span class="catty-cloud">CATTY CLOUD SYNC</span></p> </li> <li> <p>2. Panda</p> <p>Cattee</p> <p>4:06</p> <p><span class="catty-cloud">CATTY CLOUD SYNC</span></p> </li> <li> <p>3. Can't Stop the Feeling!</p> <p>Catin Cimberlake</p> <p>3:56</p> <p><span class="catty-cloud">CATTY CLOUD SYNC</span></p> </li> <li> <p>4. Work From Home</p> <p>Cat Harmony feat Colla</p> <p>3:34</p> <p><span class="catty-cloud">CATTY CLOUD SYNC</span></p> </li> </ul> </section>

嗯,我比上次添加了更多的東西,不過很簡單。我用一個 div 填充空內容部分,這個 div 用來容納 catty 專輯的封面和其餘細節。ul 容納專輯的歌曲列表。列表中用單獨的段落來容納歌曲標題、藝術家、時長、」_catty cloud sync「。

那麼你打算如何設置樣式呢?看看我怎麼作的?

首先,應該讓 .content部分紅爲Flex容器。

.content {
    display: flex;
    flex: 1 0 auto; /*這確保本區伸展到填滿可用空間*/
    flex-direction: column;
}

還應該處理它的Flex項目:

.music-head {
    flex: 0 0 280px; /*相同的備忘,不要伸展或收縮 - 固定爲 280px*/
    display: flex;  
    padding: 40px;
    background-color: #4e4e4e;
}

.music-list {
    flex: 1 0 auto;
    list-style-type: none;
    padding: 5px 10px 0px;
}

.music-head 容納專輯封面以及其它專輯細節。相同的備忘錄,不要伸展或者收縮,保持高度爲 280px。高度?沒有寬度?是的!

父元素已經切換了 flex-direction。隨後須要讓它變成一個彈性容器,因此寫上 display: flex.music-list 容納歌曲列表,填滿與上面的 .music-head 共享的剩餘可用空間。

這依然沒讓人以爲有多漂亮,不過來吧,若是你還跟着,你作的很不錯了。贊一下。

這裏有幾個問題。

歌曲列表看起來很糟糕

包含音樂封面的部分有真的很難看的文本

我會再次來你解決這些問題。

下面是我提出的解決方案。

處理歌曲列表

每一個歌曲列表包含 4 個段落,歌名、藝術家、時長和 「catty cloud sync」。

必定有辦法讓全部這些放在一行,每一個段落佔據該行相等空間。用Flexbox來搞定!這裏的概念與不少柵格系統中用的同樣。

li {
  display: flex; /*段落如今顯示在一行上*/
  padding: 0 20px; /*留點呼吸空間*/
  min-height: 50px;
}

li p {
  flex: 0 0 25%; /*這是甜麪醬*/
}

看到段落會發生什麼了嗎?

flex: 0 0 25%;

「不要伸展或者收縮,不過每一個段落應該佔據 25% 的可用空間」 。段落所佔空間是相等的。

使用這種技術

這種技術是頗有用的。能夠用它來建立不相等的內容區。好比,兩欄視圖。

一個欄目能夠佔可用空間的 60%,另外一個佔 40%

.first-section: 0 0 60%;
.second-section: 0 0 40%;

能夠用這種技術建立柵格系統。你將看到的效果以下:

給列表交替的顏色,也處理一下 「catty cloud sync」 標籤。

li span.catty-cloud {
  border: 1px solid black;
  font-size: 0.6em;
  padding: 3px;
}

li:nth-child(2n) {
  background-color: #f2f2f2;
}

因此,你征服它了,開始更好理解Flexbox方言了。這是你如今應該獲得的東西了。

如今要處理第二個問題了。讓相冊詳情文本看着更好看點。下面真是很簡單的事情。

.catty-music{
    flex: 1 0 auto;
    display: flex;
    flex-direction: column;
    font-weight: 300;
    color: #fff;
    padding-left: 50px;
}

.catty-music div:nth-child(1){
    margin-bottom: auto;
}

.catty-music div:nth-child(2){
    margin-top: 0;
}

.catty-music div:nth-child(2) i.fa{
    font-size: 0.9em;
    padding: 0 0.7em;
    font-weight: 300;
}
.catty-music div:nth-child(1) p:first-child{
    font-size: 1.8em;
    margin: 0 0 10px;
}

.catty-music div:nth-child(1) p:not(:first-child){
    font-size: 0.9em;
    margin: 2px 0;
}

你作到了,並且作的至關不錯。

一個快速練習

我留下腳註部分給你做爲練習。試着本身解決腳註。只需採用相同的技術。你知道你能搞定嗎?若是卡住了,能夠查看 Catty Music 的完整源代碼。你也能夠把整個腳註分紅Flex項目,從這裏開始。

簡直不相信你到了這一步。下面,你會看到Flexbox是如何有助於響應式設計。

Flexbox用於響應式設計

已經有很多關於響應式設計的書,有很多書還不錯。

由於本文專一於Flexbox,因此我不會深刻響應式設計。

若是你從未接觸過任何關於響應式設計相關的知識,建議你點擊這裏進行了解

像我以前在某處說過的那樣,用Flexbox,咱們確實獲得了一些開箱即用的響應性。

Flexbox就像 彈性的盒子 。不過,能夠經過媒體查詢搞定不一樣的屏幕尺寸,而後改變彈性行爲。

以下是一個示例。咱們又用簡單無序列表來幫忙。

<ul>
    <li>Home</li>
    <li>About</li>
    <li>Contact</li>
    <li>Register</li>
    <li>Login</li>
  </ul>

而且設置點樣式…

ul {
    list-style-type: none;
    display: flex;
    border: 1px solid #4e4e4e;
}

li {
    flex: 0 0 auto;
    padding: 10px;
    margin: 10px;
    background-color: #8cacea;
    color: #fff;
    font-size: 1em;
}

如今你已是Flexbox專家了,因此你知道是咋回事。

以下是導航欄的樣子。

這對於桌面以及平板電腦可能還挺酷,不過在某些屏幕尺寸上,就特別難看。在移動設備上,你會想讓導航條目垂直堆放。而後媒體查詢就登堂入室了。

@media screen and (max-width: 769px) {
    /* 這裏的代碼只適用於寬度小於 769px 的屏幕設備*/
    ul {
        flex-direction: column; /* 在更小的設備上,切換方向*/
    }
}

若是在這以前,你對響應式設計還懂那麼點,那就太棒了。把Flexbox歸入你已有的知識好了。

順便說一句,我假設你理解媒體查詢是什麼。若是不理解的話,看看下面的簡介。

媒體查詢

媒體查詢是響應式設計的核心,讓你能夠以特定屏幕尺寸爲目標,單獨指定運行在該設備上的代碼。

使用媒體查詢最流行的形式是 @media 規則。

它看起來是這樣的:

@media screen and (max-width: 300px) {
  /*在這個代碼塊中寫 CSS*/
}

看着這段代碼,猜均可以猜到它的做用。

「對於最大寬度爲 300px 的屏幕設備… 作這作那」

在該代碼塊中的任何樣式都將適用於匹配表達式的設備,即 「screen and (max-width: 300px)」 。

我猜這有助於消除一些疑惑。

快速練習

Catty music 在移動設備上的顯示有所不一樣。這但是個好消息。更棒的是你應該試着從新建立它。

若是你遇到了難題,本教程代碼庫的連接在下一節。解決方案也在倉庫中。快到最後了!在總結部分,我將討論瀏覽器支持、有用的連接和幫助你上手的資源。

總結

你已經學習瞭如何使用Flex容器和Flex項目的對齊屬性。我引導你理解了絕對和相對彈性、自動外邊距對齊以及切換彈性方向。你還有機會將Flexbox技能應用到建立 Catty Music 應用,而後我也提到了響應式設計。

這確實是一段漫長的旅程。

如今,我會向你解釋一些最終的概念。用一些我認爲你會發現頗有用的資源和連接幫助你。

Flexbox的瀏覽器支持

這是當傾向於在生產中使用Flexbox時,被問到的一個常見的問題。這問題我也無法很好回答,不過 caniuse 網站能很好處理這個問題。

以下是一個來自 caniuse 的屏幕截圖,瀏覽器支持很棒。你能夠在這裏本身看

在我職業生涯早期,我瀏覽過 caniuse 不少次,依然無法掌握表示的數據是什麼意思。因此這裏有一個簡單的解釋。

caniuse 網站的右下角是一個圖例。

看看上面的圖像,或者就訪問一下網站,找到圖例,就明白了。實際上就是這麼回事。

文章轉載自:
理解 Flexbox:你須要知道的一切

相關文章
相關標籤/搜索