🆕 Bricks 2.4 已发布:查询循环性能提升 40%,迁移教程同步更新 →

首页 / 中文教程 / 教程

Bricks 查询循环布局切换开关

教程:Bricks 查询循环布局切换开关——Bricks 附完整代码可直接复用,适合外贸独立站与 WordPress 开发者。

Ray ChanRay Chan·2026-08-12·约 3 分钟
目录
  1. 1.引言
  2. 2.DOM 结构
  3. 3.JavaScript
  4. 4.CSS
  5. 5.最终效果
  6. 6.结论

这篇教程教你:当用户点击查询循环上方的图标切换按钮时,动态改变查询循环容器的布局。

引言

想让用户自己从几种布局方案里挑一个来查看你的查询循环网格吗?

这篇教程将演示如何做到这一点——不需要外部插件、不需要 JS 库、也不需要复制内容(复制内容真的会伤 SEO 内容优化,对吧?),只需要在页面里加一小段自定义代码。

DOM 结构

按照下面的结构重建,并按下图添加类名。注意:post 容器的样式/结构完全由你决定——它不影响脚本运行。

**重要:一定要给默认选中的切换按钮加上 .toggle-layout--active 类。**这个类的样式随你喜欢。

在每个布局切换按钮上,添加下面的属性:

data-layout 属性:选一个能描述该布局的唯一名称作为值。示例中我们用了 list、list-two-col、grid。这些名字会被当作类名,加到查询容器上,用来针对特定布局给内部元素写样式。

data-layout-col 属性:填入将应用到查询容器的列数:

JavaScript

把下面的代码插入页面。个人推荐使用条件加载脚本的方法:

// 等 DOM 完全加载后再运行脚本 - 避免阻塞渲染
window.addEventListener('DOMContentLoaded', () => {
   // 查找所有带布局切换的容器
   const containers = document.querySelectorAll('.loop-ctn-w-layout-toggles');
   // 检查页面上是否有带布局切换的容器
   if (containers.length < 1) return console.log('There is no container with layout toggles on this page. Double check you correctly added the .loop-ctn-w-layout-toggles class on the main container.');
   // 遍历所有容器
   containers.forEach(container => {
      // 查找切换按钮容器
      const toggleContainer = container.querySelector('.toggle-container');
      // 检查是否有切换按钮容器
      if (!toggleContainer) return console.log('There is no toggle container. Double check you correctly added the .toggle-container class on the toggle container.');
      // 查找查询容器
      const queryContainer = container.querySelector('.query-container');
      // 检查是否有查询容器
      if (!queryContainer) return console.log('There is no query container. Double check you correctly added the .query-container class on the query container.');
      // 查找所有切换按钮
      const toggles = toggleContainer.querySelectorAll('.toggle-layout');
      // 查找当前激活的切换按钮
      const activeToggle = toggleContainer.querySelector('.toggle-layout--active');
      // 加载时设置默认布局
      queryContainer.classList.add(activeToggle.dataset.layout);
      // 检查是否有切换按钮
      if (toggles.length < 1) return console.log('There are no layout toggles. Double check you correctly added the .toggle-layout class on each toggle.');
      // 创建空数组,存放所有不同的布局类
      let layouts = [];
      // 把所有布局类填入数组
      toggles.forEach(toggle => {
         // 检查 data-layout 属性是否正确设置
         if (!toggle.dataset.layout) return console.log('The attribute data-layout has not been correctly set on the toggles.');
         layouts.push(toggle.dataset.layout);
      });
      // 遍历每个切换按钮
      toggles.forEach(toggle => {
         // 给切换按钮添加点击事件监听
         toggle.addEventListener('click', (e) => {
            // 阻止默认行为
            e.preventDefault();
            // 读取 data-layout 属性
            const layout = toggle.dataset.layout;
            // 如果已经是当前布局,避免重复执行动画
            if (queryContainer.classList.contains(layout)) return;
            // 从属性读取列数
            const col = toggle.dataset.layoutCol;
            // 检查 data-layout-col 属性是否正确设置
            if (!toggle.dataset.layoutCol) return console.log('The attribute data-layout-col has not been correctly set on the toggles.');
            // 移除现有的激活类
            toggles.forEach(el => el.classList.remove('toggle-layout--active'));
            // 给点击的切换按钮添加激活类
            toggle.classList.add('toggle-layout--active');
            // 从查询容器移除已有布局类
            queryContainer.classList.remove(...layouts);
            setTimeout(() => {
               // 给查询容器添加自定义布局类,方便进一步定制内部元素样式
               queryContainer.classList.add(layout);
               // 修改网格列数
               queryContainer.style.setProperty('--grid-column-count', col);
            }, 100);
         })
      })
   })
})

CSS

把下面的 CSS 插入页面:

.loop-ctn-w-layout-toggles .query-container {
   /* 下面的变量按需设置 */
   --grid-layout-gap: 3rem;
   --grid-column-count: 4;
   --grid-item--min-width: 280px;
   /* 变量结束 - 不要修改下面的数值 */
   display: grid;
   grid-gap: var(--grid-layout-gap);
}
@media screen and (min-width: 768px) {
   .loop-ctn-w-layout-toggles .query-container {
      --gap-count: calc(var(--grid-column-count) - 1);
      --total-gap-width: calc(var(--gap-count) * var(--grid-layout-gap));
      --grid-item--max-width: calc((100% - var(--total-gap-width)) / var(--grid-column-count));
      grid-template-columns: repeat(auto-fill, minmax(max(var(--grid-item--min-width), var(--grid-item--max-width)), 1fr));
   }
   /* 可选动画 */
   body.bricks-is-frontend .loop-ctn-w-layout-toggles .query-container .post-container {
      animation: none;
      opacity: 0;
   }
   body.bricks-is-frontend .loop-ctn-w-layout-toggles .query-container.list .post-container,
   body.bricks-is-frontend .loop-ctn-w-layout-toggles .query-container.list-two-col .post-container,
   body.bricks-is-frontend .loop-ctn-w-layout-toggles .query-container.grid .post-container {
      animation: 300ms slide-up ease-in-out forwards;
   }
   /* 可选:根据查询容器布局定制内部元素样式 */
   .loop-ctn-w-layout-toggles .query-container.list .post-container,
   .loop-ctn-w-layout-toggles .query-container.list-two-col .post-container {
      flex-direction: row;
   }
   .loop-ctn-w-layout-toggles .query-container.list .post-container img {
      width: 30%;
      max-height: 100%;
   }
   .loop-ctn-w-layout-toggles .query-container.list-two-col .post-container img {
      width: 45%;
      max-height: 100%;
   }
}
@keyframes slide-up {
   0% {
      opacity: 0;
      transform: translateY(40px);
   }
   100% {
      opacity: 1;
      transform: translateY(0);
   }
}

重要提示:

  • 这套代码基于这篇文章里的第 2 种网格方法。你可以修改前 3 个 CSS 变量来设置默认布局样式。

  • CSS 里包含一段可选的动画代码——记得把它换成你自己的布局名:

  • 这个示例中我们决定给 list 和 list-two-col 布局改 flex-direction。为此需要加几行自定义 CSS:先把布局类挂到查询容器上(如下图红色方框所示),然后定位你要改的 CSS 选择器——本例是 post 容器和特色图:

最终效果

一切设置正确的话,前端应该能看到下面的效果:

相关阅读:

结论

这个方案只靠一段 JS + 一段 CSS 就实现了查询循环的布局切换:切换按钮用 data-layout(布局名)和 data-layout-col(列数)两个属性驱动,脚本负责给查询容器切换布局类、更新 --grid-column-count 变量,CSS 用 grid 的 auto-fill + minmax 响应式算法(最小列宽 280px、断点 768px)自动排布。不需要任何外部插件或库。

💡 译者注:原文代码块中有一行 body.bricks-is-frontend,是原文抓取时残留的 markdown 链接产物,实际应为 body.bricks-is-frontend(与同段其他选择器一致),翻译时已修正。

常见误区

几个坑:一是网格/列表两种布局用两套独立 Query Loop,数据重复查、维护两份,最好用同一个 Loop 切 CSS;二是切换状态用 URL 参数还是 localStorage 要想清楚——要分享状态用 URL,要记偏好用 localStorage;三是移动端默认布局没定,小屏还强行网格挤成一团。布局切换本质是同数据换皮,切换逻辑轻、样式分清楚,体验才顺。

延伸阅读

常见问题(FAQ)

网格和列表要做两个 Query Loop 吗? 不用,同一个 Loop 切 CSS 即可,避免重复查数据、维护两份。

切换状态存 URL 还是 localStorage? 要分享链接存 URL 参数;只记本机偏好用 localStorage。

移动端怎么默认? 断点下给列表/网格设默认布局,小屏别强行网格挤成一团。

切换会重新查数据库吗? 不会,切换只换 CSS 类、数据不变,所以尽量别用两套 Loop。

Ray Chan

站长

Ray Chan

WordPress Developer & Bricks Specialist

WordPress developer with 10+ years of client builds. Switched to Bricks in 2023 — now builds fast WordPress sites and migrates legacy Elementor/Divi projects.

延伸阅读