2023一文搞懂flex布局

279 阅读8分钟

flex布局.png

父容器

在正式开始之前,先设定父元素,与子元素

<div class="parent">
    <div class="son1">1</div>
    <div class="son2">2</div>
    <div class="son3">3</div>
    <div class="son4">4</div>
    <div class="son5">5</div>
    <div class="son6">6</div>
    <div class="son7">7</div>
</div>
.parent{
      width: 300px;
      height: 300px;
      display: flex;
 }
 
 .son{
     width:50px;
     height:50px;
 }
 
 //因为子元素都是相同的,为了更加关注于flex布局,笔者这里只写了尺寸,和flex相关属性。

flex-wrap(设置是否换行)

nowrap(默认值) | wrap | wrap-reverse

nowrap

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex-wrap:nowrap;
 }
子元素宽度未溢出

我们可以看到此时子元素宽度为50px

image.png
子元素宽度溢出
image.png

此时发现,我们有7个子元素,每个子元素为50px,50px*7 >300px,但是子元素并未溢出,此时子元素平分父元素宽度,子元素宽度为300px/7=42.86

image.png

wrap

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex-wrap:wrap;
 }
image.png

可以看到此时,虽然子元素溢出,但是已经换行

wrap-reverse

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex-wrap:wrap-reverse;
 }
image.png

flex-direction(设置主轴方向)

row(默认) | row-reverse | column | column-reverse

主轴的方向决定了交叉轴的方向,前面我们先讲了换行方式,因为交叉轴需要配合多行才能更好的显示效果

row

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex:wrap;
      flex-direction:row;
 }
image.png

row-reverse

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex:wrap;
      flex-direction:row-reverse;
 }
image.png

column

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex:wrap;
      flex-direction:column;
 }
image.png

column-reverse

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex:wrap;
      flex-direction:column-reverse;
 }
image.png

总结,当主轴为横向时,交叉轴向下,主轴为纵向时,交叉轴向右

flex-flow

flex-dirextion | flex-wrap

flex-flow其实是flex-direction和flex-wrap两个属性的集合,并且没有顺序

一个值

当flex-flow为一个属性时。

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex-flow: wrap; //此时为flex-wrap的值
 }
image.png
.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex-flow: row-reverse; //此时为flex-direction的值
 }
image.png

可以看到此时和单独设置flex-wrap或者flex-direction一样

两个值

既然是flex-direction和flex-wrap两个属性的集合,接下来我们看一看两个值的情况

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex-flow: row-reverse wrap; //flex-direction | flex-wrap
 }
image.png

此时我们先写了flex-direction的值,再写的flex-wrap的值,我们将其交换一下试一试:

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex-flow: wrap;  row-reverse//flex-wrap | flex-direction
 }
image.png

可以发现,此时布局没有任何变化,也就是说,无论先写的是flex-direction的值还是flex-wrap的值都是可以的,并没有像margin一样严格规定了每个值的顺序

justify-content(设置子元素主轴方向上的排列方式)

flex-start | flex-end | center | space-around(两边占中间一半) | space-between(两边相切)

flex-start

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      justify-content: flex-start;
 }
image.png

flex-end

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      justify-content: flex-end;
 }
image.png

center

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      justify-content: center;
 }
image.png

space-around

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      justify-content: space-around;
 }
image.png

此时,你一定很好奇,两边并不是相切的,而且明显比中间短,那么两边的间距到底是多少呢,此时两边的间距为中间间距的一半

space-between

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      justify-content: space-between;
 }
image.png

align-items(设置子元素在交叉轴上的排列方式)

stretch(默认) | flex-start | flex-end | center | baseline

stretch

将子元素在交叉轴上拉伸至父元素一致

子元素在交叉轴上设置了值时

本来准备写宽度,但突然发现好像不是很严谨,故变成了交叉轴有值 我们先来看看此时的父子元素分别是

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      align-items: stretch;
 }
 
 .son{
     width:50px;
     height:50px;
 }
image.png

这时我们发现,当子元素在交叉轴设置了值时,align-items: stretch 失效了。

接下来我们看一看当子元素在交叉轴没有值时

子元素在交叉轴没有设置值时
.parent{
      width: 300px;
      height: 300px;
      display: flex;
      align-items: stretch;
 }
 .son1{
      width:50px;
 }//注意,这里我只设置了第一个子元素没有高度
image.png

这个时候我们发现 align-items: stretch 已经起作用了

flex-start

image.png

flex-end

image.png

center

image.png

baseline

image.png

align-content(设置多行子元素在交叉轴上的排列方式)

flex-start | flex-end | center | space-around | space-between | stretch

多行子元素设置在交叉轴的排列方式

我们先来看一看当多行子元素在交叉轴上使用align-items

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex-wrap: wrap;
      align-items: center;
 }
image.png

可以发现此时设置的align-items: center好像并没有达到我们想要的效果,此时我们就需要align-content属性

flex-start

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      flex-wrap: wrap;
      align-content: flex-start;
 }
image.png

flex-end

image.png

center

image.png

space-around

image.png

space-between

image.png

stretch

当子元素在交叉轴上有值时,我们发现没有作用

.parent{
      width: 300px;
      height: 300px;
      display: flex;
      align-content: stretch;
 }
 
 .son{
     width:50px;
     height:50px;
 }
image.png

当去掉子元素在交叉轴上的值时

.son1{
     width:50px;//注意:此时我们只是去掉了第一个子元素的值
 }
image.png

子容器

.parent{
      width: 300px;
      height: 300px;
      display: flex;
 }
 
 .son{
     width:50px;
     height:50px;
 }

align-self(设置单个子元素在交叉轴上的排列方式)

auto(默认值) | stretch | flex-start | flex-end | center | baseline

auto

自动继承父元素的align-items属性

stretch

同样,如果子元素在交叉轴上设置了数值,便不起作用

 .son{
     width:50px;
     height:50px;
     align-self: stretch;
 }
image.png

当子元素未设值时

 .son1{
     width:50px;
     align-self: stretch;
 }
image.png

flex-start

image.png

flex-end

image.png

center

image.png

baseline

 .son2{
     width:50px;
     height:50px;
     align-self: baseline;
 }
image.png

order

子元素的排列顺序,越小越靠前,默认值为0,可以接受负值

.son2{
    order:-5;
 }
 .son3{
     order:-4;
 }
image.png

flex-grow(子元素拉伸因子)

在学习flex-grow之前,我们先要弄懂一个概念:剩余空间

image.png

父元素-所有子元素 = 剩余空间

在此例中,我们的剩余空间为:300px - 50px*3 = 150px

当我们设置每个元素的拉伸比例

.son1{
    flex-grow:1;
}
.son2{
    flex-grow:2;
}
.son3{
    flex-grow:3;
}

子元素1:50px + 1/(1+2+3)*150px = 75px

子元素2:50px + 2/(1+2+3)*150px = 100px

子元素3:50px + 3/(1+2+3)*150px = 125px

image.png

当然,flex-grow设置为负数和百分比,或者带单位的数字是不起作用的

当flex-grow设置为小数时,将会把剩余空间设置为1

.son1{
    flex-grow: 0.2;
}
image.png

子元素1: 50px + 0.2/1*150px = 80px

flex-shrink(子元素收缩规则)

当子元素的总空间大于父元素的空间时,剩余空间将转化为溢出空间

.son1{
    width: 150px;
}
.son1{
    width: 150px;
}
.son1{
    width: 150px;
}

当我们把子元素都设置为150px,子元素总空间:150px*3 = 450px ,是大于父元素空间300px的

当然,之前我们看过当子元素总空间大于父元素时,实际宽度为平分父元素空间

image.png

当我们设置子元素

.son1{
    width: 150px;
    flex-shrink: 1;
}
.son1{
    width: 150px;
    flex-shrink: 2;
}
.son1{
    width: 150px;
    flex-shrink: 3;
}

此时: 子元素1:150px- (150px* 1/150px* 1+150px* 2+150px* 3)*150px = 125px

子元素2:150px- (150px* 2/150px* 1+150px* 2+150px* 3)*150px = 100px

子元素3:150px- (150px * 3/150px * 1+150px * 2+150px* 3)*150px = 75px

image.png

flex-basis(子元素主轴方向的基础大小)

优先级:flex-basis > width

    .son1{
           width: 50px;
           flex-basis: 100px;
           
    }
image.png

我们发现此时的子元素宽度变为100px,可接受参数为带单位的数值和百分比

flex

为flex-grow,flex-shrink,flex-basis三个属性的集合

/* 单值,无单位数字:flex:<flex-grow> 1 0
flex: 2;

/* 单值,宽度/高度:flex: 1 1 <flex-basis> */
flex: 10em;
flex: 30px;
flex: min-content;



/* 双值:flex:<flex-grow> 1 <flex-basis> */
flex: 1 30px;


/* 双值:flex: <flex-grow> <flex-shrink> 0*/
flex: 2 2;


/* 三值:flex:<flex-grow> <flex-shrink> <flex-basis>*/
flex: 2 2 10%;

一道经典面试题

面试官,了解flex:1吗?请解释一下

答:首先是flex为flex-grow和flex-shrink和flex-basis的缩写,当flex的值为不带单位的单值时候

flex三个属性分别为:

flex-grow:1

flex-shrink:1

flex-basis:0

结语

希望看完此篇flex布局,能对你有所帮助,感谢观看,如有错误,还望指正

感谢

深入理解 flex-grow、flex-shrink、flex-basis(如果还对子元素的flex简写属性有疑惑,强烈建议观看这篇文章)