Flexbox 彈性盒模型

Flexbox叫彈性盒模型盖矫,它的使用場景主要是屏幕自適應布局和取代浮動布局樟澜。

細節(jié)性的知識需要大量實踐,系統性的知識則需要真正理解系統阿趁。我認為Flexbox就屬于系統性的知識稽莉。所以這篇文章從概念入手瀑志,力求做到只要閱讀一遍,就可以讓開發(fā)者心中有乾坤。

一維布局模型

你他媽可能是三體看多了吧劈猪,啥叫一維布局模型昧甘?

一維布局模型,簡單講就是战得,在主軸方向確定的情況下充边,只有,沒有常侦。

我們熟悉的二維布局模型有哪些呢浇冰?有display: tabledisplay: grid。而我們今天要講的display: flex就是妥妥的一維布局模型了聋亡。

直接看圖肘习。

[圖片上傳失敗...(image-395a3d-1578030195248)]

可以看到,Flexbox有的概念坡倔,卻沒有的概念漂佩。這導致它的表達能力是受限的。

概念

我們如何確定一條短線是中文的還是阿拉伯數字的1呢罪塔?

你可能覺得我在搞笑投蝉。一眼看過去,橫向的不就是中文的征堪,縱向的不就是阿拉伯數字的1么瘩缆。

是的。那是因為我們遵循著一些默認的約定:兩眼連成的線確定了水平方向请契。

Flexbox也是這個道理咳榜。它是一個一維布局模型,我們就要找到確定僅有的維度的那根線爽锥。

這就引出了Flexbox的第一個概念:主軸(mian axis)與交叉軸(cross axis)。主軸就是那根僅有的維度線畔柔。兩眼連成的線與主軸方向保持平行氯夷,這就是肉眼看待Flexbox的正確方式。否則有時候它會顯得很別扭靶擦。

然后我們再來說彈性盒子腮考。既然它是一個盒子,那肯定得有容器玄捕,也得有內容踩蔚。

也就引出了Flexbox的第二個概念:彈性容器(flex container)與彈性項目(flex item)。

你可以將彈性容器理解為冷戰(zhàn)時期的柏林枚粘,各方國際政治勢力自然就是若干彈性項目了馅闽。幾個國際大流氓聚在一起開會討論什么呢?當然是開會討論如何瓜分柏林咯。是的福也,彈性盒模型討論的就是彈性項目如何瓜分彈性容器這一溫馨的話題局骤。

上一小節(jié)我們提到過,Flexbox是一維布局模型暴凑。它帶來的結果就是Flexbox有的概念峦甩,卻沒有的概念。

所以引出Flexbox的第三個概念:行(line)现喳。

直接看圖凯傲。

[圖片上傳失敗...(image-c6e1d9-1578030195249)]

最小長度

如果彈性容器有富余空間,那好說嗦篱,大家分就是了冰单。而如果彈性容器空間不夠,彈性項目不僅沒得分默色,大家還得擠一擠球凰。那么問題就來了,擠不是無限制的擠腿宰,咱們就來探討一下呕诉,擠到什么程度,是可忍孰不可忍吃度?

舉個例子甩挫。

.container {
    display: flex;
    width: 850px;
    padding: 5px;
}
.container .item {
    width: 200px;
    height: 50px;
    margin: 5px;
}
.container .item:nth-child(2) {
    width: 1000px;
}

[圖片上傳失敗...(image-dd981a-1578030195249)]

兩個彈性項目的長度加起來的和已經超過了彈性容器,所以不得不擠壓椿每。擠壓的比率咱們先不考慮伊者,咱們先觀察擠壓的方式。有沒有發(fā)現紅色部分都有不同程度的收縮间护,但是黃色部分卻巋然不動亦渗?

黃色部分是什么?是彈性容器的padding和彈性項目的margin汁尺。盒子模型咱們都了解吧法精,除了paddingmarginborder之外痴突,是不是只剩content了搂蜓?

咱們可以大膽猜測,Flexbox只敢欺負盒子模型的content辽装,其余都是大爺帮碰,惹不起。

別急拾积,再來驗證一下殉挽。

.container {
    display: flex;
    width: 850px;
    padding: 5px;
}
.container .item {
    width: 200px;
    height: 50px;
    margin: 5px;
}
.container .item:nth-child(2) {
    width: 1000px;
    padding: 0 450px;
}

[圖片上傳失敗...(image-5d0592-1578030195249)]

這下是不是很清楚了丰涉?第一個彈性項目的content長度已經變成了0;第二個也好不到哪去此再,因為盒子長度都被padding占據昔搂,它的content長度實際上也是0。都把人家擠破產了输拇,卻絲毫不敢動其他的屬性摘符,勢利眼無疑了。

我們再來看一個有意思的例子策吠。

.container {
    display: flex;
    width: 850px;
    padding: 5px;
}
.container .item {
    width: 200px;
    height: 50px;
    margin: 5px;
}
.container .item:nth-child(2) {
    width: 1000px;
    padding: 0 300px;
}
.container .item .inner {
    width: 500px;
    height: 100%;
}

[圖片上傳失敗...(image-5bf43-1578030195249)]

我在第二個彈性項目中放了一個長500px的元素逛裤,結果你猜怎么著,彈性項目的padding竟然有一部分和元素重合了猴抹。連子元素都未能幸免带族。

一般來說盒子模型的content都是被文字撐開的,我們最后再來看看文字的情況蟀给。

[圖片上傳失敗...(image-6084f4-1578030195249)]

在彈性項目顯式設置了寬度的情況下蝙砌,彈性項目并不能完全包裹文字。也就是說文字也幫不了它跋理,既然它聲明了寬度择克,文字撐開的長度最多不能超過顯式聲明的寬度,超出的文字只能溢出前普。

[圖片上傳失敗...(image-3e4e66-1578030195249)]

而沒有顯式聲明寬度的情況肚邢,文字的寬度就是彈性項目盒子模型的content,Flexbox也拿它沒辦法拭卿。

總結一下:當富余空間不夠時骡湖,Flexbox只會擠壓彈性項目的content,其余如padding 峻厚、marginborder完全不受影響响蕴。同時彈性項目沒有顯式聲明寬度的情況下,Flexbox也不會擠壓文字惠桃。

display

從這里開始换途,我們就要講具體的CSS屬性了。

display有兩個和Flexbox相關的屬性刽射,分別是display: flexdisplay: inline-flex

對于容器內部的項目來說剃执,效果是一樣的誓禁。它們的區(qū)別在于容器自身應該以塊元素還是行內元素的身份立命。包括table也有這樣的區(qū)分肾档,就不多講了摹恰。

flex-direction

這個屬性聲明的是主軸的方位和方向辫继。

首先,主軸可不一定是水平的俗慈,主軸切換了那可就什么都變了姑宽。

其次,主軸聲明的信息有兩個闺阱,分別是:

  • 它是水平的還是垂直的炮车?
  • 它在水平或垂直維度上是從左到右還是從右到左?

所以這里也涉及到四個屬性值酣溃。

.container {
    flex-direction: row(default) | row-reverse | column | column-reverse;
}

[圖片上傳失敗...(image-192af0-1578030195249)]

flex-wrap

這個屬性聲明的是當容器中的項目一行放不下的時候瘦穆,是讓大家擠一擠呢,還是換行赊豌。

其實這里也包含兩個信息:

  • 要不要換行扛或?
  • 如果需要換行就會形成多行,多行是從上到下排列還是從下到上排列碘饼?
.container {
    flex-wrap: nowrap(default) | wrap | wrap-reverse;
}

[圖片上傳失敗...(image-783856-1578030195249)]

如果把flex-directionflex-wrap結合起來熙兔,大家會不會懵逼?上上下下左左右右艾恼。其實不管它怎么reverse住涉,flex-direction反轉的是主軸的方向,flex-wrap反轉的交叉軸的方向蒂萎。

抓住一些概念性的東西秆吵,就不會懵逼了。

flex-flow

這是一個集合屬性五慈,可以同時定義flex-directionflex-wrap纳寂。

也就是說,這一個屬性可以一站式聲明主軸和交叉軸的特性泻拦。

.container {
    flex-flow: row-reverse wrap-reverse;
}

justify-content

這個屬性聲明每行內的項目如何水平對齊毙芜。

把彈性容器一行內的項目想象成一行行內元素,justify-contenttext-align的食用方式是一樣的争拐。

.container {
    justify-content: flex-start(default) | flex-end | center | space-between | space-around | space-evenly;
}

[圖片上傳失敗...(image-96682b-1578030195249)]

flex-start腋粥、flex-endcenter非常表意,咱們按下不表架曹。

解釋一下后面三個屬性值:

  • space-between表示兩頭的項目對齊容器壁隘冲,項目與項目之間的空隙平均分配。所謂的between指的就是項目之間绑雄。
  • space-around表示兩頭的項目與容器壁保留一個單位的空隙展辞,項目與項目之間保持兩個單位的空隙。around翻譯成中文是周圍万牺,指的就是每個項目左右兩邊的空隙平均分配罗珍。
  • space-evenly表示兩頭的項目與容器壁之間的空隙和項目與項目之間的空隙都保持一個單位洽腺。evenly翻譯成中文是均勻,指的是所有空隙平均分配覆旱。

align-items

這個屬性聲明每行內的項目如何垂直對齊蘸朋。

.container {
    align-items: stretch(default) | flex-start | flex-end | center | baseline;
}

[圖片上傳失敗...(image-f98076-1578030195249)]

這里有一個問題,如果彈性項目顯式的聲明了高度扣唱,那stretch將不再起作用藕坯。所以這里的例子,我往項目中加了一個子元素画舌,把高度顯式的聲明在子元素上堕担,這樣項目的高度就是被撐開的。

<div class="container">
    <div class="item"><div class="inner">1</div></div>
    <div class="item"><div class="inner">2</div></div>
    <div class="item"><div class="inner">3</div></div>
</div>

可以看到曲聂,默認情況下霹购,行內的彈性項目會拉伸,相當于聲明了高度100%朋腋。一旦項目顯式的聲明了高度齐疙,拉伸就不再起作用了。

align-content

這個屬性將容器的一行視為最小單位旭咽。它聲明的是如果容器的交叉軸方向有富余空間贞奋,每行應該如何垂直對齊。

.container {
    align-content: stretch(default) | flex-start | flex-end | center | space-between | space-around | space-evenly;
}

[圖片上傳失敗...(image-f5dc67-1578030195249)]

這里也一樣穷绵,如果彈性項目顯式的聲明了高度轿塔,那stretch將不再起作用。

同時有兩點需要注意:

  • 彈性容器需要顯式的聲明高度仲墨,而且高度必須高于所有行的高度和勾缭,否則去哪來的富余空間呢?
  • 如果容器內只有一行目养,也就是說不需要換行或者不允許換行俩由,那align-content屬性將無法生效,因為它是作用于行的癌蚁,只有一行也敢叫老子跑一趟幻梯?

為什么沒有justify-items

如果你同時了解display: flexdisplay: grid,也許你會發(fā)現它們都有xx-itemsxx-content屬性努释。但是別急碘梢,再進一步深究,發(fā)現Flexbox少了一個justify-items伐蒂。

我們先來闡述一下xx-itemsxx-content作用范圍有什么區(qū)別痘系。

  • xx-items作用于項目,這意思很明朗饿自。
  • xx-content又是作用于什么呢汰翠?肯定是比項目更大的單位,又聯想Flexbox的align-content是作用于行昭雌,我們可以大膽猜測xx-content作用于行或者列复唤。

點破到這里,大家應該有點眉目了吧烛卧?Flexbox是一維布局模型佛纫,它根本沒有列的概念。

你說不對呀总放,既然Flexbox沒有列的概念呈宇,那不是應該沒有justify-content屬性,而應該有justify-items屬性么局雄?

話是這么說甥啄,我當初也是這么認為的。

但后來仔細想一想炬搭,Flexbox的align-items聲明的是一行內的項目如何垂直對齊蜈漓,與之相對,justify-items聲明的就應該是一列內的項目如何水平對齊宫盔。好像更離譜融虽。而如果將彈性容器一行內的每個項目都當做一列,justify-content似乎就說的通了灼芭。

這就好比討論螃蟹的螯到底是不是手一樣有额,怎么都覺得別扭。只能找一個相對更合理的說法了彼绷。

提出這個問題沒別的意思巍佑,只是想加深大家對Flexbox的理解。

order

從這里開始苛预,涉及到的屬性都是彈性項目自身的屬性句狼。在大的格局確定的情況下,項目之間也是可以有一些騰挪空間的热某。

這個屬性聲明的是彈性項目自身的次序腻菇。只要顯式聲明了不是默認值0的整數,項目顯示的次序將會不同于源代碼定義的次序昔馋。

這個主要是留給JavaScript動態(tài)控制項目的次序用的筹吐,非動態(tài)直接修改源代碼的次序就好了。

.item {
    order: <integer>; /* default is 0 */
}

[圖片上傳失敗...(image-4b42a8-1578030195249)]

flex-grow

這個屬性聲明的是彈性項目是否要瓜分行內的富余空間秘遏,以及如何瓜分丘薛。

屬性值只允許正整數。

.item {
    flex-grow: <number>; /* default is 0 */
}

[圖片上傳失敗...(image-e0dcce-1578030195249)]

首先解釋一下什么是富余空間:它是在彈性容器規(guī)則和彈性項目顯式寬度或者內容的共同約束下邦危,行內剩余的水平空間洋侨。比如圖例中除去margin舍扰、padding的黃色部分。

行內的富余空間是如何被瓜分的呢希坚?

首先边苹,彈性項目要提出申請。比如第一個項目提出flex-grow: 1裁僧,意思是說它想要一份富余空間个束。至于一份富余空間是多少像素,目前還不能確定聊疲。

等所有項目都申請完畢茬底,計算申請的總份數。已知富余空間長度和申請總份數获洲,就能知道一份富余空間是多少像素阱表。

最后根據每人提出申請的份數,分配富余空間。

只有當行內有富余空間時,flex-grow屬性才會生效啸澡。行內空間已經預先被瓜分完甚至不夠時,該屬性就管不了了烂叔。

flex-shrink

這個屬性聲明的是彈性項目是否要瓜分行內的負債空間,以及如何瓜分固歪。

屬性值只允許正整數蒜鸡。

.item {
    flex-shrink: <number>; /* default is 1 */
}

[圖片上傳失敗...(image-fe9fba-1578030195249)]

同樣,解釋一下什么是負債空間:它是在彈性容器規(guī)則和彈性項目顯式寬度或者內容的共同約束下牢裳,行內短缺的水平空間逢防。此時如果不換行的話,就要求擠壓彈性項目的長度蒲讯。

行內的負債空間的瓜分規(guī)則與富余空間的瓜分規(guī)則大致相同忘朝。

首先,彈性項目要提出申請判帮。只不過這時的份額就不再是我要多少局嘁,而是我還多少。

等所有項目都申請完畢晦墙,計算申請的總份數悦昵。

這里的問題在于,計算負債空間的長度稍微比較復雜晌畅。我們在文章一開始探討過彈性項目最小長度的話題但指,這里再次總結一下:

  • 彈性容器只會擠壓彈性項目的content,其余如paddingmarginborder不受影響棋凳。
  • 如果彈性項目內有文本或者固定寬度的子元素拦坠,這又分兩種情況。第一種是項目本身沒有顯式聲明寬度贫橙,則最小長度以子元素的長度為準贪婉;第二種是項目本身顯式聲明了寬度,則最小長度以子元素的長度為準卢肃,但不能超過項目本身的寬度。結合上面圖例中最后兩個例子才顿,更容易理解(我知道你已經懵逼了)莫湘。

最后根據每人提出申請的份數,分配負債空間郑气。就是還債幅垮。

為什么flex-grow屬性的默認值是0,而flex-shrink屬性的默認值是1呢尾组?

因為默認情況下忙芒,如果有富余空間我可以不要的,但是有負債空間又無法換行的話讳侨,我不得不要呵萨。所以flex-shrink屬性的默認值是1,意思就是默認情況下跨跨,如果空間不夠則大家平均的被擠壓潮峦。

你可以將所有項目的flex-shrink屬性值設置為0,如此這般所有項目都鐵骨錚錚勇婴、不畏強權了忱嘹。見上面圖例的第四個例子。

flex-basis

這個屬性聲明的是預先分配給彈性項目的長度耕渴。它是width屬性的替代品拘悦,優(yōu)先級比width高。

.item {
    flex-basis: <length> | auto; /* default is auto */
}

[圖片上傳失敗...(image-b97b99-1578030195249)]

如果widthflex-basis都顯式的聲明了一個非auto的值橱脸,那么flex-basis的優(yōu)先級更高础米。否則,哪個顯式聲明了就以哪個為準慰技。

確實不太清楚制定flex-basis屬性標準的意義何在椭盏。

它們的區(qū)別好像僅限于屬性值為0的情況。width: 0我們都知道表示沒有寬度吻商,見上面圖例的第二個例子掏颊;而flex-basis: 0表示以內容的寬度為寬度,見上面圖例中的第三個例子。

flex

這是一個集合屬性乌叶,可以同時定義flex-grow盆偿、flex-shrinkflex-basis

你可以集合三個屬性的值准浴,也可以只寫flex-grow一個屬性的值事扭。

.item {
    flex: <'flex-grow'> | <'flex-grow'> <'flex-shrink'> <'flex-basis'>;
}

align-self

這個屬性聲明的是彈性項目自身在行內的垂直對齊方式。

“我就是我乐横,是顏色不一樣的煙火”求橄。

.item {
    align-self: auto(default) | stretch | flex-start | flex-end | center | baseline;
}

[圖片上傳失敗...(image-5e2c96-1578030195249)]

除了auto之外,align-self的屬性值和align-items的屬性值是一樣的葡公,效果也一樣罐农。

align-items: auto是說我默認服從集體,不自搞一套催什,所以才會多這么個屬性值涵亏。

為什么有align-self屬性而沒有justify-self屬性呢?

這個問題我們討論過吧蒲凶?因為沒有jusifty-items屬性气筋,所以justify-self屬性也無從談起。

你看人家Grid就有justify-self屬性旋圆。

其他

有一個小游戲 Flexbox Froggy 可以幫助你輕松的實踐Flexbox的各項特性宠默。

轉自github

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市臂聋,隨后出現的幾起案子光稼,更是在濱河造成了極大的恐慌,老刑警劉巖孩等,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件艾君,死亡現場離奇詭異,居然都是意外死亡肄方,警方通過查閱死者的電腦和手機冰垄,發(fā)現死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來权她,“玉大人虹茶,你說我怎么就攤上這事∮缫” “怎么了蝴罪?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長步清。 經常有香客問我要门,道長虏肾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任欢搜,我火速辦了婚禮封豪,結果婚禮上,老公的妹妹穿的比我還像新娘炒瘟。我一直安慰自己吹埠,他們只是感情好,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布疮装。 她就那樣靜靜地躺著缘琅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪廓推。 梳的紋絲不亂的頭發(fā)上胯杭,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音受啥,去河邊找鬼。 笑死鸽心,一個胖子當著我的面吹牛滚局,可吹牛的內容都是我干的。 我是一名探鬼主播顽频,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼藤肢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了糯景?” 一聲冷哼從身側響起嘁圈,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蟀淮,沒想到半個月后最住,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡怠惶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年涨缚,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片策治。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡脓魏,死狀恐怖,靈堂內的尸體忽然破棺而出通惫,到底是詐尸還是另有隱情茂翔,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布履腋,位于F島的核電站珊燎,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜俐末,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一料按、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卓箫,春花似錦载矿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至旅急,卻和暖如春逢勾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背藐吮。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工溺拱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谣辞。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓迫摔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親泥从。 傳聞我的和親對象是個殘疾皇子句占,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內容