在設計的眼中,排版的操做是一件很簡單的事情,靠左、置中、靠右,我只要點一下,全部元素,就會乖乖的到指定的位置。前端
但到了前端在排版的實現上,就不是這樣了。git
咱們經常得用一堆其實原本不是這樣用的屬性來作 hack,好比說用 line-height 來作垂直置中,這樣作的確能達到效果,可是在語意上就有點不順,拿剛剛提到的 line-height 來講,這原本是用來看成段落中的行距,但卻由於這個屬性能擴展文字的上下空間,結果也被拿來作垂直置中。那有沒有一個方法能用來更好地實現 Web 佈局呢?ruby
這是 Google 的 Angular。他們幾個月前作了一套 UI 來實如今 Angular 上的 Material Design。這套框架用來實現佈局的方式,不是以往的 float,而是用了 Flexbox。框架
Flexbox 是什麼呢?就 W3C 官方給到的解釋是,這是設計來實現更復雜的版面佈局。那我本身對他的定義是,Flexbox 從本質上就是一個 Box-model 的延伸,咱們都知道 Box-model 定義了一個元素的盒模型,然而 Flexbox 更進一步的去規範了這些盒模型之間彼此的相對關係。而不須要去用一些很 cheat 的作法,去 hack 一些原本其實不該該用來作版面佈局的屬性。ide
身爲一個喜歡去玩一些新東西的前端,應該說每一個跟互聯網有所接觸的人,都須要去學新東西。佈局
這是我碰到新東西的時候,必定會問本身的三個問題:
1. 這能作什麼?也就是他能解決什麼問題?
2. 能用在哪裡?在哪些地方能用這個方法?
3. 爲何能用?他實現所用到的邏輯是什麼?性能
接下來就跟你們分享一下,當初看到 Flexbox 的我問了本身這個三個問題以後,到目前爲止我找到的答案。flex
舉一個例子,全部前端都會有的痛點,置中,咱們之前是怎麼實現的?網站
最常看到就是用絕對定位,而後把 top 和 left 偏移 五零%,在用 margin 偏移回去。可是這隻適用在已經固定大小的元素。ui
最近幾年常看到的作法是這樣,在想置中的元素以前,加上一個元素,不想管太舊的 IE 的話,甚至僞元素也能夠。在容器用 text-align,而後把底下的兩個元素弄成 inline 的形式,在用 vertical-align。他的好處就是,即便底下的元素會隨內容改變大小,但無論怎麼改變,就是能夠始終維持垂直和水平置中。
固然啦,還有不少置中的方法,就不一一介紹了,咱們來看一下用 flex 的話怎麼置中。
用 Flex 來作置中的話,你能夠很從容地作到置中,不用一堆即便原本不是這樣用的屬性。我只要先指定容器爲一個 Flex 容器,而後 justify-content 讓他水平方向置中,再 align-items 讓他垂直方向置中。我能夠很簡單很優雅的就作到置中。
那也許你會說,欸?既然一個能夠的話,那我再多放幾個可不能夠?其實能夠的。
假設咱們如今容器底下有三個元素,喔,這裡就要提到 Flexbox 另一個屌炸天的功能。
假設一個元素是四零%,另外一個是一二%,那在一個 Flex 容器中,只要你有設定 flex-grow 這項屬性的話,他的第三個元素就會自適應寬度,填滿剩下容器的空白。而在多個元素的狀態之下,咱們仍然能很輕易的就置中。
剛剛咱們提到過,flexbox 是用來規範盒模型之間的相對關係,從這裡你就能夠看到。如今我將 justify-content 設成 space-around,元素就會變成已分散對齊的方式去分佈在 flex 容器中。
關於元素的分步,咱們再來看幾個例子。
這是一個我最近看到的網站。咱們能夠看到他底下有一個 Slider,這有個問題,並且也經常是前端在版面上的一個痛點,咱們想讓全部的子元素可以等高。在之前咱們很難只用 CSS 去作到這樣。
而 flexbox 能夠很輕易地只用 CSS 作到這點。只須要在 flex 容器加上 align-items 就好。就能實現容器底下的全部元素,與最高的那個元素等高。
即便我在原本最高的那個元素多加一些內容,其餘的元素也必定會維持等高。
Flex 最初被 W3C 於 09 年制定出來,隨後就被大量的討論。拿指定元素爲一個 flex 容器來說,第一個版本裡是 display:box,第二個版本是 display: flexbox,第三個版本是 display: flex。實在太複雜,還好如今在開源的世界裏已經有大大把這三個版本的 flex 作成一些 mixin,使用的時候,你只要 include 進來就能夠。
就跟 IE 的使用體驗同樣,全部的好東西跟 IE 基本都沾不上邊,因此若是你須要考慮 IE 用戶,那請慎入。因此有人說 IE 的功能只剩下用來下載 Chrome 和 Firefox。
若是你到網上搜 flex,大多都會著墨在 他的對齊、他的控制 DOM 順序是如何如何好用。但今天咱們想聊一聊更深一點的東西,flex item 寬度的計算,大多數狀況下,咱們只在乎顯示的比例,這也是寬度的計算比較少被討論的緣由,但若是你想要更精確的控制 item 的顯示寬度,其實你是須要去了解,在一個 flex 容器當中,item 的寬度是如何被計算出來的。
當咱們把一個容器指定爲 flex 容器時,它裡面的 item 實際上是有著這樣的設定:flex: 0 1 auto
這三個數字其實分別表明:flex-grow、flex-shrink、flex-basis,這三個屬性能夠說是 flex 之因此智能的緣由。
咱們先來聊聊 flex-basis 好了,這個屬性在 flex 容器爲橫向的時候,其實就是寬度,當咱們把 item 指定成 flex: 0 0 480px 時,其實就是把它的寬度設定成 480px。可是這樣並不能表現出 flex 有什麼特別的地方啊?爲什麼要重複設定寬度?
這時候就要講到另外兩個屬性:flex-grow、flex-shrink
這兩個屬性實際上是雙胞胎,grow 表示在 item 總寬度比容器小的時候,爲了讓 item 填滿容器,每一個 item 增長的寬度。假設有三個 basis 爲 100px 的 item。咱們從左到右給予 grow 值分別爲 三、二、1,那麼當 flex 做用以後,最左邊的 item 實際增長的寬度是多少?從圖中能夠算到增長的寬度是 90px,因而最後最左邊 item 的寬度是 190px。
咱們剛纔提到 grow 跟 shrink 實際上是雙胞胎,其實他們真的很像,shrink 表示在 item 總寬度比容器大的時候,爲了讓 item 填滿容器,每一個 item 減小的寬度。可是計算的公式倒是不同的。爲何?由於當你在加的時候無所謂,可是在減的時候,若是隻計算賦予的 shrink 值,那麼頗有可能最後減小的寬度比 basis 大,因而 item 的寬度就變成負值。那咱們該怎麼修正?把 basis 當成參數計算進去,這樣就能保證減小的寬度永遠小於 basis。因此咱們能夠獲得修正後的公式,同樣以最左邊爲例子,最後計算出來減小 60px,因而 item 就變成 140px。以上腦子很差使,不要緊,實際上最經常使用的只是 flex: 1。
講到這裏,你剛剛講的好像這東西很厲害的樣子,那你有沒有一個最快最簡單粗暴的方式去說 Flexbox 真的是個好東西?
嗯⋯⋯有點難,不過我想應該能夠。
參考:https://ruby-china.org/topics/23767