优先使用 <link> 而非 @import:前者并行加载、支持 preload 和 media、兼容 HTTP/2;后者串行阻塞、触发 FOUC、浪费带宽且无法条件跳过请求。

link 标签加载 CSS 是并行的,@import 是串行阻塞的
浏览器解析 HTML 时,<link rel="stylesheet"> 会触发 CSS 文件的并行下载,同时继续解析后续 HTML;而 @import(尤其写在 CSS 文件里)会让浏览器等前一个样式表完全加载并解析完,才开始下载下一个——这会把关键资源加载链拉长,首屏渲染明显变慢。
常见错误现象:@import url("base.css") 放在 theme.css 开头,结果 theme.css 本身已通过 <link> 引入,但其中的 @import 仍会阻塞后续样式规则生效,甚至导致 FOUC(Flash of Unstyled Content)。
- 只在 CSS 文件内用
@import时,它总在当前文件解析完成后再发起请求,无法与父 HTML 的其他<link>并行 - 如果非要用
@import,必须写在<style>标签最顶部(且该标签需在<head>中靠前位置),但依然不如<link> - Webpack/Vite 等构建工具中,
@import会被提前解析合并,此时无运行时开销——但这是构建期行为,不改变原生 CSS 加载语义
link 标签支持 preload 和 media 属性,@import 完全不支持
<link> 可以配合 rel="preload" 提前拉取关键 CSS,或用 media 做条件加载(比如 media="print" 或 media="(max-width: 768px)"),这些特性对性能优化和响应式至关重要;@import 没有对应机制,只能无差别加载。
使用场景举例:移动端首屏只需基础样式,完整组件库 CSS 可延迟加载——用 <link rel="preload" href="components.css" as="style" onload="this.rel='stylesheet'"> 配合 JS 控制时机,@import 做不到。
立即学习“前端免费学习笔记(深入)”;
-
media属性让浏览器跳过不匹配条件的 CSS 下载(如打印样式在屏幕浏览时不下载) -
rel="preload"需搭配onload或onerror脚本切换rel值,否则不会应用样式 -
@import即使加了media查询(如@import url("foo.css") screen and (min-width: 768px);),仍会发起 HTTP 请求,只是不应用规则——浪费带宽
HTTP/2 下 link 多文件优势更明显,@import 无法受益
HTTP/2 支持多路复用,多个 <link> 可共用一个 TCP 连接并发传输;而 @import 强制串行,即使底层是 HTTP/2,也无法绕过 CSS 解析层的依赖顺序限制。
性能影响:实测 5 个 CSS 文件,全用 <link> 比嵌套 4 层 @import 快 300–600ms(取决于网络 RTT 和服务器配置)。
- 构建工具输出单个 CSS bundle 时,
@import和<link>差异消失——但那是打包结果,不是加载行为 - 动态插入样式(如 JS 创建
<link>)仍享受并行能力;动态注入@import字符串到<style>则触发同步重排,更慢 - 部分老版本 Safari 对
@import在<style>中的解析有 bug,可能忽略或错序加载
实际项目中怎么选:优先 link,禁用 @import(除非极特殊维护场景)
现代项目基本没有理由用 @import。它曾用于 IE 条件注释替代方案,或规避某些构建工具限制,但现在都被更好方式替代。
容易踩的坑:@import 写在 SCSS/Less 中会被编译器展开,看似“安全”,但一旦误写进最终输出的 CSS 文件(比如忘了关 source map 或用了 raw loader),就立刻回归原生性能问题。
- 所有第三方 CSS(如 Bootstrap、normalize.css)必须用
<link>直接引入,不要包在自定义 CSS 里用@import - CI/CD 流程中可加检查:
grep -r "@import" src/ | grep "\.css$",发现就报错 - 若必须复用 CSS 片段(如主题变量),改用 CSS 自定义属性(
var(--color-primary))或构建时注入,而非运行时@import
真正影响加载效率的从来不是语法糖,而是浏览器如何调度请求——@import 在这个链条上多加了一道不可跳过的等待门。



















