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.first-child {
width: 200px;
height: 200px;
background-color: rgb(64, 166, 249);
position: absolute;
align-self: center;
}
复制代码
效果以下:
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.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.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用来设置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之间的空间的一半。