内容简介:总想写flex,却一直拖——拖——拖,今天算是写完了。与以往的文章不同,这篇文章更像是写给自己看的,所以有些术语不会再解释,如看不懂,可以先去这篇文章里看看术语.简单的说,flex container的每个孩子都是一个flex item,而每个flex item都是一个flex-level box,另外,由于在计算computed value时flex item会发生块级化,因此每个flex item也是一个block container。而对于没有html元素包裹的连续文字,会被自动包裹在一个匿名的blo
总想写flex,却一直拖——拖——拖,今天算是写完了。与以往的文章不同,这篇文章更像是写给自己看的,所以有些术语不会再解释,如看不懂,可以先去这篇文章里看看术语.
Flex Container
-
display为flex的元素会产生一个flex container,该container在正常流内以block-level的形式存在。
-
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 Item
简单的说,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
1. flex item为绝对定位元素
因为为绝对定位元素,所以该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。
例1:
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> 复制代码
效果如下:
现在为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。
2. flex item的margin和padding
- 相邻的flex item的margin不会重叠(flex container的margin也不会与flex item的margin重叠)。
- margin和padding若设置为百分比,则百分比是基于flex container的inline size(若writing mode是horizontal,则inline size为宽度;若mode是vertical,则inline size 为高度 )。
例子:
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也重叠了。
3. 折叠的flex item
- Flex item可以设置visibility: collapse,达到折叠的效果。效果类似于table的行折叠。
- Flex item即使折叠了,但依然有个隐形的空壳存在,为的是保证flex container的cross size的稳定。如果flex container仅有一个flex line(每条flex line上按main size方向依次摆放flex item,类似于line box),那么某个flex item折叠可能会影响flex container 的main size,但是不会影响flex container的cross size。
- 尽管折叠的flex item不会被渲染,但依然会出现在dom 树上。为了计算折叠的flex item的那个空壳的大小,在dom树形成的过程中,flex layout 会先假设所有item都没有折叠,然后在由dom树形成渲染树的过程中,会将折叠的flex item用一个保留了原始的cross size的空壳替换掉。
例子:
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 className="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> 复制代码
效果如下:
鼠标移到菜单上,子菜单会显示出来
4. flex item的automatic minimum size
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设置一个具体的值比较好。
- 当flex item的content是一篇较大的文档,给min-width或min-height设置成字体相关的值比较好,例如min-width: 12em。使用 automatic minimum size会导致溢出。
- 当flex item有较多的孩子节点时,automatic minimum size的取值需要基于min-content size, 而 layout engine为了找到min-content size需要一一遍历所有的孩子节点,有损性能。如果直接给min size设置specified value,就不必去找min-content size了。
注意:ratio表示一个元素的width与height的比例关系,一般通过给padding-top设定百分比来表达一个固定比例。
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的原本顺序,会影响页面的可访问性。
1. flex-direction
Name: flex-direction Value: row | row-reverse | column | column-reverse Initial: row Applies to: flex containers Inherited: no Percentages: n/a
2. flex-wrap
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方向调换。
3. Order
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; } 复制代码
效果如下:
灵活性
1. flex-grow
当一个flex line还有多余的空间可扩展,这些空间如何分配给该行的flex item呢?用flex-grow, 它用来设置某个flex item可扩展多少比例的多余空间。取值为number,默认为0。
2. flex-shrink
当一个flex line的空间不足,这些缺失的空间如何分担给该行的flex item呢?用flex-shrink,它表示某个flex item需要缩小多少比例的空间,取值为number,默认为1。
3. flex-basic
定义了分配多余空间(可为正数亦可为负数)前该flex item所占的main size,浏览器会根据该值来计算主轴上的多余空间。可设定如下属性值:
- auto: 当specified value为auto时,按如下步骤取值。 第一步:采用的used value为flex item的main size(即主轴上的width或height的属性值), 第二步:如果这个used value依然为auto,那么used value 会基于 flex item的content 得到一个具体值。
- content: 基于flex item的content得到一个automatic size。
- <width>: 和width或height的设置方式一样,可设为<length> 或 <percentage>
默认值为auto。当主轴为水平方向,设置了flex-basic,则flex item的width值会失效。例如,如果某个flex item的flex-basic设为0,则把该flex item的宽度视为0,即使它本身width为100px,这个100px也会被纳入多余空间中,供flex inline的所有flex item一起分配。
4. flex
flex属性为flex-grow flex-shrink flex-basic的缩写,默认值为0 1 auto,可设定的值为:
- initial: 0 1 auto,当有多余空间时,没有弹性;当空间不足时,flex item可以缩小。
- auto: 1 1 auto,flex会有充足的弹性
- none: 0 0 auto, flex会完全没有弹性
- <positive-number>: 1 auto
- <flex-grow> <flex-shrink> <flex-basic>: 若flex-grow省略了,默认值取1;若flex-shrink省略了,默认值取1;若flex-basic省略了,默认值取0。
通常,flex item不会缩小到比min content sizes还要小。为防万一,我们可以为flex item设置min-width或min-height。
对齐
1. 使用auto margin对齐
- 如果设置了flex-grow,auto margin 会被设置为0;若设置了flex-basis,没有设置flex-grow,那么在主轴方向上,根据flex-basis计算出的多余的空间都会分配给auto margin
- auto margin的优先级高于justify-content及align-self,轴上任何多余的空间(不包括负的空间)都会分配给auto margin。
- 如果box在某个轴上发生溢出了,则auto margin会被忽略,且box在该轴的尾部溢出。(如果既有auto margin, 又有justify-content/align-self/align-items,依然是忽略justify-content/align-self/align-items,采用auto margin,只不过此时因为overflow,接着会忽略auto margin, 在轴的尾部溢出)
总的来说,当存在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起作用了。
2.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
效果如下:
3. align-items和align-self
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
- auto: 对于flex-item,可以设置align-self为auto, auto值的computed value会设置为flex container的align-items的值。
- center: flex item的margin box 在交叉轴方向上处于flex line的中间位置。如果flex line的高度比flex item的还要低,则flex item在交叉轴的首尾两端溢出相等部分。
- baseline: flex item会依照flex line的baseline对齐。在交叉轴方向上,baseline与flex item的margin box的上边缘距离最远的那个flex item会被放置在交叉轴的开始位置。
- stretch: 若flex item的 cross size的computed value为auto(如果flex-direction为row,那么cross size就是flex item的height),且交叉轴方向的margin均不为auto,那么align-items/align-self为stretch时,flex item会被拉伸。flex item的cross size的used value会尽可能的接近flex line的高度,如果flex item设置了min(max)-width(height),那么这个used value会受它们的限制。
效果如下图:
4. align-contents
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之间的空间的一半。
效果如下:
注明:本篇文章中少数图片来源网络,如有侵权,请立即联系本人删除。以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Flutter 完整开发实战详解(十六、详解自定义布局实战)
- 数据结构 1 线性表详解 链表、 栈 、 队列 结合JAVA 详解
- 详解Openstack环境准备
- Java泛型详解
- iOS RunLoop 详解
- Raft协议详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Pro JavaScript Design Patterns
Dustin Diaz、Ross Harmes / Apress / 2007-12-16 / USD 44.99
As a web developer, you’ll already know that JavaScript™ is a powerful language, allowing you to add an impressive array of dynamic functionality to otherwise static web sites. But there is more power......一起来看看 《Pro JavaScript Design Patterns》 这本书的介绍吧!