link 标签的 media 属性是渲染开关而非加载开关,浏览器仍会同步下载带 media 的 css 文件;真正异步加载需通过 rel="preload" + js 切换或动态插入 link 元素实现。

link 标签的 media 属性不是加载开关,而是渲染开关
很多人误以为给 <link rel="stylesheet" href="print.css" media="print"> 加上 media 就能“只在打印时加载”,其实浏览器仍会**同步下载该 CSS 文件**(除非配合 rel="preload" 或 JS 动态插入)。media 只控制样式是否生效,不阻塞或延迟资源获取。
- 常见错误现象:
network面板里看到print.css在页面初始化阶段就发起了请求,哪怕用户从没点打印 - 真正按媒体类型“异步加载”的核心是:先不加载,等媒体条件满足(如
window.matchMedia("print").matches为true)再动态插入<link> -
media值支持screen、print、prefers-color-scheme: dark等,但所有这些值对默认加载行为无抑制作用
用 rel="preload" + as="style" 实现真正的延迟加载
想让某份样式表只在特定媒体条件下才开始下载,必须绕过 HTML 解析期的默认行为。最可靠的方式是用 <link rel="preload"> 占位,再用 JS 判断媒体查询后手动切换为 stylesheet:
<link rel="preload" href="dark-mode.css" as="style" id="dark-style"><script>
const darkLink = document.getElementById('dark-style');
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
darkLink.rel = 'stylesheet';
}
</script>
-
rel="preload"不会应用样式,只预取资源;as="style"让浏览器知道这是 CSS,启用正确 MIME 类型和优先级 - 必须显式设置
rel = 'stylesheet'才会解析并应用样式,否则它永远只是个预加载项 - 注意:不能直接在
<link rel="preload">上写media,因为preload不支持media属性,会忽略
动态插入 <link> 是更灵活的异步方案
当媒体条件复杂(比如需要监听变化),或要避免预加载干扰关键路径,直接创建 <link> 元素插入 DOM 更可控:
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
function loadStylesheet(href, media) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = href;
link.media = media; // 此处 media 才真正起效:匹配时才应用
document.head.appendChild(link);
}
// 示例:仅在打印前加载打印样式
window.addEventListener('beforeprint', () => {
loadStylesheet('/css/print.css', 'print');
});
-
link.media在动态插入后立即生效:不匹配时样式不计算、不重排,匹配时才触发解析与布局影响 -
beforeprint事件比单纯检查matchMedia更准——它确保只在用户真正触发打印流程时加载,避免误判 - 注意:动态插入的
<link>不会阻塞渲染,但一旦media匹配,仍会触发一次同步样式计算,可能引起小范围重排
移动端 media="(max-width: 768px)" 的兼容性陷阱
在 iOS Safari 和部分 Android WebView 中,matchMedia 对响应式媒体查询(如 max-width)的初始判断可能不准,尤其页面未完成 layout 时。直接依赖它做加载决策容易漏掉样式。
- 常见错误现象:移动端首次进入页面,
matchMedia("(max-width: 768px)").matches返回false,导致移动端样式没加载 - 解决方案:加一层
setTimeout延迟判断,或监听resize后再确认,更稳妥的是用requestIdleCallback或document.readyState === 'interactive'时机 - 不要把
media写死在 HTML 的<link>里期望“自动异步”,它只会让样式失效,不会节省带宽或提升首屏速度
真正异步的关键永远在 JS 控制权——HTML 的 <link> 天然不具备条件加载能力,靠属性声明做不到,必须用代码接管时机。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










