上一期我整理介绍了grid布局方式,如果想看的同学,可以直接点击此文章:
Grid布局
这期我把flex布局方式笔记也整理出来了,内容是我自己在根据别人视频学习过程中整理的资料。
目前很多css的框架都使用Flexbox作为基础。浏览器大部分也都兼容。
接下来直接看代码演示,我们先准备一个素材,准备5个div元素,定义为 ABCDE。因为div默认情况下display是block块级元素,所以默认情况下会独占一行。所以我们得到如下图的排版。这就是我们准备的素材。
A
B
C
D
E
html {
font-size: 12px;
}
.box {
width: 60px;
height: 60px;
background-color: #eee;
text-align: center;
line-height: 60px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
font-size: 2rem;
}
.A {
background-color: #6dd98f;
}
.B {
background-color: #0c7899;
}
.C {
background-color: #961375;
}
.D {
background-color: #bb7e38;
}
.E {
background-color: #cfec9f;
}
Flex Container和Flex Items
Flex布局方式主要就分为2个角色,Flex Container和Flex Items,也就是父容器和子项目。我们先来改写素材。
A
B
C
D
E
将四个div元素外部包括一个flex-container父容器,并且设置flex-container的display为flex。那么我们便得到了如下图的布局。
.flex-container {
display: flex;
background-color: #2B34F5;
}
这里父容器就是flex-container元素,而里面五个div则便是flex items子项目。
flex container中属性
flex-direction
flex-direction这个属性是定义父容器中子项目,即flex items的排序方向。
flex-direction的默认值一般为 row,即是横向排序。
如果你改成:
flex-direction: column;
这时候便是纵向排序。
另外还有以下排序方式:
flex-direction: row-reverse; //横向倒转排序。
如下图:
flex-direction: column-reverse; //纵向倒转排序。
如下图:
这里有一个比较重要的知识点:主轴(main-axis)和交叉轴(cross-axis)。当flex属性不同时候,主轴和交叉轴不同。这个知识点需要和justify-content和align-items结合起来使用,下面我们先来介绍justify-content和align-items这2个知识点。
flex-direction属性 | 主轴(main-axis) | 交叉轴(cross-axis) |
---|---|---|
row | row | column |
column | column | row |
justify-content和align-items
justify-content是设置主轴的排序方向的。而align-items则是设置交叉轴的排序方向的。
我们还是看代码:
.flex-container {
display: flex;
background-color: #2B34F5;
flex-direction: row;
justify-content: center;
}
我们把flex-direction设置为row横向排序,这时候设置justify-content,即主轴方向居中,此时的主轴便是row,那么我们可以得到如下图的效果:
但是当我们把代码改为flex-direction: column时候,此时主轴便成了colunm,设置justify-content: center属性则不会得到水平方向的居中,如下图。
.flex-container {
display: flex;
background-color: #2B34F5;
flex-direction: column;
justify-content: center;
}
此时,如果我们要得到水平方向居中,则应该设置align-items:center,而不是justify-content: center。因为此时row水平方向是属于交叉轴。
.flex-container {
display: flex;
background-color: #2B34F5;
flex-direction: column;
justify-content: center;
align-items: center;
height: 500px;
}
那我们便把flex-container父容器高度设置大点,这时候主轴便是column,那么justify-content: center熟悉会让子元素垂直居中于父容器内,则align-items: center则会让子元素水平居中于父容器内。
从这个举例来看,是不是很好理解主轴和交叉轴概念。
另外,justify-content除了center外,还有其他各种属性
.flex-container {
display: flex;
background-color: #2B34F5;
flex-direction: row;
height: 500px;
align-items: center;
}
我们把父容器恢复为flex-direction: row水平布局。
justify-content: flex-start; //沿着主轴起始方向排版布局
如下图:
justify-content: flex-end;//沿着主轴结束方向排版布局
如下图:
这里要记住一点:
设置flex-direction: row属性时候,justify-content属性设置为flex-start或flex-end,子元素都是由左至右排序。设置flex-direction: colunm属性时候,justify-content属性设置为flex-start或flex-end,子元素都是由上至下排序。即顺序都是ABCDE,不会是EDCBA。
flex-wrap
flex-wrap即是会不会分行的意思。
A
B
C
D
E
A
B
C
D
E
A
B
C
D
E
A
B
C
D
E
我们在父容器中加入多个子div,这时候我们缩小浏览器的宽度。
.flex-container {
display: flex;
background-color: #2B34F5;
flex-direction: row;
justify-content: flex-start;
align-items: center;
height: 500px;
}
这时候会发现,子div还是会被压缩在水平方向一行,每个子div宽度会被挤压。这是因为flex-wrap默认的属性值是nowrap,即不换行的意思,所以不管怎么添加子div,都只会在同一行。
如果我们修改属性flex-wrap: wrap:
.flex-container {
display: flex;
background-color: #2B34F5;
flex-direction: row;
justify-content: flex-start;
align-items: center;
height: 500px;
flex-wrap: wrap;
}
这时候,超出宽度的子div便会被移到下一行中。这时候我们再配合justify-content和align-items两个属性,就能得到不一样效果,比如下面排版:
.flex-container {
display: flex;
background-color: #2B34F5;
flex-direction: row;
justify-content: center;
align-items: center;
height: 500px;
flex-wrap: wrap;
}
flex-flow
flex-flow是flex-direction和flex-wrap的组合起来的缩写。
.flex-container {
display: flex;
background-color: #2B34F5;
flex-flow: row wrap;
justify-content: center;
align-items: center;
height: 500px;
}
flex-flow: row wrap; 在这里便是flex-direction:row,flex-wrap:wrap的缩写。这个可以根据个人习惯用此属性或者分2个属性编写。
align-content
align-content这个属性,是当flex-wrap设定为wrap的时候,即是有二行以及二行以上时候才会生效。直接看下图:
.flex-container {
display: flex;
background-color: #2B34F5;
flex-flow: row wrap;
justify-content: center;
align-items: center;
height: 500px;
}
不设置align-content时候的如下图:
align-content: center;
align-content: center时候如下图:
align-content: space-between;
align-content: space-between时候如下图:
align-content: flex-start;
align-content: flex-start时候如下图:
由上面举例可知道,align-content是设定二行以二行以上时候,行与行之间的对齐方式。
Flex Items中属性
order
order属性用于调整flex item的排序位置。我们看以下参考案例:
.flex-container {
display: flex;
background-color: #2B34F5;
flex-flow: row wrap;
justify-content: center;
align-items: center;
height: 200px;
width: 500px;
}
A
B
C
D
E
我们还是先设定父容器下5个子div,以flex布局方式,自动换行。
.B {
background-color: #0c7899;
order: 1;
}
这时候我们在B子DIV中加入属性值order:1,那么我们会得到如下布局排版方式。
发现div B已经到了末尾,这是因为flex item的order默认值都是0,当B设定为1时候,因为flex布局容器会根据order数字以小到大排序,B便会移动至末尾排序。
.B {
background-color: #0c7899;
order: -1;
}
如果我们把B DIV的order设置为-1,则会排序到第一个。
order可以随意将个别flex item的位置进行改变。
align-self
align-self是用于覆盖flex container(父容器)的align-item的设置的
.flex-container {
display: flex;
background-color: #2B34F5;
flex-flow: row wrap;
justify-content: center;
align-items: center;
height: 200px;
width: 500px;
}
比如父容器中,我们align-items的值设置了center居中。
.A {
background-color: #6dd98f;
align-self: flex-end;
}
如以上代码,我们修改DIV A的align-self属性为flex-end。那么我们会得到如下图排版:
flex-basis
flex-basis是设置flex-item的主轴方向的大小的。
.flex-container {
display: flex;
background-color: #2B34F5;
flex-flow: row wrap;
justify-content: center;
align-items: center;
height: 200px;
width: 500px;
}
比如父容器中,我们设置主轴为row,并可以换行。
.box {
width: 60px;
height: 60px;
background-color: #eee;
text-align: center;
line-height: 60px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
font-size: 2rem;
flex-basis: 200px;
}
在父容器的子div中添加flex-basis: 200px属性,此时此属性即代表子div的宽度为200px;如下图:
而如果我们将主轴改为column。
.flex-container {
display: flex;
background-color: #2B34F5;
flex-flow: column wrap;
justify-content: center;
align-items: center;
height: 200px;
width: 500px;
}
此时flex-basis代表的是子div的高度,如下图:
要记住一点,在设置flex-basis后,原有的高度或者宽度都会失效,都会改为flex-basis的设定值去计算宽度或高度。如果flex-basis设置为0,如果没有overflow的设定,此时容器宽度或高度则取决于子div容器内内容的大小。如下图:
.flex-container {
display: flex;
background-color: #2B34F5;
flex-flow: row wrap;
justify-content: center;
align-items: center;
height: 200px;
width: 500px;
}
.box {
background-color: #eee;
text-align: center;
line-height: 60px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
font-size: 2rem;
flex-basis: 0;
}
如果子容器再添加overflow属性,则如下面情况:
.box {
overflow: hidden;
background-color: #eee;
text-align: center;
line-height: 60px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
font-size: 2rem;
flex-basis: 0;
}
overflow: hidden情况下,不会显示子div。
flex-grow
flex-grow是指当flex container的主轴方向有剩余空间的时候,flex item(容器子元素)沿主轴方向扩大的设置。
.flex-container {
display: flex;
background-color: #2B34F5;
flex-flow: row wrap;
justify-content: flex-start;
align-items: center;
height: 200px;
width: 500px;
}
.box {
width: 60px;
height: 60px;
background-color: #eee;
text-align: center;
line-height: 60px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
font-size: 2rem;
}
A
B
C
D
E
.box {
width: 60px;
height: 60px;
background-color: #eee;
text-align: center;
line-height: 60px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
font-size: 2rem;
flex-grow: 1;
}
box属性中,我们加入了 flex-grow: 1,这时候原先的排版便会变成以下结果:
子容器直接平均撑满整个父容器。这是因为五个div属性都是flex-grow: 1,那五个div便都是独占一份,会各自占剩余空间200px中的一份,即40px。
如果我们不给每个子div设定flex-grow,只设定其中A DIV元素
.box {
width: 60px;
height: 60px;
background-color: #eee;
text-align: center;
line-height: 60px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
font-size: 2rem;
}
.A {
background-color: #6dd98f;
flex-grow: 1;
}
.B {
background-color: #0c7899;
}
.C {
background-color: #961375;
}
.D {
background-color: #bb7e38;
}
.E {
background-color: #cfec9f;
}
那么从上图排版,我们会发现A DIV会独占剩余200px的所有空间。也就是A DIV宽度变成了60+200=260px;
而当主轴改为column时候,则是垂直方向A独占剩余空间。
.flex-container {
display: flex;
background-color: #2B34F5;
flex-flow: column wrap;
justify-content: flex-start;
align-items: center;
height: 500px;
width: 500px;
}
.box {
width: 60px;
height: 60px;
background-color: #eee;
text-align: center;
line-height: 60px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
font-size: 2rem;
}
.A {
background-color: #6dd98f;
flex-grow: 1;
}
.B {
background-color: #0c7899;
}
.C {
background-color: #961375;
}
.D {
background-color: #bb7e38;
}
.E {
background-color: #cfec9f;
}
flex-shrink
flex-shrink则与flex-grow相反。是指当flex item子容器主轴方向的大小总和,超出父容器flex container的时候,flex item沿主轴方向如何缩小的设定。
.flex-container {
display: flex;
background-color: #2B34F5;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
height: 300px;
width: 240px;
}
.box {
width: 60px;
height: 60px;
background-color: #eee;
text-align: center;
line-height: 60px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
font-size: 2rem;
}
我们将父容器宽度改为240px,主轴为row方向,不换行。每个div设定为60px,那么理论上5个div应该有300px总和。但是现在父容器只有240px,少了60px。
我们发现五个div还在同一行,但是宽度被缩减了。这是因为flex-shrink默认值都是1。
.box {
width: 60px;
height: 60px;
background-color: #eee;
text-align: center;
line-height: 60px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
font-size: 2rem;
flex-shrink: 0;
}
我们现在每个div设置flex-shrink: 0。这时候代表当主轴方向空间不足时候,不会去压缩子容器的宽度。那么我们可以得到下图排版:
.A {
background-color: #6dd98f;
flex-shrink: 1;
}
.B {
background-color: #0c7899;
flex-shrink: 1;
}
.C {
background-color: #961375;
flex-shrink: 1;
}
.D {
background-color: #bb7e38;
flex-shrink: 1;
}
.E {
background-color: #cfec9f;
}
我们在子DIV A、B、C、D中都加入属性值flex-shrink: 1,这代表ABCD四个DIV都各自分担一份被缩小的空间,也就是60/4=15px,那么ABCD四个div都会缩小为60-15=45px的宽度,而E因为flex-shrink:0,所以仍然会是60px的宽度。如下图排版:
flex
flex的属性是flex-grow,flex-shrink和flex-basis组合起来的缩写。类似于父容器属性flex-flow,根据每个人写法习惯不同,可以拆分成三个属性分别写,也可以组合编写。这里不多做介绍。
前端学习过程要感谢B站的CodingStartup的Steven,不过他的讲解基本是粤语和视频,很多笔记我只能在看的过程自己整理,虽然直接我也从事程序开发,但是很多时候只知道要这么做,却不知道为什么要这么做,所以工作几年后重新回头巩固知识,以上是我在学习过程中自己整理的学习笔记,希望可以帮到大家。