flex实现一行显示n个数量的布局,不同屏幕宽度下显示不同的数量,自适应一行显示的个数 电脑版发表于:2021/8/15 18:02 [TOC] ## 要实现的效果如下: ![](https://img.tnblog.net/arcimg/aojiancc2/c5a7ff9962a44d0e93b3da1b3245c531.png) #### 其实原理也非常简单,父元素主要是 主要就是设置一个flex布局,然后flex-wrap设置为需要换行 ``` .app-container { display: flex; flex-wrap: wrap; } ``` #### 子元素主要就是设置一个宽度 子元素主要就是设置一个宽度,比如要一行显示5个就是20%,一行显示8个就是100/8=12.5%,以此类推就行了。至于其他margin-top,高度这些就是辅助样式而已。 ``` .shcoolItem { width: 20%; margin-top: 10px; margin-bottom: 20px; height: 100px; background: #ffabcd; } ``` html结构这种: ``` <div class="app-container"> <div class="shcoolItem"></div> <div class="shcoolItem"></div> <div class="shcoolItem"></div> </div> ``` #### 但是目前这种方式虽然每个子元素可以均分宽度了,一行显示完就换行,但是每块之间就没有一点间距 如果颜色设置成一样我们都看不出来,看到的就是一块,所以我们可以把每块设置一个不一样的颜色来测试 ``` <div class="app-container"> <div class="shcoolItem "></div> <div class="shcoolItem shcoolItemColor2"></div> <div class="shcoolItem shcoolItemColor3"></div> <div class="shcoolItem "></div> <div class="shcoolItem shcoolItemColor2"></div> <div class="shcoolItem shcoolItemColor3"></div> </div> <style > .app-container { display: flex; flex-wrap: wrap; } .shcoolItem { width: 20%; height: 100px; background: #ffabcd; } .shcoolItemColor2{ background: #abcdff; } .shcoolItemColor3{ background: #00cc66; } </style> ``` 效果如下,可以看到是没有间距的: ![](https://img.tnblog.net/arcimg/aojiancc2/3897a6794b36472aaa262061f9a9d585.png) ## 如何设置间距宽度呢 如果直接设置margin这种间距就会影响每行的显示了,因为我们使用了固定的宽度了,比如固定了宽度20%,设置了margin的话,每个子元素在占20%每行就显示不了5个了,我们就不好去控制它了,那么我们就不改子元素,我们直接去给子元素里边在加子元素,我们把样式设置到子元素里边的元素就行了撒。 **html结构变成了这样:** 子级里边在加了子级 ``` <div class="container"> <div class="app-container"> <div class="shcoolItem"> <div class="shcoolItemWaper"></div> </div> <div class="shcoolItem"> <div class="shcoolItemWaper"></div> </div> <div class="shcoolItem"> <div class="shcoolItemWaper"></div> </div> </div> </div> ``` **我们在子元素里边的子级去设置一个margin-left,就会有间距了** ``` .shcoolItemWaper { /* 要设置这种间距要设置到flex子元素的里边的元素,不能直接设置到flex子元素里边, 因为如果子元素算上了间距,就不能控制均分了 */ margin-left: 20px; background: #ffabcd; height: 100px; } ``` 效果如下: <img src="https://img.tnblog.net/arcimg/aojiancc2/ee4e5100eee04abba9339e2d048f3ef4.png" style="width:666px;height:auto;"> 可以看到我们左边好想并没有对齐,因为我们给每个子元素都设置了margin-left,所以就没有对齐,要对齐也非常简单在容器那边设置一个-20px就行了 ``` .app-container { display: flex; flex-wrap: wrap; margin-left: -20px; } ``` tn2>这里我们利用flex子元素里边的子元素来控制了间距,其实每个flex的子元素的宽度还是20%,每个flex子元素还是紧紧的挨到一起的,我们只是利用了flex的子元素里边元素的margin值来实现的,这样就不会影响每个flex元素的宽度,这样就比较好控制每行显示的个数了 ## 如果一行不是显示固定的个数,宽度不写死,针对不同的屏幕下在去写宽度就行了 利用`@media`去在不同分辨率下设置宽度就行了 #### 整体的代码如下(这里可以直接复制出来看效果) ``` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div class="container"> <div class="app-container"> <div class="shcoolItem"> <div class="shcoolItemWaper"></div> </div> <div class="shcoolItem"> <div class="shcoolItemWaper"></div> </div> <div class="shcoolItem"> <div class="shcoolItemWaper"></div> </div> <div class="shcoolItem"> <div class="shcoolItemWaper"></div> </div> <div class="shcoolItem"> <div class="shcoolItemWaper"></div> </div> <div class="shcoolItem"> <div class="shcoolItemWaper"></div> </div> <div class="shcoolItem"> <div class="shcoolItemWaper"></div> </div> <div class="shcoolItem"> <div class="shcoolItemWaper"></div> </div> <div class="shcoolItem"> <div class="shcoolItemWaper"></div> </div> </div> </div> </body> </html> <style> body { padding: 0; margin: 0; } .container { width: 700px; margin: 20px auto; border: 2px solid #acbdff; } .app-container { display: flex; flex-wrap: wrap; margin-left: -20px; } .shcoolItem { /* 如果一行不是显示固定的个数,这里宽度不写死,针对不同的屏幕下在去写宽度就行了 */ /* width: 20%; */ margin-top: 10px; margin-bottom: 20px; height: 100px; } .shcoolItemWaper { /* 要设置这种间距要设置到flex子元素的里边的元素,不能直接设置到flex子元素里边, 因为如果子元素算上了间距,就不能控制均分了 */ margin-left: 20px; background: #ffabcd; height: 100px; } /* 小屏下一行显示5个 */ @media screen and (min-width:100px) { .shcoolItem { width: 20%; } } /* 中屏一行显示6个 写到下面会覆盖掉上面的样式 */ @media screen and (min-width:1430px) { .shcoolItem { width: 16.66%; } } /* 大屏一行显示7个。写到下面会覆盖掉上面的样式 */ @media screen and (min-width:1799px) { .shcoolItem { width: 14.2857%; } } /* 超大屏一行显示8个。写到下面会覆盖掉上面的样式 */ @media screen and (min-width:1899px) { .shcoolItem { width: 12.5%; } } </style> ``` 小屏下一行显示5个: ![](https://img.tnblog.net/arcimg/aojiancc2/960264243d4d418f9e1b91a8b0315c1f.png) 随便改一下宽度,默认一下大一点的分辨率一行显示6个的效果: ![](https://img.tnblog.net/arcimg/aojiancc2/57af3b3ba0534085b1b298411a37cf62.png) ## 最开始贴的效果图,vue中的写法 最开始贴的效果图是在vue中的实现的,其实样式写法也是一样的,只是里边flex子元素里边的元素信息多一点,包含图片,描述等,贴一下大致代码 ``` <template> <lab-nav class="course-resources"> <div class="course-box"> <div v-for="(item, index) in courseData" :key="index" class="course-box-item" @click="goCourseDetails(item)"> <div class="course-box-item-waper"> <div class="img-waper"> <img :src="'/oss/api/ImageViewer/' + item.pic + '.jpg?percent=0.6&quality=80&od=true'"> </div> <div class="title courseName">{{ item.courseName }}</div> <div class="process-bar"> <el-progress :stroke-width="10" :percentage="Number((item.process * 100).toFixed(2))" /> </div> </div> </div> </div> </lab-nav> </template> <script> import LabNav from './components/Nav/nav.vue' import subsys_lab from '../../services/subsys_lab.js' export default { components: { LabNav }, data() { return { loadCourseParam: { PageIndex: 1, PageSize: 10000, KeyWord: '', mjdid: this.$route.params.type }, courseData: [] } }, watch: { '$route': 'loadCourseData' }, mounted() { this.loadCourseData() }, methods: { } } </script> <style scoped="scoped" lang="scss"> .course-resources { .course-box { display: flex; flex-wrap: wrap; margin-left: -20px; .course-box-item { // 宽度不写死,针对不同的屏幕下在去写宽度 //width: 20%; min-width: 160px; .course-box-item-waper:hover { box-shadow: 0px 0px 8px 0px #d3d3d3; cursor: pointer; // 图片手指上去放大 img { object-fit: cover; -webkit-transition: all .2s; transition: all .2s; -webkit-transform: scale(1.4); transform: scale(1.4); } } .course-box-item-waper { background-color: #fff; padding-bottom: 10px; margin-left: 20px; margin-bottom: 20px; .img-waper { overflow: hidden; } img { width: 100%; height: 160px; height: auto; } .title { font-size: 13px; font-family: Microsoft YaHei; font-weight: 400; color: #393939; padding: 5px; } .process-bar { padding: 5px; } } } // 小屏下一行显示5个 @media screen and (min-width:100px) { .course-box-item { width: 20%; } } // 中屏一行显示6个 写到下面会覆盖掉上面的样式 @media screen and (min-width:1430px) { .course-box-item { width: 16.66%; } } // 大屏一行显示7个。写到下面会覆盖掉上面的样式 @media screen and (min-width:1799px) { .course-box-item { width: 14.2857%; } } // 超大屏一行显示8个。写到下面会覆盖掉上面的样式 @media screen and (min-width:1899px) { .course-box-item { width: 12.5%; } } } // 下面的文字宽度超过了出现省略号 .courseName { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } } </style> ``` ## 备注,一行固定显示几个等更简单的写法 上面的实现方法只是一种实现方法而已,在很多情况下其实可以有更简单的实现,比如如果一行固定显示4个这种,布局就直接写两级就行了,不用子元素里边在去增加元素来控制。贴一下其他flex布局的应用技巧。 #### 如果只有一行的显示的话参考这个,写法比较简洁 flex 实现等宽布局且间隔相等的小技巧 https://www.tnblog.net/aojiancc/article/details/7975 #### 如果一行固定显示4个这种,布局就直接写两级就行了 参考这个里边的:flex 实现每行4个,自适应排列 https://tnblog.net/aojiancc2/article/details/7904 ### flex布局一行显示多个。flex布局固定显示n个,自适应布局 https://www.tnblog.net/aojiancc6/article/details/8094