网站已运行 162 · 20小时 · 41 · 31
目录

Shopify Section 和 Block 入门:Dawn 主题结构与实作

Shopify Dawn Section 容器与可排序 Block 卡片示意图

Shopify Section 和 Block 到底是什么?第一次打开 Dawn 主题源码时,最容易困惑的并不是 Liquid 语法,而是页面为什么被拆成 templatessectionssnippets,以及主题编辑器里的一个“区段”和几个可拖动内容项,分别对应哪段代码。

本文使用我在 2026 年 8 月 21 日拉取的 Shopify 官方 Dawn 16.0.0 源码做说明,先拆解 sections/multicolumn.liquid,再写一个可以添加、删除和排序内容项的简单 Section。随后我把示例放进真实开发商店的未发布 Dawn 副本,完成文件写入、schema 翻译、Block 排序、桌面端和移动端预览。示例代码已经通过 Shopify Liquid 校验,线上 Dawn 没有被修改。

先看结论:Section、Block 和 schema 各负责什么

  • Section:页面上的一个可配置模块,对应主题 sections 目录中的一个 .liquid 文件。
  • Block:Section 内部可重复、可排序的内容单元,例如多列内容中的一列、轮播图中的一张幻灯片。
  • schema:Section 文件中的 JSON 配置,告诉主题编辑器要显示哪些设置、允许哪些 Block,以及这个 Section 能否由用户添加。
  • preset:Section 被添加到页面时使用的初始配置。没有合适的 preset,Section 通常不会按预期出现在“添加区段”列表中。

Shopify 官方文档说明,Section 是可复用、可由商家配置的 Liquid 模块;它可以包含 Block,让用户在一个 Section 内添加、删除和重新排序内容。JSON 模板负责决定某个页面使用哪些 Section,而 Section 文件负责每个模块如何输出。

本文说的 Block,先限定为 Section 内定义的 Block

当前 Shopify 主题架构里还存在独立放在 blocks 目录中的 Theme Block。它们可以在不同 Section 中复用,和 Dawn 许多现有 Section 里直接写在 schema 中的 Block 不是同一种组织方式。

Dawn 16.0.0 的 multicolumn.liquid 仍然使用 Section 内定义的 column Block。为了先把最常见的 Dawn 定制流程讲清楚,本文只处理这种结构,不把 Theme Block、App Block 和 Section Block 混在一个示例里。后续需要做跨 Section 复用时,再单独讨论 blocks 目录和 content_for

从 Dawn 的 multicolumn.liquid 看懂完整链路

Dawn 的“多列”模块适合用来理解 Section 与 Block:主题编辑器里的一整个多列区域是 Section,其中每一列都是一个 Block。文件可以分成三段来看。

1. 用 section.settings 读取整个模块的设置

标题、列数、图片比例、对齐方式等属于整个 Section 的配置,读取时使用 section.settings.设置ID。这些设置只配置一次,但会影响 Section 中的多个 Block。

2. 遍历 section.blocks 输出每个内容项

{%- for block in section.blocks -%}
  <li {{ block.shopify_attributes }}>
    <h3>{{ block.settings.title }}</h3>
    <div class="rte">{{ block.settings.text }}</div>
  </li>
{%- endfor -%}

section.blocks 是当前 Section 的 Block 列表,循环中的 block.settings 读取每一个 Block 自己的标题和正文。{{ block.shopify_attributes }} 也不能随手删掉:它让主题编辑器能够识别、选择和拖动对应的 Block。

3. 在 schema 中定义设置、Block 和 preset

文件底部的 {% schema %} 只允许包含有效 JSON。settings 定义整个 Section 的选项,blocks 定义允许添加的内容项,max_blocks 限制数量,presets 则给出添加模块时的初始状态。一个 Section 文件只能有一个 schema 标签,而且不能把它嵌套在其他 Liquid 标签中。

实作:创建一个可排序的“三个要点”Section

下面这个示例保留最必要的结构:一个 Section 标题,最多六个要点 Block,桌面端三列、手机端单列。新建文件 sections/szymwp-key-points.liquid,加入以下内容。

<div class="szymwp-key-points page-width">
  {%- if section.settings.heading != blank -%}
    <h2 class="szymwp-key-points__heading">{{ section.settings.heading }}</h2>
  {%- endif -%}

  <ul class="szymwp-key-points__grid" role="list">
    {%- for block in section.blocks -%}
      <li class="szymwp-key-points__item" {{ block.shopify_attributes }}>
        {%- if block.settings.title != blank -%}
          <h3>{{ block.settings.title }}</h3>
        {%- endif -%}

        {%- if block.settings.text != blank -%}
          <div class="rte">{{ block.settings.text }}</div>
        {%- endif -%}
      </li>
    {%- endfor -%}
  </ul>
</div>

{% stylesheet %}
  .szymwp-key-points__heading {
    margin-block-end: 2rem;
  }

  .szymwp-key-points__grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .szymwp-key-points__item {
    padding: 1.5rem;
    border: 1px solid rgba(var(--color-foreground), 0.15);
    border-radius: var(--text-boxes-radius);
  }

  .szymwp-key-points__item h3 {
    margin-block: 0 0.75rem;
  }

  @media screen and (max-width: 749px) {
    .szymwp-key-points__grid {
      grid-template-columns: 1fr;
    }
  }
{% endstylesheet %}

{% schema %}
{
  "name": "t:sections.szymwp_key_points.name",
  "settings": [
    {
      "type": "inline_richtext",
      "id": "heading",
      "label": "t:sections.szymwp_key_points.settings.heading.label",
      "default": "t:sections.szymwp_key_points.settings.heading.default"
    }
  ],
  "max_blocks": 6,
  "blocks": [
    {
      "type": "point",
      "name": "t:sections.szymwp_key_points.blocks.point.name",
      "settings": [
        {
          "type": "inline_richtext",
          "id": "title",
          "label": "t:sections.szymwp_key_points.blocks.point.settings.title.label",
          "default": "t:sections.szymwp_key_points.blocks.point.settings.title.default"
        },
        {
          "type": "richtext",
          "id": "text",
          "label": "t:sections.szymwp_key_points.blocks.point.settings.text.label",
          "default": "t:sections.szymwp_key_points.blocks.point.settings.text.default"
        }
      ]
    }
  ],
  "presets": [
    {
      "name": "t:sections.szymwp_key_points.presets.name",
      "blocks": [
        { "type": "point" },
        { "type": "point" },
        { "type": "point" }
      ]
    }
  ]
}
{% endschema %}
Shopify Dawn 主题代码编辑器中的自定义 Section 文件
在未发布的 Dawn 副本中添加 szymwp-key-points.liquid,代码编辑器能够识别 Liquid 文件。

示例使用 schema 翻译键,避免把主题编辑器文案直接写死。在 Dawn 的 locales/en.default.schema.json 中,把下面的 szymwp_key_points 节点合并到现有 sections 对象中。其他语言可以在相应的 *.schema.json 文件里添加同样的键。

"szymwp_key_points": {
  "name": "Key points",
  "settings": {
    "heading": {
      "label": "Heading",
      "default": "Key points"
    }
  },
  "blocks": {
    "point": {
      "name": "Point",
      "settings": {
        "title": {
          "label": "Title",
          "default": "Point title"
        },
        "text": {
          "label": "Text",
          "default": "<p>Add a short explanation.</p>"
        }
      }
    }
  },
  "presets": {
    "name": "Key points"
  }
}

这里没有把列数做成设置,是有意控制示例范围。刚开始写 Section 时,先保证内容结构、主题编辑器操作和手机端布局正确,再逐步增加真正需要的选项;一次放入太多颜色、间距和动画设置,后面反而更难维护。

代码里的几个关键点

  • 先判断 blank:标题或正文为空时不输出空标签,减少无意义的 HTML。
  • 保留 block.shopify_attributes:否则编辑器中选择和拖动 Block 可能不正常。
  • 使用 role=”list”:配合移除默认列表样式后,仍保留清晰的列表语义。
  • CSS 放在 stylesheet 标签中:样式跟随组件维护;标签内部不能使用 Liquid 动态输出。
  • 手机端改为单列:避免三列内容在窄屏被挤压,也不会让整页产生横向滚动。
  • preset 预置三个 Block:添加 Section 后立刻能看到结构,再按需要增删和排序。

在未发布 Dawn 副本中完成真实验证

代码校验通过并不等于店面验证完成。这次我没有直接修改线上主题,而是在开发商店中复制当前 Dawn,确认副本保持 Draft 后再写入文件和首页模板。

Shopify Dawn 主题编辑器中的 Key points Section 和 Block 排序
Key points Section 已加入首页模板,左侧可以看到三个 Block 及调整后的顺序;顶部的 Draft 表示测试主题未发布。
  1. 在 Themes 中复制当前 Dawn,并确认副本显示为 Draft
  2. 加入 szymwp-key-points.liquid,同时合并 schema 翻译键;
  3. 把 Key points Section 加入首页模板,由 preset 生成三个 Point Block;
  4. 把“Schema powers the editor”拖到第一位,确认 Block 顺序和预览同步变化;
  5. 选择单个 Block,在右侧修改标题和正文,确认编辑器能够定位对应卡片;
  6. 切换移动端预览,检查卡片是否从桌面三列变成单列;
  7. 核对副本仍为 Draft,未执行发布,也没有替换线上 Dawn。
Shopify Dawn 主题编辑器的 Block 设置与桌面端预览
选中第一个 Block 后,右侧可以独立编辑标题和正文,桌面端预览同步显示三列内容。

桌面端实际输出与预期一致:Section 标题只出现一次,三个 Block 各自读取自己的 block.settings,选中状态也能通过 block.shopify_attributes 正确关联到编辑器。

Shopify Dawn 自定义 Section 在移动端的单列预览
切换到主题编辑器的移动端预览后,三个 Block 由三列改为单列,没有把页面横向撑开。

这组截图来自本站自己的开发商店和未发布主题,分别证明了文件写入、Section 与 Block 层级、Block 排序、设置面板、桌面端输出和移动端单列布局。测试完成后主题仍保持 Draft,因此不会影响正在使用的线上主题。

常见错误

schema 不是有效 JSON

schema 里不能写 JSON 注释,最后一个数组项或对象属性后也不能多逗号。一个 Section 只能有一个 {% schema %},并且不能放进 iffor 等 Liquid 标签内部。

schema 定义了 Block,却没有循环输出

主题编辑器能添加 Block,不代表前台会自动显示。Section 主体仍然需要遍历 section.blocks,并按 Block 类型和设置输出 HTML。

复制 Dawn 文件后直接大改

直接修改体积很大的 main-product.liquidheader.liquid,短期看起来省事,升级和排错时成本会很高。先用独立、用途明确的小 Section 验证结构,更容易回滚,也更容易比较 Dawn 更新前后的差异。

和开发商店选择有什么关系

主题代码最好在专门的开发环境中验证,不要把客户正在营业的商店当作练习场。如果还没有确定应该使用 Dev store、Client transfer store 还是 Collaboration,可以先看本站的Shopify 开发商店类型对比。本文这种 Dawn 组件开发和反复测试,更适合在自己的 Dev store 或未发布主题中完成。

总结

理解 Dawn 的 Section 和 Block,可以先抓住一条链路:schema 定义主题编辑器中的选项,section.settings 读取整个模块的配置,section.blocks 遍历可排序内容项,block.settings 读取单个内容项的数据,block.shopify_attributes 则把输出结果和主题编辑器关联起来。

先从一个小而完整的 Section 开始,比直接改 Dawn 的大型核心文件更容易验证。本次把示例部署到未发布的 Dawn 副本后,已经确认 Section 可以加入模板,Block 可以独立编辑和排序,桌面端为三列,移动端预览切换为单列;测试主题仍保持 Draft,线上主题没有被替换或发布。

如果你已经完成代码层面的 Section 和 Block 实作,接下来可以用Shopify 主题编辑器使用教程核对模板范围、共享区域和发布前的操作顺序。

参考资料:Shopify.dev《Sections》Shopify.dev《Section schema》Shopify.dev《Blocks》Shopify 官方 Dawn 仓库(访问日期:2026 年 8 月 21 日;本地核对版本:Dawn 16.0.0,提交 258f00f

数臻源码猫咪图标
目录
数臻源码猫咪图标

目录

标签云: