flex平铺布局_flex布局⾃适应靠左对齐
需求
假设我有5个300px*300px的卡⽚,需要根据屏幕宽度⾃适⽤平铺排列,并在换⾏的时候靠左对齐。
不能⽤js实现,⽤js就太简单了,⽽且代码会⽐较啰嗦和让⼈困扰。
核⼼知识
利⽤flex容器的justify-content: flex-start和flex-wrap: wrap完成⾃动换⾏靠左需求
利⽤calc和margin-left完成⼦项⽬平铺需求
单单利⽤justify-content: space-evenly完成不了需求
直觉上,利⽤这个属性和wrap就可以满⾜,但实际上不可以,因为会每⾏各⾃计算空隙,这样会导致最后⼀⾏对不齐,效果如下
利⽤flex-start和margin-left: calc实现
1. 数学公式
flex-start可以满⾜我们靠左对齐的需求。接下来,我们只要完成间距的需求就可以了。⼦项⽬宽度是固定的300px,那么根据容器的宽度,肯定就能计算出来间距了,例如宽1000px的容器,那肯定只能容纳3个⼦项⽬,剩余100px空间,⼀个四个空隙,那每个空隙就是25px。
conWidth 容器宽度
itemWidth ⼦项⽬宽度
每⾏⼦项⽬个数 n = Math.floor(conWidth/itemWidth)
嗯,貌似是搞定了,我们转化成css中calc就是:
margin-left: calc((100% - Math.floor(100% / 300px) * 300px) / Math.floor(100% / 300px))
复制代码
css布局左边固定右边自适应但是,calc根本不⽀持这样:
calc没有Math.floor⽅法
calc中除法后⾯必须是数字
2. 利⽤@media 媒体查询解决每⾏个数问题
既然⽆法通过calc直接计算出来n,那就想办法跳过这⼀步。这样我们只需要完成左边的公式就⾏了。
嗯,因为我们⼦项⽬是定宽的300px,那么:容器少于900px,就只能放2个,少于1200px,就只能放3个。。。。 多写⼏个类似下⾯的媒体查询就可以了
@media screen and (max-width: 1200px) and (min-width: 900px) {
item { --n: 3; }
}
复制代码
然后我们的margin-left就可以简化成如下calc⽀持的左边的公式了
margin-left: calc((100% - var(--itemWidth) * var(--n)) / (var(--n) + 1));
复制代码
3. 最终代码
html
1
2
3
4
5
/div>
复制代码
css
.container {
background: gold;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
}
item {
outline: 1px solid black;
height: 300px;
background: red;
margin-top: 20px;
--itemWidth: 300px; /* 和项⽬宽度⼀致 */
width: calc(var(--itemWidth));
margin-left: calc((100% - var(--itemWidth) * var(--n)) / (var(--n) + 1)); }
@media screen and (max-width: 900px) {
item { --n: 2; }
}
@media screen and (max-width: 1200px) and (min-width: 900px) { item { --n: 3; }
}
@media screen and (max-width: 1500px) and (min-width: 1200px) { item { --n: 4; }
}
@media screen and (max-width: 8888px) and (min-width: 1500px) {
item { --n: 5; } /* 最多⼀⾏显⽰五个 */
}
复制代码
通过缩放浏览器观察,已经实现⾃适⽤屏幕宽度了。
1. float布局也可以这样解决
思路⼀样,但是flex的其他特性就使⽤不了了
2. 如果⽆法使⽤css中的var,例如ie浏览器
那就只要把margin-left整体写到@media 媒体查询⾥即可
3. 使⽤grid布局更简单
如果使⽤grid布局,calc都不需要⽤到了,只要在@media中写好grid样式,在不同宽度下有不同列数即可
请看我的另外⼀篇⽂章
4. 可以简化公式
直接每个项⽬宽度 100% / n 即可,但是那样html代码就会很啰嗦,每个⼦项⽬都需要再套⼀层,作为真正的flex项⽬使⽤。