网站已运行 163 · 17小时 · 22 · 38
目录

Shopify Liquid 响应式图片实作:image_url、image_tag 与 LCP 加载策略

Shopify Liquid 响应式图片 image_url 与 image_tag 流程示意图

Shopify Liquid 响应式图片并不是简单地把一张大图缩小显示。真正需要处理的是:让 Shopify CDN 生成合理尺寸的候选图片,让浏览器根据视口和布局选择合适文件,同时为图片保留宽高空间,并避免把首屏 LCP 图片错误地延迟加载。

本文基于 Dawn 16.0.0 和 Shopify CLI 4.7.0 做了一次本地实作:新增一个可复用的 responsive-image.liquid snippet,再由演示 Section 调用。最终 Theme Check 检查 158 个文件,结果为 0 个 error、11 个 Dawn 基线 warning,新增代码没有增加 warning。整个过程只修改本地测试副本,没有推送到营业主题。

Shopify Liquid 响应式图片需要解决哪几个问题

一张商品图在桌面双栏、平板和手机单栏中占用的实际宽度不同。如果只输出一个 1600px 的固定地址,手机也可能下载远大于显示区域的文件;如果手写多条 CDN URL,又容易遗漏尺寸、裁剪参数和后续平台变化。比较稳妥的做法是把职责拆开:

  • image_url 根据图片对象生成 Shopify CDN 地址,并规定允许使用的最大宽度或高度;
  • image_tag 输出完整的 <img>,可生成 srcsetwidthheightsizes 等属性;
  • widths 告诉 Shopify 需要哪些候选宽度;
  • sizes 告诉浏览器图片在不同布局下预计占多宽;
  • loadingfetchpriority 决定首屏和非首屏图片采用不同加载策略。

这里最容易混淆的是:widths 不是 CSS 宽度,sizes 也不会直接改变页面布局。前者生成候选文件,后者帮助浏览器从候选文件中做选择,真正的显示宽度仍由主题 CSS 和容器决定。

先写一个可复用的 responsive-image snippet

我在 Dawn 16.0.0 测试副本的 snippets 目录中新建 responsive-image.liquid。参数只保留图片对象、替代文本、可选 CSS 类和一个 eager 开关,避免让调用方每次重复一整串图片属性。

{% doc %}
  Renders a responsive Shopify image.

  @param {image} image - The Shopify image object to render.
  @param {string} alt - Alternative text for the image.
  @param {boolean} [eager] - Whether the image is the LCP candidate.
  @param {string} [class] - Optional CSS class.
{% enddoc %}

{%- if image != blank -%}
  {%- liquid
    assign image_loading = 'lazy'
    assign image_priority = 'auto'

    if eager
      assign image_loading = 'eager'
      assign image_priority = 'high'
    endif
  -%}

  {{
    image
    | image_url: width: 1600
    | image_tag:
      widths: '360, 540, 720, 960, 1200, 1600',
      sizes: '(min-width: 990px) 50vw, 100vw',
      loading: image_loading,
      fetchpriority: image_priority,
      alt: alt,
      class: class
  }}
{%- endif -%}

image_url: width: 1600 在这里设置的是输出上限。官方文档要求 image_url 至少提供 widthheight,并且不会把小于目标尺寸的原图强行放大。候选宽度也不应该超过这个上限,否则只是写了一个不会产生实际价值的数字。

在 Section 中传入图片和首屏状态

为了让 snippet 进入真实调用链,我又添加了一个演示 Section,通过 image_picker 取得图片对象,再把设置传给 snippet。这样既能验证 LiquidDoc 参数,也不会留下一个未被引用的孤立文件。

{%- if section.settings.image != blank -%}
  {% render 'responsive-image',
    image: section.settings.image,
    alt: section.settings.alt,
    eager: section.settings.eager,
    class: 'responsive-image-demo__image'
  %}
{%- endif -%}

实际项目中不建议让商家凭感觉勾选每一张图片是否属于 LCP。更常见的做法是由 Section 所处位置决定,例如只把首屏主图设为 eager。Dawn 新代码也可以结合 section.index 或具体模板结构判断,但仍要以页面真实布局为准:页面顶部的第一张图不一定就是最终 LCP 元素。

widths 与 sizes 应该怎样配合

参数本次设置实际作用
image_url width1600限制 CDN 输出的最大目标宽度
widths360–1600 六档生成不同宽度的 srcset 候选
sizes桌面 50vw,其他 100vw描述图片在当前布局中的预计占用宽度
CSS由主题组件决定最终控制页面中的显示尺寸

这组 sizes 适合“桌面双栏、移动端单栏”的示例。如果真实容器在桌面端固定为 580px,就应该写出更接近实际布局的表达式,而不是机械照抄 50vw。浏览器会同时参考视口宽度、设备像素比、sizessrcset,选择满足显示需求的候选文件。

候选档位也不是越多越好。图片容器只有 400px、800px 和 1200px 三种稳定形态时,继续添加大量相近宽度通常只会增加维护成本。先从主题断点、列宽和常见高密度屏幕推导,再用浏览器 Network 面板确认实际下载了哪个文件。

LCP 图片为什么不能统一 loading=”lazy”

Shopify 当前性能建议明确强调:首屏 LCP 候选图片不应使用懒加载,并可设置 fetchpriority="high"。原因很直接——浏览器如果等到布局阶段以后才开始请求最大内容图片,LCP 会被推迟。非首屏图片则适合使用 loading="lazy",减少初始页面竞争。

图片位置loadingfetchpriority
首屏主图或确认的 LCP 候选eagerhigh
首屏内但不是关键图按真实页面测试auto
首屏以下图片lazyauto

也不要把所有首屏图片都设成 high。资源优先级是竞争关系,多个“最高优先级”会削弱提示的意义。我的 snippet 只是提供开关,最终仍应在页面级测试中确认哪一张图真正需要优先加载。

本地 Theme Check 实测结果

第一次只新增 snippet 时,Theme Check 报出一个 OrphanedSnippet warning,因为它尚未被任何文件调用。添加演示 Section 并通过 render 引用后,这条新增 warning 消失。第二次完整检查结果如下:

Shopify Liquid 响应式图片代码与 Theme Check 0 errors 实测结果
Dawn 16.0.0 本地实测:158 个文件、0 个 error、11 个 Dawn 基线 warning,新增代码没有增加 warning。点击图片可查看原图。
  • Shopify CLI:4.7.0;
  • Dawn:16.0.0;
  • 检查文件:158 个;
  • Theme Check:0 error、11 warning;
  • 新增 snippet 和 Section:0 个新增 warning。

保留的 11 个 warning 来自 Dawn 测试基线,例如 UndefinedObjectVariableName 和已有孤立 snippet。它们不应被误写成这次响应式图片代码造成的问题。对比改动前后的结果,比只看最后一个总数更可靠。

发布前还要怎样验证生成结果

  1. 在未发布主题中加入 Section,分别选择横图和竖图,确认裁剪与容器比例符合预期;
  2. 查看页面源代码或 Elements 面板,确认输出包含 srcsetsizeswidthheight
  3. 在 360px、390px、平板和桌面宽度下检查图片没有撑宽页面;
  4. 打开 Network 面板,切换视口并禁用缓存,记录实际下载的图片宽度与 Content-Type;
  5. 用 Performance 面板确认 LCP 元素,并检查它没有 loading="lazy"
  6. 确认首屏以外图片延迟加载,不会在初始请求中抢占带宽。

Theme Check 能证明 Liquid 结构与规则没有明显错误,但它不能替代浏览器渲染和网络请求验证。本文的结论范围是“本地代码通过静态检查”,没有把未执行的在线商店性能数据写成实测提升。

几个常见错误

  • 没有为 image_url 指定宽或高:当前官方文档要求至少提供一个尺寸参数。
  • 手工拼接旧式 CDN 文件名:容易遗漏平台优化和图片对象信息,应优先使用过滤器链。
  • widths 大于 image_url 上限:上限以外的候选没有实际意义。
  • 把 sizes 当成 CSS:它只描述预期插槽宽度,不能替代主题布局样式。
  • 所有图片统一 lazy:会延迟首屏 LCP 候选图片。
  • 只看 Theme Check 总数:应对比新增代码前后的 warning,区分主题基线问题。

总结

Shopify Liquid 响应式图片的核心不是堆叠更多尺寸,而是让图片对象、CDN 候选、浏览器选择和页面加载优先级各自承担清晰职责。image_url 控制输出上限,image_tag 负责完整标记,widthssizes 配合浏览器选择文件,首屏 LCP 候选与非首屏图片则使用不同加载策略。

如果还不熟悉文件应该放在什么目录,可以先看 Dawn 主题目录结构;需要把这段图片逻辑拆成可复用组件时,可继续参考 Liquid snippet 与 render 参数实作。完成修改后,再用 Shopify Theme Check 教程核对主题基线和新增问题。

官方资料:image_url 过滤器image_tag 过滤器Shopify 主题性能最佳实践使用 Liquid 过滤器链生成图片使用宽高防止图片布局偏移(访问日期:2026 年 8 月 29 日;实测版本:Shopify CLI 4.7.0、Dawn 16.0.0)

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

目录

标签云: