2019/5/7號二次更新:爲摺疊的flex item的例子增添了codePen連接。
2019/5/7號更新:補充了總體結構,若有疑問,歡迎留言。
css
總想寫flex,卻一直拖——拖——拖,今天算是寫完了。與以往的文章不一樣,這篇文章更像是寫給本身看的,因此有些術語不會再解釋,如看不懂,能夠先去這篇文章裏看看術語.
html
咱們先看這個例子瀏覽器
div.parent {
display: flex;
width: 1000px;
height:400px;
border: solid 2px rgba(75, 234, 12, 0.7);
border-radius: 8px;
}
div.parent > div {
border-radius: 8px;
flex: 1 1 auto;
color: #fff;
text-align: center;
line-height: 200px;
font-size: 26px;
}
div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
}
div.second-child {
width: 400px;
height: 200px;
background-color: rgb(255, 141, 75);
}
複製代碼
<div class="parent">
<div class="first-child">first-child</div>
<div class="second-child">second-child</div>
</div>
複製代碼
效果以下:網絡
上面的父級box是個flex container, 有兩個flex item(div.first-child和div.second-child)。 dom
flex direction默認爲row,那麼橫座標軸稱做main axis,flex container(flex item)在main axis方向的尺寸(即寬度)稱做flex container(flex item)的main size, flex container的main size方向的起點叫main start,終點叫main end。post
縱座標軸稱做cross axis,,flex container(flex item)在cross axis方向的尺寸(即高度)稱做flex container(flex item)的cross size。flex container的cross size方向的起點叫cross start, 終點叫cross end。性能
在flex container裏,flex item 會沿着main start依次排列,直至排到main end。接着換行,從cross satrt 開始往cross end方向排列。 字體
總體結構就大體如上,接下來會逐一講解flex container,flex item,以及它們之間的渲染原理。flex
display爲flex的元素會產生一個flex container,該container在正常流內以block-level的形式存在。ui
display爲inline-flex的元素會產生一個flex container,該container在正常流內以inline-level的形式存在。
每一個flex container都會爲它的內容創建一個flex formatting context,這與block container爲它的內容創建一個block formatting context很相似。可是,flex container並非block container, 諸如:
float和clear在flex container裏面無效(也就是flex item即便設置了float和clear也不起做用)
vertical-align在flex item上也不起做用
flex container的margin不會與它的內容的margin重疊
::first-line和::first-letter僞元素在flex container上不起做用
Specified value | Computed value |
---|---|
inline-table | table |
inline, table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, table-caption, inline-block | block |
inline-flex | flex |
others | same as specified |
簡單的說,flex container的每一個孩子都是一個flex item,而每一個flex item都是一個flex-level box,另外,因爲在計算computed value時flex item會發生塊級化,所以每一個flex item也是一個block container。而對於沒有html元素包裹的連續文字,會被自動包裹在一個匿名的block container flex item裏。
釋1: 塊級化 —— 儘管有的flex item的display屬性值爲inline,可是在計算computed value時,也會被設爲block.
釋2: block container ——該box只能包含block-level box或是創建一個inline formatting context且只能包含inline-level box
由於爲絕對定位元素,因此該flex item會脫離流。效果就如同該flex item的static position box(在計算絕對定位元素位置時,會先假設它的position爲static,處於正常流中,而後得出一個static position,再依據這個static position去定位。)爲flex container的content box。也就是該flex container裏面只有該flex item的static position box,這個flex container是個匿名的flex container。
例:爲div.first-child加上絕對定位。div.first-child改成:
div.first-child {
Width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
position: absolute;
}
複製代碼
效果以下:
選中div.second-child能夠看到,它的寬度獨佔1000px。 若是給絕對定位flex item加上align-self: center,它會處於它所在的flex container的交叉軸的中心位置。修改div.first-child以下:div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
position: absolute;
align-self: center;
}
複製代碼
效果以下:
而一旦爲絕對定位flex item設置了top/bottom,它就會參照第一個父級定位元素去移動,align-self也就失效了。如今設置div.parent爲相對定位元素,修改爲:div.parent {
display: flex;
Width: 1000px;
height:400px;
border: solid 2px rgba(75, 234, 12, 0.7);
border-radius: 8px;
position:relative;
}
複製代碼
爲div.first-child設置偏移量,修改以下:
div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
position: absolute;
align-self: center;
left: 50px;
top: 50px;
}
複製代碼
效果以下:
對比上圖,能夠看到交叉軸上div.first-child距離div.parent的上邊緣只有上圖的一半,也就是50px,同時div.first-child距離div.parent的左邊緣也是50px。div.parent {
display: flex;
flex-wrap: wrap;
width: 400px;
height: auto;
background-color: rgba(15, 241, 170, 0.42);
border-radius: 8px;
margin-top: 50px;
}
div.parent > div {
border-radius: 8px;
flex: 1 1 auto;
color: #fff;
text-align: center;
line-height: 200px;
font-size: 26px;
}
div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
margin-top: 50px;
margin-bottom: 50px;
}
div.second-child {
width: 400px;
height: 200px;
background-color: rgb(255, 141, 75);
margin-top: 50px;
}
複製代碼
效果以下:
能夠看到div.parent距離root box的上邊緣有50px,而div.first-child的上邊緣距離div.parent的上邊緣也有50px,他們並無重疊。div.first-child及div.second-child的margin-top也沒有重疊。
若是div.parent的display爲block,而且div.parent及div.first-child的border寬度均爲0,它和div.first-child的margin-top會發生重疊。修改div.parent以下:
div.parent {
display: block;
width: 400px;
height: auto;
background-color: rgba(15, 241, 170, 0.42);
border-radius: 8px;
margin-top: 50px;
}
複製代碼
效果以下:
鼠標定位到div.parent上,能夠看到它的margin-top和div.first-child的margin-top確實重疊了。同理,div.first-child與div.second-child的margin-top也重疊了。例子:
div.collapse-example {
display: flex;
> ul.nav {
height: auto;
margin: 0;
margin-right: 20px;
> li {
margin-bottom: 5px;
border-radius: 4px;
text-align: center;
font-size: 18px;
display: flex;
flex-flow: column;
}
> li:target,
> li:hover {
cursor: pointer;
> a {
border-top-left-radius: 8px;
border-top-right-radius: 8px;
font-weight: bold;
}
> ul {
border-radius: 8px;
}
a {
color: #343434 !important;
}
}
> li:not(:target):not(:hover) > ul {
height: 0;
overflow: hidden;
visibility: collapse;
}
}
ul {
padding: 0 10px;
> li {
list-style: none;
}
}
}
複製代碼
<div class="collapse-example">
<ul class="nav">
<li>
<a href="#">About</a>
<ul>
<li>
<a href="#">introduction</a>
</li>
<li>
<a href="#">blog</a>
</li>
</ul>
</li>
<li>
<a href="#">Product</a>
<ul>
<li>
<a href="#">book</a>
</li>
<li>
<a href="#">beautiful-closes</a>
</li>
</ul>
</li>
<li>
<a href="#">Contact</a>
<ul>
<li>
<a href="#">email</a>
</li>
<li>
<a href="#">weixin</a>
</li>
</ul>
</li>
</ul>
<article id="main">
This is an Example
</article>
</div>
複製代碼
效果以下:
鼠標移到菜單上,子菜單會顯示出來。( 點擊連接看看)min-width和min-height有了一個新的初始化值,即auto,表示自動設置的min size。
對於flex item,當min-width或min-height的specified value設置爲auto,相應的used value是基於內容來設置的。這個值怎麼定呢?
對於min-width,通常,取主軸上width的specified value與主軸上min-content size(一個box的最小size,該size不會致使overflow)的較小值; 若是主軸上width沒有specified value, 可是有個ratio且交叉軸上width設置了specified value,則根據ratio及交叉軸width的specified value得出一個轉換後的size,再取這個size和主軸上min-content size的較小值;若是既沒有設定主軸width的specified value有沒有ratio,那麼直接取主軸上min-content size。
同理min-height。
一般,automatic minimum size取值合理,可是若是是如下狀況,仍是爲min size設置一個具體的值比較好。
aspect ratio | padding-top value |
---|---|
1:1 | 100% |
16:9 | 56.25% |
4:3 | 75% |
3:2 | 66.66% |
8:5 | 62.5% |
flex container的內容能夠按照必定的方向和順序排列。主要依靠flex container的flex-direction和flex-wrap以及flex item的order。
可是有點需切記,不可依靠flex-direction/flex-wrap 的-reverse值 以及order來代替flex item的本來順序,會影響頁面的可訪問性。
Name: flex-direction
Value: row | row-reverse | column | column-reverse
Initial: row
Applies to: flex containers
Inherited: no
Percentages: n/a
Name: flex-wrap
Value: nowrap | wrap | wrap-reverse
Initial: nowrap
Applies to: flex containers
Inherited: no
Percentages: n/a
flex: nowrap表示flex container爲單行,內容大小超出則調整flex item的大小以避免溢出。
flex: wrap 表示在內容過多時flex container會換行
flex: wrap-reverse 表示在內容過多時flex container會換行,但cross-start及cross-end方向調換。
Name: order
Value:
Initial: 0
Applies to: flex items
Inherited: no
Percentages: n/a
order能夠設置flex item的位置。 這些flex item會在文檔順序的基礎上再基於order屬性值進行再排序,而後按照再排序的結果渲染出來。若是某些flex item的order值相同,則按照它們在文檔裏的順序渲染。
例子:div.parent {
display: flex;
width: 400px;
height: auto;
border: solid 2px rgba(15, 241, 170, 0.42);
border-radius: 8px;
}
div.parent > div {
border-radius: 8px;
flex: 1 1 auto;
color: #fff;
text-align: center;
line-height: 200px;
font-size: 26px;
}
div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
}
div.second-child {
width: 400px;
height: 200px;
background-color: rgb(255, 141, 75);
order: -1;
}
複製代碼
效果以下:
當一個flex line還有多餘的空間可擴展,這些空間如何分配給該行的flex item呢?用flex-grow, 它用來設置某個flex item可擴展多少比例的多餘空間。取值爲number,默認爲0。
當一個flex line的空間不足,這些缺失的空間如何分擔給該行的flex item呢?用flex-shrink,它表示某個flex item須要縮小多少比例的空間,取值爲number,默認爲1。
定義了分配多餘空間(可爲正數亦可爲負數)前該flex item所佔的main size,瀏覽器會根據該值來計算主軸上的多餘空間。可設定以下屬性值:
默認值爲auto。當主軸爲水平方向,設置了flex-basic,則flex item的width值會失效。例如,若是某個flex item的flex-basic設爲0,則把該flex item的寬度視爲0,即便它自己width爲100px,這個100px也會被歸入多餘空間中,供flex inline的全部flex item一塊兒分配。
flex屬性爲flex-grow flex-shrink flex-basic的縮寫,默認值爲0 1 auto,可設定的值爲:
一般,flex item不會縮小到比min content sizes還要小。爲防萬一,咱們能夠爲flex item設置min-width或min-height。
總的來講,當存在auto margin時,又有多餘的空間(不包括負的空間),則優先級以下:
flex-grow > auto margin > justify-content/align-self/align-items若是box在軸上只剩下負的空間(即溢出),則auto margin被忽略。
例子:div.parent {
display: flex;
flex-wrap: nowrap;
justify-content: center;
width: 1000px;
height: auto;
border: solid 5px rgba(15, 241, 170, 0.42);
border-radius: 8px;
}
div.parent > div {
border-radius: 8px;
flex: 1 1 auto;
color: #fff;
text-align: center;
line-height: 200px;
font-size: 26px;
}
div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
margin-left: auto;
}
div.second-child {
width: 400px;
height: 200px;
background-color: rgb(255, 141, 75);
}
複製代碼
如今div.parent的justify-content設爲center, div.first-child及div.second-child設置了flex: 1 1 auto(其中flex-grow: 1, flex-shrink: 1, flex-basis: auto); 同時div.first-child設置了margin-left爲auto,效果以下:
能夠看到div.first-child及div.second-child均擴展了,justify-content及auto margin沒起做用。
如今設置div.first-child及div.second-child的flex爲0 1 auto,修改以下:
div.parent > div {
border-radius: 8px;
flex: 0 1 auto;
color: #fff;
text-align: center;
line-height: 200px;
font-size: 26px;
}
複製代碼
效果以下:
能夠看到,剩餘空間都被div.first-child的auto margin-left 佔據了。
如今去掉div.first的auto margin,修改以下:
div.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
}
複製代碼
效果以下:
如今,justify-content起做用了。justify-content用來設置flex-item在主軸上的對齊方式。
Name: justify-content
Value: flex-start | flex-end | center | space-between | space-around
Initial: flex-start
Applies to: flex containers
Inherited: no
效果以下:
align-items定義了flex container中flex-item在交叉軸上的對齊方式,有點相似justify-content,是針對全部flex item。
align-self定義了某個flex item在交叉軸上的對齊方式,會覆蓋align-items的值。
Name: align-items
Value: flex-start | flex-end | center | baseline | stretch
Initial: stretch
Applies to: flex containers
Inherited: no
Name: align-self
Value: auto | flex-start | flex-end | center | baseline | stretch
Initial: auto
Applies to: flex items
Inherited: no
Name: align-content
Value: flex-start | flex-end | center | space-between | space-around | stretch
Initial: stretch
Applies to: multi-line flex containers
Inherited: no
align-content定義了flex line在flex container的交叉軸方向上的對齊方式,相似於justify-content,都屬於flex container屬性。只不過它要對齊的對象是flex line,且在交叉軸方向,而justify-content要對齊的對象是flex item,在主軸上。
屬性值以下:
space-around: flex container中的flex line之間的空間相等,第一個flex line與 flex container的margin box的上邊緣之間的空間只有flex line之間的空間的一半。