标签本身不阻止图片加载,但能避免初始渲染时触发请求;其内容在未被克隆插入dom前不会加载资源,插入后立即加载,且需显式设置宽高防布局抖动。

template 标签本身不阻止图片加载,但能避免初始渲染时触发请求
很多人误以为把 <img> 塞进 <template></template> 就能“禁用图片加载”,其实不是。浏览器解析到 <template></template> 时,会跳过其内容的 DOM 构建、脚本执行和资源加载——包括 src 指向的图片不会发起 HTTP 请求。这是由规范保证的行为,不是 hack。
但它只在「未被克隆插入文档前」生效。一旦你调用 content.cloneNode(true) 并 append() 到真实 DOM,图片立刻开始加载。
-
<template></template>内部的<img src="logo.jpg">在页面加载完成时,Network 面板里完全看不到该请求 - 对比
<div hidden> 或 <code>display: none:这些方式下src仍会被解析并立即加载,只是不显示 - 如果你用的是 SSR(如 Next.js、Nuxt),注意服务端渲染时
<template></template>也会原样输出 HTML 字符串,但浏览器仍按规范忽略其内容——所以服务端无需特殊处理 - 推荐写法:
<img src="a.jpg" style="max-width:90%" style="max-width:90%" alt="...">,数值取原图宽高比即可,浏览器会自动缩放 - 现代方案可用
aspect-ratio: 16/9,但 iOS Safari 15.4 之前不支持,兼容性不如属性 - 千万别只靠
max-width: 100%+height: auto:父容器宽度不确定时,初始高度为 0,照样抖动 - 适合场景:模态框内容、表格行模板、Web Component 的 shadow DOM 结构、JS 动态创建的弹窗/提示
- 不适合场景:首屏后三屏的图片流(该用
loading="lazy")、用户 hover 才加载的缩略图(该用Image对象) - 常见错误:把整页商品列表塞进一个
<template></template>,然后 onload 全量 clone —— 这等于延迟了全部渲染,反而拉垮 LCP - 初始化时设
img.src = ""或删掉src属性(保留data-src) - 用
<img alt="...">,后续由 JS 控制赋值,配合IntersectionObserver或滚动节流 - 服务端可输出空
src,再由 hydration 后的 JS 补全(React/Vue SSR 场景下更可靠) -
<template></template>在这里只适合作为“结构容器”,比如封装好带data-src的完整<img>片段,而非用来“挡请求”
template + img 组合必须配 width/height,否则懒加载或复用时易出布局抖动
从 <template></template> 克隆出来的 <img> 插入页面后,如果没声明 width/height 属性,又没用 CSS 固定宽高比,就会在图片加载完成瞬间撑开容器,造成 CLS(累计布局偏移)——尤其在卡片列表、网格布局中非常明显。
template 不是懒加载替代品,它解决的是“时机控制”,不是“条件触发”
你不能靠 <template></template> 实现“滚动到才加载”这种行为。它没有内置的可视区监听能力,也不响应 IntersectionObserver。它的价值在于:明确把一段 UI 定义为“待实例化蓝图”,由 JS 主动决定何时、何处、多少次生成。
真正想阻止图片加载?别依赖 template,直接清空 src 或用 data-src
如果目标是“页面加载时不发任何图片请求”,<template></template> 是手段之一,但更直接可控的方式是操作 src 本身:
最易被忽略的一点:哪怕用了 <template></template>,只要最终插入 DOM 的 <img> 带了 src,且没做任何延迟逻辑,它就在插入那一刻加载——template 不提供“自动懒”的魔法。











