我们有这样的需求,大容器中有很多的盒子,从左往右排列,空间不够的话,然后换行,继续从左往右排列,如下效果图

看到这样的需求,我们第一时间想到的就是弹性盒布局,给大容器开启弹性盒、允许换行,两侧分布,于是会写下如下代码:

display: flex;
flex-wrap: wrap;
justify-content: space-between;

如果是正好9个项,那这种写法没有问题,如果是8个项,最后一行的7和8就会两侧分布了,如下图:

这种效果肯定不行啊,那怎么办呢?

解决方案一 使用真实DOM进行填充,然后再隐藏这个DOM

  • 我们再创建一个dom元素项,作为最后一个9
  • 然后把第9项的高度置为0,只保留宽度
  • 或者再加点透明度为0障眼法使其看不到即可
  • 代码如下(复制粘贴使用):

    <!DOCTYPE html>
    <html lang="en">
    	<meta charset="UTF-8">
    	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    	<title>Document</title>
    	<style>
    		.wrap {
    			width: 480px;
    			height: 360px;
    			border: 4px solid #000;
    			overflow-y: auto;
    			box-sizing: border-box;
    			padding: 6px;
    			/* 开启弹性盒,换行,两端分布 */
    			display: flex;
    			flex-wrap: wrap;
    			justify-content: space-between;
    		.item {
    			width: 120px;
    			height: 120px;
    			line-height: 120px;
    			text-align: center;
    			border: 2px solid pink;
    			font-weight: 700;
    			font-size: 24px;
    			margin-bottom: 8px;
    			/* 注意是border-box盒模型 */
    			box-sizing: border-box;
    		/* 障眼法占位项 */
    		.fakeItem {
    			width: 120px;
    			height: 0;
    			border: 2px solid green;
    			box-sizing: border-box;
    			opacity: 0;
    			/* visibility: hidden; */
    	</style>
    </head>
    	<div class="wrap">
    		<div class="item">1</div>
    		<div class="item">2</div>
    		<div class="item">3</div>
    		<div class="item">4</div>
    		<div class="item">5</div>
    		<div class="item">6</div>
    		<div class="item">7</div>
    		<div class="item">8</div>
    		<div class="item">9</div>
    	</div>
    	<script>
    		 * 通过js添加一个假的项,即为占位项
    		 * 占位项的高度为0,宽度和其他项宽度一样
    		 * 也可加透明度为0,或者visibility都行的
    		 * 只要障眼法看不到即可
    		let wrap = document.querySelector('.wrap')
    		let divDom = document.createElement('div')
    		divDom.classList.add('fakeItem')
    		wrap.appendChild(divDom)
    	</script>
    </body>
    </html>
    

    这样就实现了,本文中的第一个效果图

    解决方案二 使用伪元素在最后位置进行填充

    创建dom,渲染dom有些耗费性能(实际上肉眼看不出区别的),那我们就不创建dom呗,直接使用伪元素模拟一个真实的dom,思路基本一致的,于是,我们就有了以下“优化”代码

    <!DOCTYPE html>
    <html lang="en">
    	<meta charset="UTF-8">
    	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    	<title>Document</title>
    	<style>
    		.wrap {
    			width: 480px;
    			height: 360px;
    			border: 4px solid #000;
    			overflow-y: auto;
    			box-sizing: border-box;
    			padding: 6px;
    			/* 开启弹性盒,换行,两端分布 */
    			display: flex;
    			flex-wrap: wrap;
    			justify-content: space-between;
    		/* 解决最后一行不从左往右排布问题 */
    		.wrap::after {
    			content: "";
    			height: 0;
    			/* 和内容项的宽度保持一致 */
    			width: 120px;
    		.item {
    			width: 120px;
    			height: 120px;
    			line-height: 120px;
    			text-align: center;
    			border: 2px solid pink;
    			font-weight: 700;
    			font-size: 24px;
    			margin-bottom: 8px;
    			/* 注意是border-box盒模型 */
    			box-sizing: border-box;
    	</style>
    </head>
    	<div class="wrap">
    		<div class="item">1</div>
    		<div class="item">2</div>
    		<div class="item">3</div>
    		<div class="item">4</div>
    		<div class="item">5</div>
    		<div class="item">6</div>
    		<div class="item">7</div>
    		<div class="item">8</div>
    		<!-- <div class="item">9</div> -->
    	</div>
    </body>
    </html>
    

    拓展栅格布局也是一种思路

    另外也可以使用栅格布局的方式进行尝试

    栅格布局非常强大哦!!!

    拓展思路代码

    <!DOCTYPE html>
    <html lang="en">
    	<meta charset="UTF-8">
    	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    	<title>Document</title>
    	<style>
    		.grid-box {
    			display: grid;
    			grid-template-columns: auto auto auto;
    			border: 1px solid #333;
    		.grid-box-item {
    			font-size: 30px;
    			text-align: center;
    			padding: 12px;
    			border-right: 1px solid #333;
    			border-bottom: 1px solid #333;
    		.grid-box-item:last-child {
    			border-bottom: none;
    		.grid-box-item:nth-last-child(2) {
    			border-bottom: none;
    		.grid-box-item:nth-child(3n) {
    			border-right: none;
    	</style>
    </head>
    	<div class="grid-box">
    		<div class="grid-box-item">1</div>
    		<div class="grid-box-item">2</div>
    		<div class="grid-box-item">3</div>
    		<div class="grid-box-item">4</div>
    		<div class="grid-box-item">5</div>
    		<div class="grid-box-item">6</div>
    		<div class="grid-box-item">7</div>
    		<div class="grid-box-item">8</div>
    	</div>
    </body>
    </html>
    

    宽度固定九宫格布局

    <!DOCTYPE html>
    <html lang="en">
    	<meta charset="UTF-8">
    	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    	<title>Document</title>
    	<style>
    			margin: 0;
    			padding: 0;
    		.wrap {
    			width: 300px;
    			display: flex;
    			flex-wrap: wrap;
    			/* 外边距这个得加,否则小范围重叠,越大效果越好 */
    			margin-top: 50px;
    			margin-left: 50px;
    			/* 从左往右排列加不加都行的 */
    			justify-content: flex-start;
    		.item {
    			width: 100px;
    			height: 100px;
    			line-height: 100px;
    			text-align: center;
    			box-sizing: border-box;
    			border: 1px solid #333;
    			/* 盒子往右上方移动一像素,使之重叠 */
    			margin-top: -1px;
    			margin-left: -1px;
    		/* 给最后一行的盒子设置样式,可一个,可两个,可三个 
    		   参考:https://www.douyin.com/video/7198919582197845308 */
    		.item:nth-child(3n + 1):nth-last-child(-n +3),
    		.item:nth-child(3n + 1):nth-last-child(-n +3)~.item {
    			background-color: pink;
    	</style>
    </head>
    	<div class="wrap">
    		<div class="item">1</div>
    		<div class="item">2</div>
    		<div class="item">3</div>
    		<div class="item">4</div>
    		<div class="item">5</div>
    		<div class="item">6</div>
    		<div class="item">7</div>
    		<div class="item">8</div>
    		<div class="item">9</div>
    	</div>
    </body>