先把图片性能变成可验收的交付目标
先定义用户看到的结果
Shopify 主题的图片优化不是把所有文件压小,而是让正确的资源在正确的时间、以适合当前视口的尺寸到达浏览器。实施前先选一个真实模板,例如商品详情页、集合页和首页首屏,记录网络请求、图片显示尺寸、资源实际宽度、LCP、CLS、错误率和低速网络下的可用性。每个页面都要注明测试地区、设备宽度、缓存状态、商品数量和媒体类型,否则今天的绿色结果可能只是缓存或空商品的偶然结果。
把目标拆成资源级和页面级。资源级关注原始像素、传输字节、格式、请求优先级、响应时间和解码时间;页面级关注首屏主图是否在主要文字后稳定出现、滚动后是否发生跳动、缩略图是否阻塞交互、放大查看是否仍保留清晰细节。不要先承诺一个固定百分比,因为商品摄影、裁切比例和市场网络差异很大。应记录基准值、目标范围、采样条件和停止条件,改动后用同一批 URL 复测。
Shopify 的 主题性能最佳实践强调首屏内容、响应式图片和加载优先级要一起设计。把这篇文章当作资源交付手册:先验证模板输出的 HTML,再验证 CDN 请求和现场体验,最后才决定是否扩大到其他模板。
盘点商品媒体,先消除尺寸和语义盲区
建立每个图片用途的清单
从 Liquid 数据对象开始盘点,而不是从文件名猜用途。为主图、第二张图、缩略图、变体图片、推荐卡片、横幅、品牌标志和文章封面分别记录对象来源、展示比例、最大 CSS 宽度、是否需要透明背景、是否允许裁切、是否属于首屏以及失败时的替代内容。一个商品可能同时有方图、竖图和带透明边缘的 PNG;如果把它们统一压成一个尺寸,通常会损失构图或让移动端下载过量数据。
检查图片是否存在、是否有有效的宽高、是否有替代文本、是否属于当前商品或当前变体。对于空字段,先决定是隐藏图片容器、显示品牌默认图,还是显示有文字说明的占位区域;不要让空 URL 生成一个仍占空间的破损请求。透明图要检查其边缘颜色与主题背景,避免压缩后出现灰边。用一份清单把内容运营、设计和前端的责任写清楚,每次换摄影规范时同步更新。
| 用途 | 主要数据 | 尺寸决策 | 空值处理 | 验收证据 |
|---|---|---|---|---|
| 商品首图 | product featured media | 以最大首屏显示宽度为上限 | 商品卡显示品牌默认图并保留替代文本 | HTML、请求宽度、LCP |
| 变体图片 | variant featured media | 按画廊主框尺寸准备多个宽度 | 维持当前主图,不发送空请求 | 变体切换录屏与网络日志 |
| 集合卡片 | product media | 按卡片 CSS 宽度加少量余量 | 隐藏装饰图,保留商品标题 | 卡片列表和移动视口截图 |
| 透明标志 | theme setting 或 shop logo | 保留透明边缘与可读最小宽度 | 使用文字品牌名 | 对比图、背景色矩阵 |
《Shopify image 对象说明》能帮助团队确认宽高、alt 和原始资源字段的含义。清单完成后再写模板,能避免用 CSS 事后补救数据问题。
用 image_url 生成有边界的资源地址
让 Liquid 请求宽度服从布局
Shopify 主题通常通过 image_url 过滤器请求指定宽度,再把地址放进 image_tag 或自定义标签。宽度不是越大越好:应先确定组件在最大断点的 CSS 宽度,再加上设备像素比余量,最后从有限的宽度阶梯中选择最接近的值。对商品画廊可准备 360、540、750、990、1200 和 1600 等级别;对小卡片应使用更小的上限。阶梯需要结合实际请求分布调整,而不是给每个对象生成几十种宽度。
将原图宽度、请求宽度和显示宽度分开记录。原图小于请求宽度时不要假设 CDN 能补回细节;原图远大于页面显示尺寸时也不要把原图直接交给浏览器。验证过滤器的参数是否来自受信任的 Liquid 数值,避免设置为空、为负数或超过主题约定上限。对图片 URL 做一次 HTML 输出检查,确保查询参数没有被二次编码或被字符串拼接截断。
《image_url 过滤器文档》说明 Shopify 会根据请求和浏览器能力提供适合的图像格式。实施中仍要检查实际响应头、缓存命中和回退表现;文档能力不能替代浏览器网络面板的证据。
用 srcset 和 sizes 匹配真实视口
先测 CSS 宽度,再选择合适宽度
srcset 的每个宽度级别都应对应一个可能的布局状态,sizes 则告诉浏览器图片在当前条件下大约占多宽。集合页可以按照两列、三列、四列断点写条件,商品页可以把画廊宽度与信息栏并列关系写出来。若 sizes 写成 100vw,而图片实际只有半屏宽,浏览器会反复选择过大的资源;若写得过小,高清屏会看到模糊主图。用浏览器的计算样式和截图测量值校正,而不是只看设计稿。
| 组件 | 移动端显示 | 桌面端显示 | srcset 阶梯 | sizes 思路 |
|---|---|---|---|---|
| 商品画廊 | 100vw 减左右内边距 | 约 58vw,受最大容器限制 | 360/540/750/990/1200/1600 | 移动按视口,桌面按内容列宽 |
| 集合卡片 | 50vw 减间距 | 25vw 减网格间距 | 240/360/540/750 | 按网格列数写媒体条件 |
| 推荐横幅 | 100vw | 100vw 但限制最大高度 | 750/990/1440/1920 | 跟随横幅容器而非图片原始宽度 |
| 放大查看 | 视口内最大可用宽度 | 视口内最大可用宽度 | 1200/1600/2000/2400 | 打开查看器时重新计算 |
测试时用真实商品图片和最窄、最宽两个断点,观察浏览器最终选中的 currentSrc。切换变体后再看一次,因为新图片常常沿用旧图的 sizes 或缓存。避免在每个组件里独立发明阶梯;把规则写进可复用 snippet,并允许少数艺术指导图片显式覆盖。
用 image_tag 管理 alt、loading 和优先级
把首屏主图与普通图片分开
image_tag 可以把 URL、alt、class 以及 HTML 属性集中输出。首屏真正承担最大内容绘制的主图,应考虑 eager 加载并设置合适的高优先级提示;首屏以下的画廊、推荐卡片和页脚图片才适合延迟加载。不要因为某个组件复用方便,就给所有图片添加同样的 loading 属性。首屏判定要按模板和断点验证,桌面首图不一定是移动端首图。
替代文本应描述商品或图片传达的事实,而不是堆关键词。装饰性分隔图使用空 alt 或直接用 CSS;商品正面、材质细节和变体色彩则应使用能帮助理解的短句。class 负责布局与对象定位,loading、decoding、fetchpriority 负责加载策略,三者不要互相覆盖。检查最终 HTML 而不是 Liquid 源码,因为主题片段、应用嵌入和脚本可能在渲染后改变属性。
以下组合可作为实施起点:首屏主图设置明确宽度、宽高比例和简洁 alt,避免盲目预加载多个大图;非首屏图片默认延迟加载,但当滚动容器很短或图片即将进入视口时用预取策略验证收益;需要解码的图片不要阻塞关键文字。每次调整属性都记录 Lighthouse、现场指标和用户可见差异。
预留尺寸,稳定画廊和卡片布局
让浏览器在下载前知道盒子大小
CLS 常常不是图片文件太大,而是图片到达前容器没有确定尺寸。使用图片对象的宽高、稳定的 aspect-ratio 或主题设定的媒体比例,让浏览器在布局阶段先分配空间。对裁切卡片,外层盒子与 object-fit 规则应共同定义结果;对完整展示的产品摄影,不要在 CSS 中强行裁成固定正方形。变体切换时也要维持同一盒子,避免用户点击颜色后整段内容上下跳动。
| 场景 | 容器规则 | 图片规则 | 常见故障 | 回归检查 |
|---|---|---|---|---|
| 商品主画廊 | 固定比例或由媒体比例决定 | contain 或 cover 明确写出 | 第二张图比例不同造成跳动 | 切换四种变体并记录 CLS |
| 集合卡片 | 网格行高由比例锁定 | cover,焦点由运营配置 | 长图撑高整行 | 1440、768、390 宽度对比 |
| 透明 PNG | 盒子保留可视边距 | contain,背景单独设置 | 透明边缘被裁掉 | 浅色和深色背景截图 |
| 延迟加载占位 | 先画同尺寸骨架 | 成功后替换内容 | 骨架与真图比例不一致 | 缓存禁用时录制滚动 |
对动态媒体,先把宽高写入数据属性或 CSS 变量,再由脚本替换 src;脚本失败时盒子仍应存在。不要用 JavaScript 在图片加载后才测量并改变主要布局,那会把网络波动直接变成跳动。配合 Shopify 无障碍最佳实践检查键盘焦点、替代文本和放大查看器的可操作性。
延迟加载只用于真正的非首屏内容
用滚动路径验证 lazy 边界
把页面划分为首屏、近首屏和远端内容。首屏主图、首屏商品标题旁的重要视觉内容通常需要尽快请求;近首屏的第二张图片可以观察滚动速度和网络条件决定;远端推荐、评论头像和页脚品牌图才是延迟加载的稳定对象。首屏以下不等于永远很远:移动端首屏高度、浏览器工具栏和字体变化都会改变可见范围。
逐段滚动并记录请求发起时刻、图片可见时刻和滚动是否被打断。若用户快速滑到某个组件,图片没有提前请求就会出现空白;可在合理的根边距内预取,但要限制并发和字节数。避免把整个画廊包在一个延迟脚本里,否则用户点击缩略图时可能等待脚本初始化。没有 JavaScript 时,HTML 中至少要保留可读的首图和链接。
用性能测试环境和真实手机分别检查。Shopify 的 性能测试指南提醒团队要在不同网络、设备和缓存状态下测量;同一个 lazy 阈值在快速桌面和低速移动网络上可能有不同结果。将“看起来加载了”改成可复现的请求与时间线记录。
处理 WebP、AVIF 与原图回退
让格式变化不破坏可见内容
现代浏览器可从 CDN 获得更高压缩效率的格式,但实施必须保留浏览器不能解码或源图异常时的可用路径。优先使用 Shopify 的图片过滤器和 CDN 响应协商,不要在主题里复制一套容易失真的格式判断。检查响应的 content-type、自然宽度、透明度和解码错误;带文字的包装图、细线图标和透明标志要特别看边缘。
| 检查项 | 通过条件 | 失败表现 | 处理方式 |
|---|---|---|---|
| 格式协商 | 响应格式与浏览器能力匹配 | 现代格式在旧环境无法解码 | 由 CDN 或 picture 提供原图路径 |
| 透明背景 | 边缘颜色与设计稿一致 | 出现黑边、白边或锯齿 | 重新导出源图并降低过度压缩 |
| CDN 尺寸 | 实际宽度接近布局需要 | 下载原图或小图放大 | 修正宽度阶梯和 sizes |
| 解码异常 | 图片完成并可访问 alt | 破图图标或空盒子 | 保留文本、默认图和错误日志 |
不要把浏览器支持表当成唯一验收依据。用至少一台旧版移动浏览器、一个禁用缓存的桌面浏览器和一次图片服务异常演练,验证最坏路径仍能看到商品信息。记录源图、转换参数、响应头和截图,便于内容团队定位是素材问题还是模板问题。
把图片片段做成可控的主题组件
用单一接口减少属性漂移
为商品主图、卡片媒体和横幅建立清晰的 snippet 输入:图片对象、显示用途、最大宽度、媒体比例、alt 覆盖、是否首屏和加载策略。snippet 内部负责把这些输入转换成 image_url、image_tag、srcset、sizes 和比例容器;调用方只传业务语义,不在每个 section 里拼接 URL。若主题需要艺术指导裁切,另设明确的模式,不要让一个布尔值同时决定裁切、优先级和替代文本。
在 section schema 中限制宽度选项和比例选项,减少运营人员填入不可用值。对 app embed 注入的图片,确认它是否在主题片段之后再次改写 loading 或 src;必要时在浏览器中记录最终 DOM。主题升级时先比较生成的 HTML 和网络瀑布图,再比较视觉截图,避免只看 Liquid diff。
将这些页面级策略与 Shopify 二次主题开发和 Liquid 实践结合,可以把性能规则放进组件契约,而不是依赖某位开发者记忆。组件文档需同时写默认值、可覆盖字段、适用模板和故障回退。
用网络瀑布图和现场指标验收
让每一次比较都可重复
验收至少保留三类证据:页面源代码或渲染后的 HTML、网络瀑布图、视觉和现场指标。源代码回答属性是否输出,瀑布图回答请求何时发出以及是否下载过大,指标回答真实用户是否在不同网络中受益。对每个模板固定商品、图片集合、设备宽度、地区和缓存状态,并在变更前后使用相同条件。
| 证据 | 需要记录 | 通过问题 | 失败后的第一步 |
|---|---|---|---|
| HTML 快照 | src、srcset、sizes、alt、loading、fetchpriority、尺寸 | 属性与组件契约一致吗 | 定位 Liquid 或应用注入 |
| 网络日志 | URL、响应格式、字节、宽度、缓存、时序 | 下载的是合适资源吗 | 检查阶梯、CDN 和缓存键 |
| 性能指标 | LCP、CLS、INP、错误率 | 首屏和交互是否稳定 | 分离图片问题与脚本问题 |
| 视觉截图 | 断点、背景、裁切、焦点 | 构图和可读性保持吗 | 回看比例和 object-fit |
可以参考 Shopify 性能平台说明,但不要把单次实验室分数当成上线依据。上线前安排一轮真实手机复测和图片服务异常演练;任何一个关键模板出现破图、首屏空白或布局明显跳动,都应停止扩大范围。
两个失败案例:从症状定位到安全回退
用最小改动恢复可见内容
案例一是把商品详情页主图统一加上 loading=lazy。实验室报告看似请求更少,但低速手机在标题已经可见时主图仍为空,用户滑动时还会看到延迟替换。定位方法是对比渲染 HTML、请求起始时间和 LCP 元素;修复只把真正的首屏主图恢复为 eager,并保留下方画廊延迟,随后复测而不是全站取消延迟加载。
案例二是 sizes 写成 100vw,而桌面商品页的画廊只占容器的一半。浏览器从 1600 宽度阶梯选图,网络瀑布图显示首屏字节翻倍;移动端又因断点条件错误选到 240 宽小图。定位方法是同时查看 CSS 计算宽度和 currentSrc,修正媒体条件与宽度阶梯,保留旧片段作为可快速切换的版本。
回退边界应提前写好:只恢复图片 snippet、section 设置或相关 CSS,不回退商品内容、价格和结账逻辑。发布前保存原始模板文件、构建差异、测试 URL 和截图;发现破图、空 alt、大范围 CLS 或请求量异常时,先关闭新加载策略,再保留日志和样本供修复。回退后用相同基准确认核心页面恢复,再决定是否重新开启单个组件。
发布清单与长期维护
把策略变成团队日常检查
发布前确认每个目标模板都有明确的首屏图片、srcset、sizes、尺寸预留、替代文本、延迟加载边界和格式回退。确认 Liquid 输出没有空 URL、超过上限的宽度或重复预加载,确认变体切换不改变主要盒子高度,确认放大查看和键盘操作可用。内容团队要知道源图最低像素、透明边距和命名要求,开发团队要知道哪些字段可以覆盖。
发布后先观察一小组固定 URL,再观察现场性能和错误日志。把请求宽度分布、格式比例、图片错误、LCP、CLS 和用户投诉按模板分组;如果只有某一批商品异常,优先查素材比例或源图损坏,不要立即改变全局策略。主题升级、应用安装、字体更换和新的营销横幅都可能改变首屏边界,需要重新跑一遍清单。
相关的 Shopify 店铺速度实战手册、移动端转化设计实践和页面构建取舍指南可作为后续检查的背景资料。它们不能代替本页的资源级证据,但能帮助团队把图片决策放回页面体验和运营节奏中。
常见问题
首屏主图一定要设置高优先级吗?
不一定。只有真正成为主要内容绘制、且浏览器能在早期识别的首屏主图才值得提高优先级。先用渲染后的页面和 LCP 证据确认,再避免多个大图同时争抢连接。
为什么原图已经很小,页面仍然慢?
可能是请求宽度超过显示需要、图片格式未命中、CDN 缓存未命中、解码阻塞或脚本在图片后执行。应分别看字节、响应头、请求时序、解码和主线程,而不是只看文件大小。
srcset 写得越多越好吗?
不是。过多阶梯会增加维护和缓存变体,过少则容易让浏览器在两个尺寸之间选择过大的资源。根据真实 CSS 宽度、设备像素比和请求分布选择有限阶梯,并用 currentSrc 验证。
商品变体图片比例不一致怎么处理?
先决定画廊是保持媒体比例还是统一展示比例,再让容器、object-fit 和焦点位置共同表达这个决定。切换变体时保持盒子尺寸稳定,并在浅色、深色和透明背景下检查边缘。
图片优化出现破图时应先回退什么?
先回退最近一次图片 URL、属性或比例容器变更,保留商品数据、价格和结账逻辑不动。恢复旧片段后用同一组页面和网络条件确认可见内容,再针对单个故障资源修复。