是并行加载,@import是串行阻塞:前者在HTML解析时立即发起请求并与其他资源并行下载;后者必须等父CSS完全下载解析后才请求被导入文件,导致首屏延迟、FOUC及带宽浪费。

link 是并行加载,@import 是串行阻塞
浏览器解析 HTML 时,遇到 <link rel="stylesheet"> 会立即发起请求,并与其他资源(如图片、JS)并行下载;而 @import 必须等父 CSS 文件完整下载并解析完,才开始请求被导入的文件。这意味着一个 @import url("a.css") 后面再跟 @import url("b.css"),b 的请求要等 a 的下载 + 解析全部完成才能启动。
常见错误现象:main.css 里写了 3 层 @import,PageSpeed Insights 却只报出 1 个 render-blocking 资源——实际首屏阻塞时间被悄悄拉长了 600ms+,因为工具无法穿透 CSS 文件发现隐式依赖链。
- 实测数据:5 个样式文件全用
<link>加载比嵌套 4 层@import快 300–600ms(弱网下差距更大) -
@import在<style></style>标签里也一样阻塞:哪怕写在最前面,它仍要等该<style></style>块解析完才触发请求 - HTTP/2 对
<link>的多路复用有收益,但对@import无效——底层协议再快,也绕不过 CSS 解析层的顺序约束
media 属性在 link 中可跳过下载,在 @import 中只是“不应用”
<link href="print.css" media="print"> 在屏幕浏览时根本不会发起 HTTP 请求;而 @import url("print.css") print; 依然会下载文件,只是不把规则加入 CSSOM——浪费带宽,还拖慢整体加载。
典型误用:@import url("mobile.css") screen and (max-width: 768px); 看似条件加载,实则所有设备都下载,且必须等主 CSS 解析完才开始。真正需要响应式懒加载,只能靠 <link media="screen and (max-width: 768px)">。
立即学习“前端免费学习笔记(深入)”;
-
media在<link>中是预判机制,在@import中是后置过滤 - 打印样式、暗色主题等非关键路径,用
<link media="prefers-color-scheme: dark">更精准 - 构建工具(如 Vite)虽能把
@import提前合并,但那是打包期行为,不改变运行时语义
preload 和 JS 动态控制只对 link 有效
<link rel="preload" href="critical.css" as="style" onload="this.rel='stylesheet'"> 可让关键 CSS 进入高优先级队列;而 @import 没有对应机制。同样,运行时切换主题或按需加载模块样式,只能通过 JS 创建 <link> 元素实现:
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'theme-dark.css';
document.head.appendChild(link);
试图用 JS 注入 @import 字符串到 <style></style>(如 style.textContent = '@import url(x.css)';)完全无效——@import 必须出现在 CSS 文本最开头,且只在解析阶段生效,运行时拼接不触发重新解析。
-
rel="preload"需配合 JS 切换rel值才能真正应用样式,否则只是预加载 - 动态插入的
<link>仍享受并行加载能力,不是“伪异步” - IE6–IE8 对 CSS 文件内
@import有位置 bug(非最开头会被忽略),<link>无此问题
FOUC 风险和调试盲区往往来自 @import 链
页面出现“内容先闪一下再上样式”,大概率不是没写 <link>,而是某个已引入的 CSS 文件内部用了 @import,导致部分样式延迟注入。Chrome DevTools 的 Network 面板看不到这些子请求,得打开“Disable cache”并勾选 “All” 才能捕获完整链路。
容易被忽略的一点:即使你全程只用 <link>,第三方库(如某些旧版 UI 组件)的 CSS 文件里若含 @import,照样会拖慢你的首屏——你控制不了它的内部结构,只能通过构建工具剥离或手动替换。
- 排查 FOUC 时,别只盯 HTML,要检查所有已加载 CSS 文件的内容
- Webpack/Vite 默认配置通常会处理
@import,但需确认css-loader或esbuild的injectStyles行为未被覆盖 - 现代项目中,
@import唯一合理用途只剩兼容极老 IE hack 或维护遗留拆分逻辑,其余场景应视为技术债



















