前言
- 本人在回顾flex布局的语法时发现自己不理解align-items和align-content的区别
- 仅仅停留于align-items在单行时生效,align-content在多行时生效,然后就问自己
单行
时是指什么时候?多行
时又是指什么时候?
- 仅仅停留于align-items在单行时生效,align-content在多行时生效,然后就问自己
此时的我完全一脸懵*,看来是之前在学习这些知识的时候没有好好深入去了解它额?,既然发现了,就好好的去补上它吧,阅读完这个Stack Overflow上的回答以及W3C,再加上自身的一些理解,来整理一下flex-wrap和align-self,align-items以及align-content之间的关系
图解
- 看完上图你可能会产生如下疑问
- 1 . 为何要给行加上【】?
- 2 . 何为单【行】弹性容器以及多【行】弹性容器 ?
- 3 . 【行】与弹性线是什么意思 ?
- 4 . align-content为何画在【行】的下面,align-items和align-self为何画在弹性线的下面?
对此我将会在下面一一分析,最后引用Stack Overflow的七个Example来进行一波分析,来彻底弄清楚flex-wrap和align-items,align-self,align-content之间的关系
缘由
-
一个页面是由许多个Box组成的,而每个Box的类型由display来指定,而不同类型的盒子又被归为:Inline-level Box,Block-level Box,run-in Box,其中run in Box中含有flex container,它会创建相应的FFC,然后内部的盒子根据其规则进行布局
-
通过指定display为flex或inline-flex从而使Box变为flex container,组成如下图
-
弹性容器的主轴方向是由flex-direction来决定的,而它的类型是由flex-wrap来决定的,因此针对
疑问1
是因为主轴方向是可以改变为水平(行)或垂直方向(列) -
针对
疑问2
,给出创建不同弹性容器时,弹性容器内形成的【行】的图- 单行弹性容器
- 多行弹性容器
而我所画的图中的
【行】
即上图中两条红线间的区域
-
针对
疑问3
,弹性线(flex-line)就是存在于每一个【行】中,由弹性线来引导着弹性容器内每个flex-item进行排列- 如上图的单行弹性容器中,因为align-item的默认值为flex-start,所以它的弹性线就在【行】的顶部
如果设置align-item为flex-end,那么弹性线就来到了【行】的底部,因此flex-item就会从下往上进行排列,设置为center同理
- 如上图的单行弹性容器中,因为align-item的默认值为flex-start,所以它的弹性线就在【行】的顶部
-
而对于
疑问4
,如下解释- align-items作用的对象是【行】的弹性线,align-self作用的则是
自身
的弹性线
【行】的弹性线由每个flex-item的弹性线组成
align-self覆盖align-items对该元素起的作用 - align-content作用的对象是【行】
如:stretch将交叉轴剩余空间分配给每个【行】,而flex-start则是将每个【行】沿着交叉轴正方向进行排列,等等都可以解释
- align-items作用的对象是【行】的弹性线,align-self作用的则是
-
总结七个Example
源代码
<flex-container>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
复制代码
flex-container {
display: flex;
width: 250px;
height: 250px;
background: silver;
}
flex-item {
flex: 0 0 50px;
height: 50px;
margin: 5px;
background-color: lightgreen;
}
复制代码
Example1和2
在上述的css中添加
flex-container {
flex-wrap: nowrap => wrap || wrap-reverse;
align-content: flex-start;
}
flex-item:last-child {
align-self: flex-end;
background: crimson;
}
复制代码
-
其实无论是单【行】弹性盒子或多【行】弹性盒子,align-self都会起作用,因为存在【行】,那么就会有一条弹性线,而align-self作用的对象就是元素自身的弹性线,下图就是将自身的弹性线移到了【行】底部
-
而此处,由单【行】弹性盒子变为多【行】弹性盒子,首先align-content通过移动【行】,使得其沿交叉轴正方向排列,而对于align-self其实它并没有失效,因为它将自身的弹性线移动到【行】的底部后,该元素的布局效果和不移动时是一样的!
Example3和4
在上述的css中添加
flex-container {
flex-wrap: nowrap => wrap || wrap-reverse;
align-items: flex-end;
align-content: flex-start;
}
复制代码
-
在单【行】弹性容器中align-items通过移动【行】的弹性线到【行】底部,使得每个flex-item验证交叉轴的负方向排列
因为此处每个flex-item都没有改变它的align-self的值,即默认为auto,所以不会它们不会移动本身的弹性线
-
而在多【行】弹性容器中align-content通过移动【行】,使得每个flex-item沿着交叉轴正方向排列,而此处的align-items虽然也将每个【行】的弹性线移动到【行】底部,但效果和不移动一样
Example5和6和7
flex-container {
flex-wrap: wrap | wrap-reverse;
}
flex-item:nth-child(2) {
align-self: flex-end;
background: red;
}
复制代码
-
在多【行】弹性容器中由于align-content的默认值stretch将每个【行】平分交叉轴上剩余的空间,从而使得【行】变大了,同时移动第二个flex-item的弹性线到该【行】的底部,从而改变它的布局(即以弹性线为起点,沿交叉轴负方向排列)
扩展聊聊flex-grow、flex-shrink和flex-basis
-
首先flex-grow、flex-shrink都是在主轴方向上生效的
- flex-grow按比例将该【行】的剩余空间分配给【行】的每个flex-item
- flex-shrink则是要求【行】的每个flex-item按公式缩小大小以不超出弹性容器
boxj需要缩减的长度
(i从1到【行】的flex-item元素数量,j是其中一个)
(boxj-contentLength of main axis) * (boxj-flex-shrink)
—————————————————————————— * 在主轴上超出的长度
Σ[(boxi-contentLength of main axis) * (boxi-flex-shrink)]
- box1需要缩减的长度 = [120 * 1 / (120 * 1 + 120 * 1 + 320 * 3)] * 200 = 20
200 – 20 = 180
- box2需要缩减的长度 = [120 * 1 / (120 * 1 + 120 * 1 + 320 * 3)] * 200 = 20
200 – 20 = 180
- box3需要缩减的长度 = [320 * 3 / (120 * 1 + 120 * 1 + 320 * 3)] * 200 = 160
400 – 160 = 240
flex-container { display: flex; flex-flow: row wrap; width: 600px; height: 600px; border: 2px solid red; } flex-item { width: 200px; height: 200px; box-sizing: border-box; padding: 0 40px; background: #f0f; } flex-item:nth-of-type(2) { background-color: #ff0; } flex-item:nth-of-type(3) { width: 400px; flex-shrink: 3; background-color: #0ff; } 复制代码
<flex-container> <flex-item></flex-item> <flex-item></flex-item> <flex-item></flex-item> </flex-container> 复制代码
-
再聊聊flex-basis与max-width/height、min-width/height、width/height之间的关系
推荐此文章:The Difference Between Width and Flex Basis
并且推荐一下该作者的Flexbox Zombies教育游戏(免费的,挺有意思的)
注意点
-
为什么没有’justify-items’和’justify-self’属性?
- 如我需要将单行弹性容器的最后一个flex-item放置在右下角,如果有justify-self情况下,那么可以通过
justify-self: flex-end
和align-self: flex-end
完成,但实际上justify-self的设置并不能生效,我个人偏向于没必要
,因为可以通过margin: auto
平分剩余的水平和垂直空间来实现效果,就可以使用margin-left: auto
和align-self: flex-end
- 如我需要将单行弹性容器的最后一个flex-item放置在右下角,如果有justify-self情况下,那么可以通过
-
被不换行的内容撑开的Box,flex-shrink对它无效
可以被不换行文字或子元素撑开父元素(flex-item),这样它本身的flex-shrink就不会生效
flex-container {
display: flex;
width: 600px;
height: 600px;
border: 5px solid red;
}
.sonBox {
background: chocolate;
width: 400px;
height: 100px;
}
flex-item:nth-child(2) {
background: blueviolet;
width: 200px;
height: 200px;
}
flex-item:nth-child(3) {
background: cornflowerblue;
width: 200px;
height: 200px;
}
复制代码
<flex-container>
<flex-item>
<div class="sonBox"></div>
</flex-item>
<flex-item></flex-item>
<flex-item></flex-item>
</flex-container>
复制代码
圣杯布局
-
最后运用所学知识,写一个圣杯布局,不是简简单单
-
header、footer固定占的高度20%,中间高度自适应
-
left、right固定宽占20%,center宽自适应
<flex-container>
<header></header>
<div class="content">
<div class="left"></div>
<div class="center"></div>
<div class="right"></div>
</div>
<footer></footer>
</flex-container>
复制代码
flex-container {
display: flex;
flex-flow: column nowrap;
height: 500px;
width: 500px;
overflow: hidden;
resize: both;
}
header,footer {
flex-basis: 20%;
background: crimson;
}
div.content {
display: flex;
flex: 1 1 auto;
}
.left,.right {
flex-basis: 20%;
background: chocolate;
}
.center {
flex: 1 1 auto;
background: goldenrod;
}
复制代码
总结
- 此文章是提炼出来 + 自身理解的笔记,还是推荐感兴趣的读者去阅读Stack Overflow以及w3c
- 文章有不对的地方,欢迎大家讨论,我会有则改之,无则加勉的