Masonry 瀑布流布局
CSS columns 实现的瀑布流;自动列数(基于 minColumnWidth)或固定列数;零 JS 布局开销。
基础用法
底层用浏览器原生 columns: N + break-inside: avoid——零 JS 布局开销,只用 useResizeObserver 在容器宽度变化时重算列数。子元素填充顺序是 top-to-bottom-left-to-right(与严格”最短列优先”略不同,但在 95% 场景视觉等价),但渲染足够流畅,且 SSR 友好。
背景 视口
#1 · 120px
#2 · 80px
#3 · 160px
#4 · 100px
#5 · 140px
#6 · 180px
#7 · 90px
#8 · 130px
#9 · 110px
#10 · 170px
#11 · 95px
#12 · 150px
#13 · 125px
<script setup lang="ts">
import { CfMasonry } from '@chufix-design/vue';
const heights = [120, 80, 160, 100, 140, 180, 90, 130, 110, 170, 95, 150, 125];
const palette = ['#5b8def', '#52c41a', '#fa8c16', '#eb2f96', '#13c2c2', '#722ed1'];
</script>
<template>
<CfMasonry :min-column-width="160" :gap="8">
<div
v-for="(h, i) in heights"
:key="i"
class="demo-card"
:style="{ height: `${h}px`, background: palette[i % palette.length] }"
>#{{ i + 1 }} · {{ h }}px</div>
</CfMasonry>
</template>
<style scoped>
.demo-card { display: flex; align-items: center; justify-content: center; color: white; font-weight: 600; border-radius: var(--r-4); }
</style> <script setup>
import { CfMasonry } from '@chufix-design/vue';
const heights = [120, 80, 160, 100, 140, 180, 90, 130, 110, 170, 95, 150, 125];
const palette = ['#5b8def', '#52c41a', '#fa8c16', '#eb2f96', '#13c2c2', '#722ed1'];
</script>
<template>
<CfMasonry :min-column-width="160" :gap="8">
<div
v-for="(h, i) in heights"
:key="i"
class="demo-card"
:style="{ height: `${h}px`, background: palette[i % palette.length] }"
>#{{ i + 1 }} · {{ h }}px</div>
</CfMasonry>
</template>
<style scoped>
.demo-card { display: flex; align-items: center; justify-content: center; color: white; font-weight: 600; border-radius: var(--r-4); }
</style> import { CfMasonry } from '@chufix-design/react';
export default function Demo() {
const heights = [120, 80, 160, 100, 140, 180, 90, 130, 110, 170, 95, 150, 125];
const palette = ['#5b8def', '#52c41a', '#fa8c16', '#eb2f96', '#13c2c2', '#722ed1'];
return (
<>
<CfMasonry minColumnWidth={160} gap={8}>
<div v-for="(h, i) in heights" key={i} className="demo-card" style={{ height: `${h}px`, background: palette[i % palette.length] }} >#{i + 1} · {h}px</div>
</CfMasonry>
</>
);
} import { CfMasonry } from '@chufix-design/react';
export default function Demo() {
const heights = [120, 80, 160, 100, 140, 180, 90, 130, 110, 170, 95, 150, 125];
const palette = ['#5b8def', '#52c41a', '#fa8c16', '#eb2f96', '#13c2c2', '#722ed1'];
return (
<>
<CfMasonry minColumnWidth={160} gap={8}>
<div v-for="(h, i) in heights" key={i} className="demo-card" style={{ height: `${h}px`, background: palette[i % palette.length] }} >#{i + 1} · {h}px</div>
</CfMasonry>
</>
);
} API
| 属性 | 类型 | 默认 | 说明 |
|---|---|---|---|
columns | number | 自动 | 固定列数,优先于 minColumnWidth |
minColumnWidth | number | 240 | 自动列数模式下的列最小宽度(px) |
gap | number | 12 | 列间距 + 行间距(px) |
反馈与讨论
Masonry 瀑布流布局 的讨论