前言
瀑布流在如今的桌面端和手機端非常常見,在2023年的今天,CSS3 Grid布局已經(jīng)非常成熟,可以放心使用,因此我們來試試使用Grid來實現(xiàn)瀑布流。
原理
動態(tài)給每個單元格設(shè)置grid-row即可。
注意事項
本方案的核心就是
grid-row,本范例只考慮了圖片是單元格里的唯一元素,如果你的單元格有更復(fù)雜的內(nèi)容,你需要想辦法計算正確的grid-row。圖片作為單元格內(nèi)唯一元素的話,后端接口應(yīng)當傳遞圖片的寬和高,這就要求圖片上傳的時候就儲存下寬和高,否則的話,需要前端動態(tài)計算圖片寬高,就很沒有必要了。但是,本范例也演示了前端如何獲取圖片寬和高。
想要運行范例代碼,你需要在/assets/目錄存放19張圖片,命名從1.jpg到19.jpg。
全部代碼
<template>
<div v-if="show" id="waterfall-container">
<div
v-for="item in imgList"
:key="item"
class="waterfall-item"
:style="{ gridRow: item.gridRow }"
>
<img :src="item.src" />
</div>
</div>
</template>
<script>
export default {
data() {
return {
imgList: [...Array(19 - 1 + 1).keys()].map((e) => {
return {
id: e + 1,
src: require("@/assets/" + (e + 1) + ".jpg"),
height: 0,
gridRow: "",
};
}),
show: false,
};
},
created() {
this.computeGridRow();
},
methods: {
computeGridRow() {
let count = this.imgList.length;
this.imgList.forEach((img) => {
let image = new Image();
image.src = img.src;
image.onload = () => {
img.gridRow =
"auto / span " + Math.round((image.height * 200) / image.width);
count -= 1;
if (!count) {
this.show = true;
}
};
});
},
},
};
</script>
<style lang="scss">
$root-font-size: 10px;
$grid-gap: 1.6rem;
// 假設(shè)1920px屏幕打算顯示6列
$column-count-1920: 6;
// 這里采用1900px是因為要排掉滾動條寬度,通常是17px,這里多排除一些,所以1920px減掉20px
$minmax-1920: (
(1900px / $root-font-size) * 1rem - ($grid-gap * ($column-count-1920 + 1))
) / $column-count-1920;
// 假設(shè)手機屏幕打算顯示2列
$column-count-480: 2;
// 480的意思是目前世界上最大的手機分辨率寬度是低于480px,
// 所以@media screen and (max-device-width: 480px)使用480px。
// 這里采用360px是保證360px的老式手機依然能看到雙列瀑布流
$minmax-480: (
(360px / $root-font-size) * 1rem - ($grid-gap * ($column-count-480 + 1))
) / $column-count-480;
// 如果你要在平板上有合理的顯示效果,你應(yīng)該添加更多的變量和@media規(guī)則,但本范例不再舉例
html {
font-size: $root-font-size;
}
body {
margin: 0;
}
#waterfall-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax($minmax-1920, 1fr));
column-gap: $grid-gap;
box-sizing: border-box;
margin: 0 auto;
padding: $grid-gap;
max-width: (1920px / $root-font-size) * 1rem;
.waterfall-item {
box-sizing: border-box;
padding-bottom: $grid-gap;
width: 100%;
height: 100%;
transition: all 0.3s;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
}
@media screen and (max-device-width: 480px) {
#waterfall-container {
grid-template-columns: repeat(auto-fill, minmax($minmax-480, 1fr));
}
}
</style>