Skip to content

调试半天,原来一个插件就能搞定流式布局,还是能自定义那种

今天开发一个首页,领导表示要百度图片那种效果,能长能短,能满满当当的填充整个页面。

好久没有鼓捣这种东西了,原来流式布局这么简单。

css解决方案

使用 CSS Grid + grid-auto-rows 实现简易流式布局,不依赖 JS,简洁易维护。

html
<div class="card-conatiner">
    <div class="card-item">内容</div>
</div>

<style>
.card-conatiner {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 16px;
}

.card-item {
    transition: all 0.3s ease;
}
</style>

但是这个方案缺陷比较多,虽然简单,但是没办法覆盖动态宽高的情况。而且这里内容是图片的话,还存在加载以后样式错乱的问题。

Masonry.js插件一步解决

费了半天劲,结果效果不是太好。上网一搜,竟然有个插件专门解决这个问题。

shell
# 安装
npm install masonry-layout
html
<template>
  <div ref="gridContainer" class="grid">
    <div v-for="(item, index) in cards" :key="index" class="grid-item">
      内容
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick } from 'vue';
import Masonry from 'masonry-layout';

const cards = ref([
  { title: '卡片1', content: '这是扩展内容...', expanded: false },
  { title: '卡片2', content: '更多文字内容...', expanded: false },
]);
const gridContainer = ref(null);
let msnry = null;

const toggleExpand = async (index) => {
  cards.value[index].expanded = !cards.value[index].expanded;
  await nextTick(); // 等待 DOM 更新
  msnry.layout(); // 重新计算布局
};

onMounted(() => {
  msnry = new Masonry(gridContainer.value, {
    itemSelector: '.grid-item',
    columnWidth: 250,
    gutter: 16,
    percentPosition: true,
  });
});
</script>

<style scoped>
.grid {
  margin: 0 auto;
}

.grid-item {
  width: 250px;
  margin-bottom: 16px;
}
</style>

效果非常棒,而且配置简单。

简单罗列一下API:

js
{
    itemSelector: '.grid-item', //附加选择器,用来指定哪些元素包裹的元素会重新排列。
    columnWidth: 200, //1列网格的宽度,单位为像素(px), 默认: 第一个浮动元素外宽度。
    percentPosition:true, //将元素定位设成百分比。true后,元素宽度自动适应容器的尺寸变化。
    gutter: 10, //元素水平方向的间隙
    horizontalOrder: true,
    singleMode: false,
    //禁用测量每个浮动元素的宽度。如浮动元素具有相同的宽度,设为true。默认 false。
    resizeable: true, // 绑定一个Masonry访问,窗口resize时布局平滑流动。默认:true。
    animate: true, // 布局重排动画。默认:false。
    animationOptions: {}, 
    //一对动画选项,具体参数可以参考jquery .animate()中的options选项。
    appendedContent: $('.new_content'),
    //  附加选择器元素,用来尾部追加内容。
    // 在集成infinitescroll插件的情况下使用。
    saveOptions: true,
    // 默认情况下,Masonry 将使用以前Masonry使用过的参数选项,所以你只需要输入一次选项。
    // 默认:true
    stamp:'.grid-stamp',
    // 网格中的固定元素,不会因重新布局改变位置,移动元素填充到固定元素下方
    fitWidth: true, // 设置网格容器宽度等于网格宽度,这样配合css的auto margin实现居中显示
    originLeft: true, // 默认true网格左对齐,设为false变为右对齐
    originTop: true, // 默认true网格对齐顶部,设为false对齐底部
    containerStyle: { position: 'relative' }, // 设置容器样式
    stagger: '0.03s', 
    //重布局时网格并不是一起变换的,排在后面的网格比前一个延迟开始,该项设置延迟时间  
    initLayout: true, //初始化布局,设未true可手动初试化布局
}