[譯] 讀完 flexbox 細則以後學到的 11 件事

讀完 flexbox 細則以後學到的 11 件事

在經歷了多年的浮動佈局和清除浮動的折磨以後,flexbox 就像新鮮空氣通常,使用起來是如此的簡單方便。javascript

然而最近我發現了一些問題。當我認爲它不該該是彈性的時候它倒是彈性的。修復了以後,別的地方又出問題了。再次修復以後,一些元素又被推到了屏幕的最右邊。這究竟是什麼狀況?css

固然了,最後我把它們都解決了,可是黃花菜都涼了並且個人處理方式也基本上沒什麼規範,就好像那個砸地鼠的遊戲,當你砸一個地鼠的時候,另外一個地鼠又冒出來,很煩。前端

無論怎麼說,我發現要成爲一個成熟的開發者而且真正地學會 flexbox 是須要花時間的。可是不是再去翻閱另外的 10 篇博客,而是決定直接去追尋它的源頭,那就是閱讀 The CSS Flexible Box Layout Module Level 1 Specjava

下面這些就是個人收穫。react

1. Margins 有特別的功能

我過去經常想,若是你想要一個 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-reversecolumncolumn-reverse 也都是適用的。

2. min-width 問題

你或許會想必定有一個直截了當的方法確保在一個容器中全部的 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 寬的問題。

3. flexbox 做者的水晶球

就像你知道的,flex 屬性實際上是 flex-growflex-shrinkflex-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能夠更清楚地表示代碼的語義。這對於那些忘記這些代碼是如何工做的人來講就友好多了。 )

4. inline-flex

坦白講,幾個月前我才知道 display: inline-flex 這個屬性。它會代替塊容器建立一個內聯的 flex 容器。

可是我估計有 28% 的人還不知道這件事,因此如今你就不是那 28% 了。

5. vertical-align 不會對 flex 條目起做用

或者這件事我並非徹底的懂,可是從某種意義上我能夠肯定,當使用 vertical-align: middle 來嘗試對齊的時候,它並不會起做用。

如今我知道了,細則裏面直接寫了,vertical-align 在 flex 條目上不起做用」 (注意:就好像 float 同樣)。

6. margins 和 padding 不要使用 %

這並不只僅是一個最佳實踐,它相似於外婆說的話,去遵照就行了,不要問爲何。

"開發者們在 flex 條目上使用 paddings 和 margins 時,應該避免使用百分比" — 愛你的,flexbox 細則。

下面是我在細則裏面看到的最喜歡的一段話。

註解:這個變化糟透了,可是它精準地抓住了世界的當前狀態(實現無定法,CSS 無定則)

小心,糖衣炮彈進行中。

7. 相鄰的 flex 條目的邊緣不會塌陷

你或許知道有時候會出現相鄰條目的邊緣塌陷。你或許也知道其餘的時候不會出現邊緣塌陷。

如今咱們都知道相鄰的 flex 條目是不會發生邊緣塌陷的。

8. 即便 position: static,z-index 也會有效

我不肯定我是否真的在意這一點。可是我想到或許有一天,它就會真地有用。就好像我冰箱裏有一瓶檸檬汁。

某一天我家來了其餘人,而後他會問:"嗨,你這裏有檸檬汁嗎?",我這時就會告訴他:"有的,就在冰箱裏",他會接着說:"謝謝,大兄弟。那麼若是我想給一個 flex 條目設置 z-index,我須要指定 position 嗎?",我會說:"兄弟,不須要,flex 條目不須要這樣。"

9. Flex-basis 是精細且重要的

一旦 initialautonone 都不能知足你的需求時,事情就有點複雜了,可是咱們 flex-basis,有趣的是,你知道的,我不知道怎麼結束這句話。若是大家有好的建議的話,歡迎留言。

若是你有 3 個 flex 條目,它們的 flex 值分別爲 3,3 和 4。那麼當 flex-basis0 的話它們就會忽略他們的內容,佔據可用空間的 30%,30%,40%。

然而,若是你想要 flex 更友好可是有點不太可預測的話,使用 flex-basis: auto。這個會將你的 flex 的值設置得更合理,同時也會考慮到一些其餘因素,而後爲你給出相對合理的寬度。

看看這個很棒的示意圖。

我十分肯定我讀到的關於 flex 的博客中至少有一篇提到了這一點,可是我也不知道爲何,直到我看到上面這張圖纔想起來。

10. align-items: baseline

若是我想讓個人 flex 條目垂直對齊,我老是使用 align-items: center。可是就像 vertical-align同樣,這樣當你的條目有不一樣的字體大小而且你但願它們基於 baselines 對齊的時,你須要設置 baseline 才能對齊的更完美。

align-self: baseline 也能夠,或許更直觀。

11. 我很蠢

下面這段話不論我讀幾遍,都沒法理解它的含義...

在主軸上內容大小是最小內容大小的尺寸,而且是加緊的,若是它有一個寬高比,那麼任何定義的 min 和 max 的大小屬性都會經過寬高比轉換,而且若是主軸的 max 尺寸是肯定的話會進一步加緊。

這些單詞經過個人眼睛被轉化成電信號穿過個人視神經,剛剛抵達的時候就看到個人大腦打開後門一溜煙跑了。

就像米老鼠和瘋狂麥克斯 7 年前生了個孩子,如今和薄荷酒喝醉了,使用他從爸爸媽媽吵架時學到的語言肆意的辱罵周圍的人。

女士們,先生們,我已經放棄了體面開始胡言亂語了,這意味着你能夠關閉這篇文章了(若是你看這個是爲了學習的話你能夠在這裏中止了)。

讀這篇細則我學到的最有趣的事情是,儘管我看過大量的博文,以及 flexbox 也算是相對簡單的知識點,可是我對其的瞭解曾是那麼的不完全。事實證實 '經驗' 不老是起做用的。

我能夠很開心的說花時間來閱讀這些細則已經獲得了回報。我已經優化的個人代碼,設置了 auto margins,flex 的值也設置成了 auto 或者 none,並在須要的地方定義了 min-width 爲 0。

如今這些代碼看起來好多了,由於我知道這樣作是正確的。

個人另一個收穫就是,儘管這些細則在某些方面正如我所想的基於編者視角並有些龐雜,可是仍然有有不少友好的說明和例子。甚至還高亮了那些初級開發者容易忽略的部分。

然而,這個是多餘的,由於我已經告訴了你全部有用知識點,你就不用再本身去閱讀了。

如今,若是大家要求,那麼我會再去閱讀全部其餘的 CSS 細則。

PS:我強烈建議讀讀這個,一個瀏覽器 flexbox bugs 的清單:github.com/philipwalto….


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOSReact前端後端產品設計 等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃

相關文章
相關標籤/搜索