Shopify Liquid 响应式图片实作:image_url、image_tag 与 LCP 加载策略
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>,可生成srcset、width、height、sizes等属性;widths告诉 Shopify 需要哪些候选宽度;sizes告诉浏览器图片在不同布局下预计占多宽;loading与fetchpriority决定首屏和非首屏图片采用不同加载策略。
这里最容易混淆的是: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 至少提供 width 或 height,并且不会把小于目标尺寸的原图强行放大。候选宽度也不应该超过这个上限,否则只是写了一个不会产生实际价值的数字。
在 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 width | 1600 | 限制 CDN 输出的最大目标宽度 |
widths | 360–1600 六档 | 生成不同宽度的 srcset 候选 |
sizes | 桌面 50vw,其他 100vw | 描述图片在当前布局中的预计占用宽度 |
| CSS | 由主题组件决定 | 最终控制页面中的显示尺寸 |
这组 sizes 适合“桌面双栏、移动端单栏”的示例。如果真实容器在桌面端固定为 580px,就应该写出更接近实际布局的表达式,而不是机械照抄 50vw。浏览器会同时参考视口宽度、设备像素比、sizes 和 srcset,选择满足显示需求的候选文件。
候选档位也不是越多越好。图片容器只有 400px、800px 和 1200px 三种稳定形态时,继续添加大量相近宽度通常只会增加维护成本。先从主题断点、列宽和常见高密度屏幕推导,再用浏览器 Network 面板确认实际下载了哪个文件。
LCP 图片为什么不能统一 loading=”lazy”
Shopify 当前性能建议明确强调:首屏 LCP 候选图片不应使用懒加载,并可设置 fetchpriority="high"。原因很直接——浏览器如果等到布局阶段以后才开始请求最大内容图片,LCP 会被推迟。非首屏图片则适合使用 loading="lazy",减少初始页面竞争。
| 图片位置 | loading | fetchpriority |
|---|---|---|
| 首屏主图或确认的 LCP 候选 | eager | high |
| 首屏内但不是关键图 | 按真实页面测试 | auto |
| 首屏以下图片 | lazy | auto |
也不要把所有首屏图片都设成 high。资源优先级是竞争关系,多个“最高优先级”会削弱提示的意义。我的 snippet 只是提供开关,最终仍应在页面级测试中确认哪一张图真正需要优先加载。
本地 Theme Check 实测结果
第一次只新增 snippet 时,Theme Check 报出一个 OrphanedSnippet warning,因为它尚未被任何文件调用。添加演示 Section 并通过 render 引用后,这条新增 warning 消失。第二次完整检查结果如下:
- Shopify CLI:4.7.0;
- Dawn:16.0.0;
- 检查文件:158 个;
- Theme Check:0 error、11 warning;
- 新增 snippet 和 Section:0 个新增 warning。
保留的 11 个 warning 来自 Dawn 测试基线,例如 UndefinedObject、VariableName 和已有孤立 snippet。它们不应被误写成这次响应式图片代码造成的问题。对比改动前后的结果,比只看最后一个总数更可靠。
发布前还要怎样验证生成结果
- 在未发布主题中加入 Section,分别选择横图和竖图,确认裁剪与容器比例符合预期;
- 查看页面源代码或 Elements 面板,确认输出包含
srcset、sizes、width和height; - 在 360px、390px、平板和桌面宽度下检查图片没有撑宽页面;
- 打开 Network 面板,切换视口并禁用缓存,记录实际下载的图片宽度与 Content-Type;
- 用 Performance 面板确认 LCP 元素,并检查它没有
loading="lazy"; - 确认首屏以外图片延迟加载,不会在初始请求中抢占带宽。
Theme Check 能证明 Liquid 结构与规则没有明显错误,但它不能替代浏览器渲染和网络请求验证。本文的结论范围是“本地代码通过静态检查”,没有把未执行的在线商店性能数据写成实测提升。
几个常见错误
- 没有为 image_url 指定宽或高:当前官方文档要求至少提供一个尺寸参数。
- 手工拼接旧式 CDN 文件名:容易遗漏平台优化和图片对象信息,应优先使用过滤器链。
- widths 大于 image_url 上限:上限以外的候选没有实际意义。
- 把 sizes 当成 CSS:它只描述预期插槽宽度,不能替代主题布局样式。
- 所有图片统一 lazy:会延迟首屏 LCP 候选图片。
- 只看 Theme Check 总数:应对比新增代码前后的 warning,区分主题基线问题。
总结
Shopify Liquid 响应式图片的核心不是堆叠更多尺寸,而是让图片对象、CDN 候选、浏览器选择和页面加载优先级各自承担清晰职责。image_url 控制输出上限,image_tag 负责完整标记,widths 与 sizes 配合浏览器选择文件,首屏 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)




