1.为什么要最后一行左对齐
我们都知道flex布局就是一个二维坐标系,有横轴和纵轴,里面的子元素则根据我们最初定义的横轴和纵轴初始方向进行排列,如下图:
在flex布局中,justify-content属性非常常用,它用来规定横轴元素的排列规则,通常使用的有以下几种:
- 两端对齐:justify-content: space-between;
- 左对齐:justify-content: flex-start;
- 右对齐:justify-content: flex-end;
- 居中对齐:justify-content: center;
当我们使用两端对齐时,最后一行元素就会出现问题,如下图一样:
代码如下:
<style> .container { width: 300px; border: 1px solid #000; display: flex; flex-wrap: wrap; justify-content: space-between; } .list { width: 66px; height: 66px; margin-bottom: 10px; background-color: rgb(148, 148, 131); } </style> <div class="container"> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> </div>
这个时候我们可能就需要让最后一行元素左对齐。
2.每行列数固定
如果每一行的元素固定,比如我们这里每一行的元素都是四个,这个时候我们有两种方式解决最后一行元素左对齐问题。
2.1 模拟两端对齐
这里模拟的意思代表我们不使用justify-content: space-between进行两端对齐,但是我们又要有两端对齐的效果,而且每一个子元素之间的间隙也要有。
为了实现这种效果,我们需要动态计算每个 子元素之间的间隙,间隙我们利用margin来控制,代码如下:
.container { width: 300px; border: 1px solid #000; display: flex; flex-wrap: wrap; } .list { width: 66px; height: 66px; margin-bottom: 10px; background-color: rgb(148, 148, 131); } // 每一行的最后一个元素不设置右边距 .list:not(:nth-child(4n)) { margin-right: 22px; }
这种方式虽然也可以实现两端对齐的效果,但是需要计算每一个子元素的右边距。
2.2 根据个数动态设置margin
这里的动态设置margin指的是设置最后一个元素的margin值,假如我们这里每一行4个元素,但是最后一行只有三个元素,此时如果我们将最后一行的最后一个元素的右边距设置为元素宽度+间隙宽度,那么是可以实现左对齐效果的。
但是这个时候我们需要知道最后一行有几个元素,这里会用到一个CSS选择器:
- .list:last-child:nth-child(4n - 1)说明最后一行,要么3个元素,要么7个元素……
- .list:last-child:nth-child(4n - 2)说明最后一行,要么2个元素,要么6个元素……
上面的两行代码让我们取到了最后一行的第3个元素和第2个元素,然后动态设置margin,代码如下:
.container { width: 300px; border: 1px solid #000; display: flex; flex-wrap: wrap; justify-content: space-between; } .list { width: 65px; height: 65px; margin-bottom: 10px; background-color: rgb(148, 148, 131); } .list:last-child:nth-child(4n - 1) { margin-right: calc(66px + 12px); } .list:last-child:nth-child(4n - 2) { margin-right: calc(66px + 66px + 12px + 12px); }
当最后一行有三个元素时,则最后一个元素的右边距=元素宽度+间隙宽度。
3.每行子元素宽度不固定
有时候我们每行的元素宽度不是固定的,这个时候我们有两外两种方法来实现最后一行左对齐。
3.1 margin-right:auto
这种方式实现起来很简单,我们只需要设置最后一个元素的margin-right为auto即可,代码如下:
.container { width: 300px; border: 1px solid #000; display: flex; flex-wrap: wrap; justify-content: space-between; } .list { width: 65px; height: 65px; margin-bottom: 10px; background-color: rgb(148, 148, 131); margin-right: 10px; } .list:nth-child(1) { width: 65px; height: 65px; margin-bottom: 10px; background-color: rgb(148, 148, 131); margin-right: 10px; } .list:nth-child(2) { width: 60px; height: 60px; margin-bottom: 10px; background-color: rgb(148, 148, 131); margin-right: 10px; } .list:nth-child(3n) { width: 50px; height: 50px; margin-bottom: 10px; background-color: rgb(148, 148, 131); margin-right: 10px; } .list:last-child { margin-right: auto; }
为了方便大家理解,我给很多list元素设置了不同宽度,大家可以看到最后一行元素虽然左对齐了,但是最右边并没有实现完美的贴边对齐,所有这也是这种方式的一个小小的缺陷。
3.2 设置伪元素
除了利用margin-right:auto之外,我们还可以利用伪元素来实现最后一行左对齐,创建伪元素并设置flex:auto或者flex:1,代码如下:
.container { width: 300px; border: 1px solid #000; display: flex; flex-wrap: wrap; justify-content: space-between; } .list { width: 65px; height: 65px; margin-bottom: 10px; background-color: rgb(148, 148, 131); margin-right: 10px; } .list:nth-child(1) { width: 65px; height: 65px; margin-bottom: 10px; background-color: rgb(148, 148, 131); margin-right: 10px; } .list:nth-child(2) { width: 60px; height: 60px; margin-bottom: 10px; background-color: rgb(148, 148, 131); margin-right: 10px; } .list:nth-child(3n) { width: 50px; height: 50px; margin-bottom: 10px; background-color: rgb(148, 148, 131); margin-right: 10px; } .container::after { content: ''; flex: auto; /* 或者flex: 1 */ }
这种效果和margin:auto是一致的
4.每行列数不固定
有些时候我们每一行的个数是不定的,这个时候上面的方法就不太适用了,我们需要使用其它方法来实现最后一行左对齐:使用足够多的占位空白元素来进行占位,占位元素的个数由最多列数的个数决定。
.container { border: 1px solid #000; display: flex; flex-wrap: wrap; justify-content: space-between; } .list { width: 65px; height: 65px; margin-bottom: 10px; background-color: rgb(148, 148, 131); margin-right: 10px; } .container>i { width: 65px; margin-right: 10px; } <div class="container"> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <div class="list"></div> <i></i><i></i><i></i><i></i><i></i> </div>
这里我们声明了很多占位i标签元素,并且给它设置了宽度,因为我们没有给它设置高度,所以不会影响我们的布局,这种方式也实现了最后一行左对齐,但是它改变了html结构。
总结
这里给出了4种实现flex布局最后一行左对齐的方法,但是每一种都还是有瑕疵的,运用最广泛的还是利用占位元素的方式,因为它不仅适用于每行元素不固定的场景,每行元素个数固定时它也可以使用。
但是如果想要完美实现两端对齐,可以考虑grid布局方式。