flex布局是我们开发中很常用的一种布局模式,他可以快速实现一些我们需要的布局结构,相比传统的定位布局节省很多代码,相信大多数小伙伴都是用得得心应手了,如果用一般css写flex布局,会涉及很多宽度高度的计算,带来许多烦恼,本文将带领小伙伴用less来快速实现flex布局.
-
布局需求
想象这样一个需求,一个大盒子里面有十个正方形小盒子,我们需要小盒子在大盒子里面整齐排列,不管是一行两个、一行三个、一行四个还是五个,都要整齐排列,并且每行第一个最后一个紧挨着大盒子,每行所有盒子间隔一共50px,想象一下这个功能用css将会有多复杂,而less中的变量和函数将会为我们带来极大便利,接下来,我将带领小伙伴们用less快速实现。
-
less解决方案
HTMLl结构及切换每行小盒子数逻辑:
<button class="toggle">切换</button>
<ul class="box">
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
</ul>
let btn = document.querySelector('.toggle');
let box = document.querySelector('.box');
let count = 1;
const update = () => {
count += 1;
if (count > 5) {
count = 1;
}
if (count === 1) {
btn.innerHTML = "未指定"
box.className = "box"
} else {
btn.innerHTML = `每行${count}个`;
box.className = `box col-${count}`
}
}
btn.addEventListener('click',update);
设置初始化样式:
* {
margin:0px;
padding: 0px;
box-sizing: border-box;
}
.box {
width: 600px;
margin: 100px auto;
outline: 1px solid;
display: flex;
flex-wrap: wrap;
list-style: none;
align-content: flex-start;
.item {
width: 100px;
border: 1px solid;
height: 100px;
background-color: pink;
}
}
考虑到切换布局后,每行所有小盒子的间隔总共为50px,我们可以用一个变量@restSpace来保存,每行小盒子数为@length,那么下盒子的间隔就是@restSpace/(@length - 1) * 1px,每个小盒子的高度便为(600 - @restSpace) / @length * 1px,利用less的函数特性,小盒子样式为:
@restSpace:50;
.demo (@length) {
@margin:(@restSpace) / (@length - 1) * 1px;
width:(600 - @restSpace) / @length * 1px;
margin-right:@margin;
margin-bottom:@margin;
// 每行最后一个小盒子右外边距为 0px
&:nth-of-type(@{length}n) {
margin-right: 0px;
}
}
当点击切换后,首先每行显示两个小盒子,外层盒子class="box col-2",那么此时页面布局样式在前面基础上加上:
.box {
&.col-2 .item {
// 调用上面小盒子的样式函数,传入每行两个盒子
.demo(2);
}
}
上效果图:
考虑到布局的变换,每行小盒子数量会变化,我们将上一步封装为函数,传入每行小盒子的数量,并循环创建每行两个、三个、四个、五个盒子情况下的样式:
// @i:2 从每行两个小盒子开始
.demoPro(@length,@i:2) when (@i <= @length){
// .col-@{i} 根据每行小盒子数拼接class名
&.col-@{i} .item {
.demo(@i);
}
.demoPro(@length,@i + 1);
}
// @length为5,循环创建每行2-5个盒子布局的样式
.demoPro(5);
至此,我们的所有对应的布局全部完成,看看效果吧:
可以看到,不管是每行两个、三个、四个还是五个,整个布局都是整齐协调的,且每行第一个第一个和最后一个紧挨着外层盒子,每行所有间隔总和不变,每个小盒子随着布局伸缩,这就是
less的变量以及函数的特性带来的好处,可以节省很多css代码,且计算方便。
-
less完整代码
下面我们来看一看完整的less代码:
*{
margin:0px;
padding: 0px;
box-sizing: border-box;
}
.toggle {
display: block;
margin: 30px auto;
width: 100px;
}
.box {
width: 600px;
margin: 100px auto;
outline: 1px solid;
display: flex;
flex-wrap: wrap;
list-style: none;
align-content: flex-start;
.item {
width: 100px;
border: 1px solid;
height: 100px;
background-color: pink;
}
@restSpace:50;
.demo (@length) {
@margin:(@restSpace) / (@length - 1) * 1px;
width:(600 - @restSpace) / @length * 1px;
margin-right:@margin;
margin-bottom:@margin;
&:nth-of-type(@{length}n) {
margin-right: 0px;
}
}
.demoPro(@length,@i:2) when (@i <= @length){
&.col-@{i} .item {
.demo(@i);
}
.demoPro(@length,@i + 1);
}
.demoPro(5);
}
-
css代码
为了方便理解以及对比,我把css实现代码(根据less生成)附在后面,以供小伙伴们参考:
* {
margin: 0px;
padding: 0px;
box-sizing: border-box;
}
.toggle {
display: block;
margin: 30px auto;
width: 100px;
}
.box {
width: 600px;
margin: 100px auto;
outline: 1px solid;
display: flex;
flex-wrap: wrap;
list-style: none;
align-content: flex-start;
}
.box .item {
width: 100px;
border: 1px solid;
height: 100px;
background-color: pink;
}
.box.col-2 .item {
width: 275px;
margin-right: 50px;
margin-bottom: 50px;
}
.box.col-2 .item:nth-of-type(2n) {
margin-right: 0px;
}
.box.col-3 .item {
width: 183.33333333px;
margin-right: 25px;
margin-bottom: 25px;
}
.box.col-3 .item:nth-of-type(3n) {
margin-right: 0px;
}
.box.col-4 .item {
width: 137.5px;
margin-right: 16.66666667px;
margin-bottom: 16.66666667px;
}
.box.col-4 .item:nth-of-type(4n) {
margin-right: 0px;
}
.box.col-5 .item {
width: 110px;
margin-right: 12.5px;
margin-bottom: 12.5px;
}
.box.col-5 .item:nth-of-type(5n) {
margin-right: 0px;
}
-
总结
Less使用嵌套,使得代码更短、更干净,层级关系更明确,易度性强,加之其提供了一系列运算符、变量、函数等,使布局样式的编更快,更省时,更易于维护。事实上,在绝大多数情况下,较之css来得更加的优雅,初用时就会觉得徒增麻烦,后面就会发现是真的——香!!!
本文是来自前端菜鸟自学前端过程中的第一篇技术博客,是我用less实现flex布局的一种解决方案,当然还有其他方案,也还有更佳方案,本文仅是我的一种想法,如有纰漏,还请见谅,欢迎来评论区交流。