现代浏览器(Chrome 80+、Firefox 69+、Safari 14+)在 media 值合法且当前不匹配时会跳过下载,前提是媒体类型完整、语法正确、非 all 且非未声明;否则仍可能加载。

link 的 media 属性确实能“按条件引入 CSS”,但它的行为和很多人想的不一样:它不保证跳过下载,只控制样式是否生效;真正能省请求的,是现代浏览器对不匹配媒体查询的主动跳过机制——但这有前提。
media 属性什么时候会跳过下载?
现代浏览器(Chrome 80+、Firefox 69+、Safari 14+)在以下条件下,会完全不发起网络请求:
-
media值是合法且当前不匹配的媒体查询,例如:-
media="(prefers-color-scheme: dark)"(用户系统为浅色模式) -
media="screen and (max-width: 480px)"(当前视口宽度为 1200px)
-
- 媒体查询语法正确,无空格错位、括号缺失等低级错误
- 不是
media="all"或未声明media(此时默认为all,总会加载)
反例:media="screen and (min-width: 768px )" 尾部多一个空格 → 部分 Safari/Electron 会降级为 all,强制加载
验证方法:打开 DevTools → Network 面板 → 刷新页面 → 看目标 CSS 文件是否根本没出现(不是 200 但灰掉,而是压根没请求)
media 值必须带媒体类型,不能只写特性
media 不是 CSS 里的 @media,它要求完整语法:媒体类型 + 媒体特性。
- ✅ 正确:
media="screen and (max-width: 768px)" - ✅ 正确:
media="print" - ✅ 正确:
media="screen and (orientation: landscape)" - ❌ 错误:
media="(max-width: 768px)"(缺媒体类型,旧版 Safari 忽略整条link) - ❌ 错误:
media="not screen"(语法合法但语义模糊,部分浏览器仍会下载)
最稳妥的兜底写法是:media="screen",再把所有断点逻辑交给 CSS 文件内部的 @media 规则处理——这样既避免兼容性风险,又确保样式层叠可控。
和 @import 混用会破坏条件加载
别在 CSS 文件里用 @import 做条件引入:
-
@import url("dark.css") (prefers-color-scheme: dark);
看似等价,实则:- 所有
@import在解析阶段就触发,无法跳过下载 - 它阻塞后续 CSS 规则解析,拖慢 LCP
- Chrome Network 面板明确标为 “blocking”
- 无法通过 JS 卸载或切换
- 所有
也就是说:@import 的 media 只是“条件应用”,不是“条件加载”——文件照下,只是不参与计算。
真正需要运行时判断时,用 JS 动态插入
当条件依赖 JS 运行时状态(比如用户点击切换主题、localStorage 记录偏好、或 UA 特征检测),link media 就不够用了。
关键动作只有三步:
- 用
window.matchMedia()检查当前是否匹配(支持监听变化) - 匹配时创建
link元素,设rel="stylesheet"和href - 插入到
document.head,并加id方便后续移除
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '/css/dark.css';
link.id = 'dark-theme';
document.head.appendChild(link);
}
注意:动态插入的 CSS 会触发重排,若在首屏关键路径上,可能造成闪动;更稳的做法是预加载关键样式,再用 JS 控制激活时机。
容易被忽略的一点是:你以为删掉一个 media 不匹配的 link 就省了请求,其实它可能早就被 parser 预加载了——真正省请求,靠的是浏览器对不匹配查询的主动拦截,而这只在语法严谨、环境明确时才可靠。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











