轉自:http://zhoon.github.io/css3/2014/08/23/flex.html 感謝他的整理 css
flex爲css的佈局帶來了新的時代,做爲一個重構工程師,咱們不再用侷限於float和position,特別是在移動端,咱們能夠利用flex輕鬆實現以往float和psition很難實現甚至是沒法實現的佈局。 本文主要講解flex的三個子屬性:flex-grow、flex-shrink、flex-basis。他們只是博大精深的flex中的一部分,本文默認你對flex已經有初步的瞭解,若是不瞭解,建議先看看這裏:http://www.w3cplus.com/blog/666.html。html
flex佈局發生在父容器和子容器之間。父容器須要有flex的環境(display:flex;),子容器才能根據自身的屬性來佈局,簡單的說,就是瓜分父容器的空間。相反就是說若是父容器沒有flex的環境,那麼子容器就沒法使用flex的規則來劃分父容器的空間。css3
講到瓜分父容器的空看,那麼首先須要講一個很重要的詞:剩餘空間。git
什麼是剩餘空間呢?具有flex環境的父容器,一般是有一條主軸和一條側軸,默認狀況下主軸就是水平從左向右的,側軸是垂直從上到下的(相似書寫模式)。 剩餘空間就是父容器在主軸的方向上還有多少可用的空間。好比看下面這段html結構:github
container就是父容器,B1 B2 B3就是子容器,假如container的width是500px,那麼剩餘空間就是:500px - B1.width - B2.width - B3.width。嗯就是這麼簡單!瀏覽器
##flex-grow (default:0) 知道了剩餘空間的概念,首先來看一下flex-grow。上面那個例子,咱們假設container的width是500px,如今咱們再假設B一、B二、B3的width是100px,那麼剩餘空間就是500-100*3=200。 知道了剩餘空間有什麼用呢?這個時候flex-grow就該出場了,假如咱們這個時候對B1設置flex-grow:1,那麼咱們會發現,B1把B2和B3都擠到右邊了,也就是說剩餘的200px空間都被B1佔據了,因此此時B1的width比實際設置的值要大。佈局
因此這裏flex-grow的意思已經很明顯了,就是索取父容器的剩餘空間,默認值是0,就是三個子容器都不索取剩餘空間。可是當B1設置爲1的時候,剩餘空間就會被分紅一份,而後都給了B1。 若是此時B2設置了flex-grow:2,那麼說明B2也參與到瓜分剩餘空間中來,而且他是佔據了剩餘空間中的2份,那麼此時父容器就會把剩餘空間分爲3份,而後1份給到B1,2份給到B2,以下面這樣子。flex
##flex-basis (default:auto) 初次見flex-basis這個屬性,還挺疑惑的,不知道它是用來幹嗎的。 後來研究發發現,這個屬性值的做用也就是width的替代品。 若是子容器設置了flex-basis或者width,那麼在分配空間以前,他們會先跟父容器預定這麼多的空間,而後剩下的纔是納入到剩餘空間,而後父容器再把剩餘空間分配給設置了flex-grow的容器。 若是同時設置flex-basis和width,那麼width屬性會被覆蓋,也就是說flex-basis的優先級比width高。有一點須要注意,若是flex-basis和width其中有一個是auto,那麼另一個非auto的屬性優先級會更高。htm
tips:flex-basis和width爲auto值,那最後的空間就是根據內容多少來定的,內容多佔據的水平空間就多。blog
##flex-shrink (default:1) 好了,上面講了這麼多,大家應該都明白了把。 有人會想,不就這樣嘛,很容易啊,不就是剩餘空間的分配嗎?
是的,上面講的都是剩餘空間的分配。可是,你有沒有想過還有沒有其餘的狀況呢?能夠發現,上面講的例子B1 B2 B3的寬度總和都是沒有超過父容器的寬度的。 那若是三個子容器的寬度和超過父容器的寬度呢?那還有剩餘空間能夠分配嗎,此時瀏覽器又是怎麼處理呢?請看下面:
tips:flex環境默認是不換行的,即便父容器寬度不夠也不會,除非設置flex-wrap來換行
此時咱們會發現,B1設置的flex-grow沒有做用,不但沒有獲取到剩餘空間,他的空間甚至是比他定義的300px還要小,並且咱們發現B2和B3的空間也相應的被壓縮了。 那麼這裏的問題就是:一、爲何flex-grow沒有做用,反而被壓縮呢?二、三個容器的壓縮比例是這樣的呢?
這就是這一節的重點了 -> flex-shrink <-
一樣的,三個容器處於flex環境中,因此佈局以前,父容器仍是會計算剩餘空間。 這一次計算的結果是這樣的:剩餘空間=500px - 300px - 160px - 120px = -80px,剩餘空間是一個負數因此很容易理解第一個問題,即便是設置了flex-grow,可是因爲沒有剩餘空間,因此B1分配到的空間是0。
因爲flex環境的父容器的寬度500px是不會變,因此爲了是子容器的寬度和最多爲父容器的寬度,那就只有兩個辦法:第一個是使子容器換行,第二個是壓縮子容器使之恰好撐滿父容器的寬度。 由於flex子容器是默認不換行的,因此這裏不作討論。而第二種壓縮,實際上就是上面例子表現出來的樣式。如今就遇到了上面第二個問題,這三個的壓縮比例是多少呢,各自須要壓縮的空間是多少呢?
這個時候就須要談談flex-shrink,這個屬性其實就是定義一個子容器的壓縮比例。他的默認值是1,因此上面那個例子,就是三個子容器壓縮的比例是同樣的 1:1:1。 若是此時咱們設置B1的壓縮比例是2,那會怎樣呢?
咱們能夠發現,B1被壓縮的更多了。而B2和B3獲得了跟多的空間。那咱們怎麼得出他們各自的壓縮率呢?咱們假設B2 B3的壓縮率是X1,那麼B1的壓縮率就是X2了,那就有了以下方程:
X2 = 2 * X1; 500 = 300 * X2 + 160 * X1 + 120 * X1;
經過上面咱們就能夠解出X1和X2等於多少了,這樣就能夠計算出壓縮率和被壓縮了多少空間了。
##總結 經過上面的分析,咱們就能夠得出這樣幾個結論:
一、剩餘空間=父容器空間-子容器1.flex-basis/width - 子容器2.flex-basis/width - …二、若是父容器空間不夠,就走壓縮flex-shrink,不然走擴張flex-grow;三、若是你不但願某個容器在任什麼時候候都不被壓縮,那設置flex-shrink:0;四、若是子容器的的flex-basis設置爲0(width也能夠,不過flex-basis更符合語義),那麼計算剩餘空間的時候將不會爲子容器預留空間。五、若是子容器的的flex-basis設置爲auto(width也能夠,不過flex-basis更符合語義),那麼計算剩餘空間的時候將會根據子容器內容的多少來預留空間。