- 原文地址:11 things I learned reading the flexbox spec
- 原文做者:David Gilbertson
- 譯文出自:掘金翻譯計劃
- 譯者:XatMassacrE
- 校對者:zaraguo,reid3290
在經歷了多年的浮動佈局和清除浮動的折磨以後,flexbox 就像新鮮空氣通常,使用起來是如此的簡單方便。javascript
然而最近我發現了一些問題。當我認爲它不該該是彈性的時候它倒是彈性的。修復了以後,別的地方又出問題了。再次修復以後,一些元素又被推到了屏幕的最右邊。這究竟是什麼狀況?css
固然了,最後我把它們都解決了,可是黃花菜都涼了並且個人處理方式也基本上沒什麼規範,就好像那個砸地鼠的遊戲,當你砸一個地鼠的時候,另外一個地鼠又冒出來,很煩。前端
無論怎麼說,我發現要成爲一個成熟的開發者而且真正地學會 flexbox 是須要花時間的。可是不是再去翻閱另外的 10 篇博客,而是決定直接去追尋它的源頭,那就是閱讀 The CSS Flexible Box Layout Module Level 1 Spec。java
下面這些就是個人收穫。react
我過去經常想,若是你想要一個 logo 和 title 在左邊,sign in 按鈕在右邊的 header ...android
點線爲了更清晰ios
... 那麼你應該給 title 的 flex 屬性設置爲 1 就能夠把其餘的條目推到兩頭了。git
.header {
display: flex;
}
.header .logo {
/* nothing needed! */
}
.header .title {
flex: 1;
}
.header .sign-in {
/* nothing needed! */
}複製代碼
這就是爲何說 flexbox 是個好東西了。看看代碼,多簡單啊。github
可是,從某種角度講,你並不想僅僅爲了把一個元素推到右邊就拉伸其餘的元素。它有多是一個有下劃線的盒子,一張圖片或者是由於其餘的什麼元素須要這樣作。數據庫
好消息!你能夠不用說「把這麼條目推到右邊去」而是更直接地給那個條目定義 margin-left: auto
,就像 float: right
。
舉個例子,若是左邊的條目是一張圖片:
我不須要給圖片使用任何的 flex,也不須要給 flex 容器設置 space-between
,只須要給 'Sign in' 按鈕設置 margin-left: auto
就能夠了。
.header {
display: flex;
}
.header .logo {
/* nothing needed! */
}
.header .sign-in {
margin-left: auto;
}複製代碼
你或許會想這有一點鑽空子,可是並非,在 概述 裏面這個方法就是用來將一個 flex 條目推到 flexbox 的末端的。它甚至還有本身單獨的章節,使用 auto margins 對齊。
哦對了,我應該在這裏添加一個說明,在這篇博客中我會假設全部的地方都設置了 flex-direction: row
。可是對於 row-reverse
,column
和 column-reverse
也都是適用的。
你或許會想必定有一個直截了當的方法確保在一個容器中全部的 flex 條目都適應地收縮。固然了,若是你給全部的條目設置 flex-shrink: 1
,這不就是它的做用嗎?
仍是舉例說吧。
假設你有不少的 DOM 元素來顯示出售的書籍而且有個按鈕來購買它。
(劇透:蝴蝶最後死了)
你已經用 flexbox 安排地很好了。
.book {
display: flex;
}
.book .description {
font-size: 30px;
}
.book .buy {
margin-left: auto;
width: 80px;
text-align: center;
align-self: center;
}複製代碼
(你想讓 'Buy now' 按鈕在右邊,即便是很短的標題的時候,那麼你就要給他設置 margin-left: auto
。)
這個標題太長了,因此他佔用了儘量多的空間,而後換到了下一行。你很開心,生活真美好。你洋洋得意地將代碼發佈到生產環境而且自信地認爲沒有任何問題。
而後你就會獲得一個驚喜,但不是好的那種。
一些自命不凡的做者在標題中用了一個很長的單詞。
那就完了!
若是那個紅色的邊框表明手機的寬度,而且你隱藏了溢出,那麼你就失去你的 'Buy now' 按鈕。你的轉換率,可憐的做者的自我感受都會遭殃。
(注:幸運的是我工做的地方有一個很棒的 QA 團隊,他們維護了一個擁有各類相似於這樣的使人不爽的文本的數據庫。也正是這個問題特別的促使我去閱讀這些細則。)
就像圖片展現的那樣,這樣的表現是由於描述條目的 min-width
初始被設置爲 auto
,在這種狀況下就至關於 Electroencephalographically 這個單詞的寬度。這個 flex 條目就如它的字面意思同樣不容許被任何的壓縮。
那麼解決辦法是什麼呢?重寫這個有問題的屬性,將 min-width: auto
改成 min-width: 0
,給 flexbox 指明瞭對於這個條目能夠比它裏面的內容更窄。
這樣就能夠在條目裏面處理文本了。我建議包裹單詞。那麼你的 CSS 代碼就會是下面這個樣子:
.book {
display: flex;
}
.book .description {
font-size: 30px;
min-width: 0;
word-wrap: break-word;
}
.book .buy {
margin-left: auto;
width: 80px;
text-align: center;
align-self: center;
}複製代碼
這樣的結果就是這個樣子:
重申一下,min-width: 0
不是什麼爲了特定結果取巧的技術,它是細則中建議的行爲 。
下個章節我會處理儘管我明確寫明瞭可是 ‘Buy now’ 按鈕仍然不老是 80px 寬的問題。
就像你知道的,flex
屬性實際上是 flex-grow
,flex-shrink
和 flex-basis
的簡寫。
我必須認可爲了達到我想要的效果,我在不停地嘗試和驗證這三個屬性上面花費了不少時間。
可是直到如今我才明白,我其實只是須要這三者的一個組合。
flex: 0 1 auto
flex: 1 1 auto
flex: 0 0 auto
我但願你還不是很驚奇,由於還有讓你更驚奇的。
你看,Flexbox Crew (我一般認爲 flexbox 團隊的皮衣是男女都能穿的尺寸)。對,Flexbox Crew 知道我用得最多的就是這三個屬性的組合,因此他們給予了這些組合 對應的關鍵字。
第一個場景是 initial
的值,因此並不須要關鍵字。flex: auto
適用於第二種場景,flex: none
是條目不伸縮的最簡單的解決辦法。
早就該想到它了。
它就好像用 box-shadow: garish
來默認表示 2px 2px 4px hotpink
,由於它被認爲是一個 ‘有用的默認值’。
讓咱們再回到以前那個醜陋的圖書的例子。讓咱們的 'Buy now' 按鈕更胖一點...
... 我只要設置 flex: none
:
.book {
display: flex;
}
.book .description {
font-size: 30px;
min-width: 0;
word-wrap: break-word;
}
.book .buy {
margin-left: auto;
flex: none;
width: 80px;
text-align: center;
align-self: center;
}複製代碼
(是的,我能夠設置 flex: 0 0 80px;
來節省一行 CSS。可是設置爲 flex: none
能夠更清楚地表示代碼的語義。這對於那些忘記這些代碼是如何工做的人來講就友好多了。 )
坦白講,幾個月前我才知道 display: inline-flex
這個屬性。它會代替塊容器建立一個內聯的 flex 容器。
可是我估計有 28% 的人還不知道這件事,因此如今你就不是那 28% 了。
或者這件事我並非徹底的懂,可是從某種意義上我能夠肯定,當使用 vertical-align: middle
來嘗試對齊的時候,它並不會起做用。
如今我知道了,細則裏面直接寫了,vertical-align 在 flex 條目上不起做用」 (注意:就好像 float
同樣)。
這並不只僅是一個最佳實踐,它相似於外婆說的話,去遵照就行了,不要問爲何。
"開發者們在 flex 條目上使用 paddings 和 margins 時,應該避免使用百分比" — 愛你的,flexbox 細則。
下面是我在細則裏面看到的最喜歡的一段話。
註解:這個變化糟透了,可是它精準地抓住了世界的當前狀態(實現無定法,CSS 無定則)
小心,糖衣炮彈進行中。
你或許知道有時候會出現相鄰條目的邊緣塌陷。你或許也知道其餘的時候不會出現邊緣塌陷。
如今咱們都知道相鄰的 flex 條目是不會發生邊緣塌陷的。
我不肯定我是否真的在意這一點。可是我想到或許有一天,它就會真地有用。就好像我冰箱裏有一瓶檸檬汁。
某一天我家來了其餘人,而後他會問:"嗨,你這裏有檸檬汁嗎?",我這時就會告訴他:"有的,就在冰箱裏",他會接着說:"謝謝,大兄弟。那麼若是我想給一個 flex 條目設置 z-index,我須要指定 position 嗎?",我會說:"兄弟,不須要,flex 條目不須要這樣。"
一旦 initial
,auto
和 none
都不能知足你的需求時,事情就有點複雜了,可是咱們有 flex-basis
,有趣的是,你知道的,我不知道怎麼結束這句話。若是大家有好的建議的話,歡迎留言。
若是你有 3 個 flex 條目,它們的 flex 值分別爲 3,3 和 4。那麼當 flex-basis
爲 0
的話它們就會忽略他們的內容,佔據可用空間的 30%,30%,40%。
然而,若是你想要 flex 更友好可是有點不太可預測的話,使用 flex-basis: auto
。這個會將你的 flex 的值設置得更合理,同時也會考慮到一些其餘因素,而後爲你給出相對合理的寬度。
看看這個很棒的示意圖。
我十分肯定我讀到的關於 flex 的博客中至少有一篇提到了這一點,可是我也不知道爲何,直到我看到上面這張圖纔想起來。
若是我想讓個人 flex 條目垂直對齊,我老是使用 align-items: center
。可是就像 vertical-align
同樣,這樣當你的條目有不一樣的字體大小而且你但願它們基於 baselines 對齊的時,你須要設置 baseline
才能對齊的更完美。
align-self: baseline
也能夠,或許更直觀。
下面這段話不論我讀幾遍,都沒法理解它的含義...
在主軸上內容大小是最小內容大小的尺寸,而且是加緊的,若是它有一個寬高比,那麼任何定義的 min 和 max 的大小屬性都會經過寬高比轉換,而且若是主軸的 max 尺寸是肯定的話會進一步加緊。
這些單詞經過個人眼睛被轉化成電信號穿過個人視神經,剛剛抵達的時候就看到個人大腦打開後門一溜煙跑了。
就像米老鼠和瘋狂麥克斯 7 年前生了個孩子,如今和薄荷酒喝醉了,使用他從爸爸媽媽吵架時學到的語言肆意的辱罵周圍的人。
女士們,先生們,我已經放棄了體面開始胡言亂語了,這意味着你能夠關閉這篇文章了(若是你看這個是爲了學習的話你能夠在這裏中止了)。
讀這篇細則我學到的最有趣的事情是,儘管我看過大量的博文,以及 flexbox 也算是相對簡單的知識點,可是我對其的瞭解曾是那麼的不完全。事實證實 '經驗' 不老是起做用的。
我能夠很開心的說花時間來閱讀這些細則已經獲得了回報。我已經優化的個人代碼,設置了 auto margins,flex 的值也設置成了 auto 或者 none,並在須要的地方定義了 min-width 爲 0。
如今這些代碼看起來好多了,由於我知道這樣作是正確的。
個人另一個收穫就是,儘管這些細則在某些方面正如我所想的基於編者視角並有些龐雜,可是仍然有有不少友好的說明和例子。甚至還高亮了那些初級開發者容易忽略的部分。
然而,這個是多餘的,由於我已經告訴了你全部有用知識點,你就不用再本身去閱讀了。
如今,若是大家要求,那麼我會再去閱讀全部其餘的 CSS 細則。
PS:我強烈建議讀讀這個,一個瀏覽器 flexbox bugs 的清單:github.com/philipwalto….
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、React、前端、後端、產品、設計 等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃。