link 在 html 解析阶段加载,@import 在 css 解析阶段才触发;前者并行下载、可被 js 控制、支持 media 等属性,后者串行加载、无法监控、不被 document.stylesheets 包含。

link 是 HTML 解析阶段加载,@import 是 CSS 解析阶段才触发
浏览器遇到 <link rel="stylesheet"> 时,会立刻发起网络请求,并行下载,同时继续解析后续 HTML;而 @import 必须等包含它的 CSS 文件(无论是外部 .css 还是 <style></style> 块)被下载、解析到那一行时,才会发起下一轮请求——这天然晚一个事件循环,甚至更久。
常见错误现象:
- 在
<style></style>底部写@import url("theme.css"),导致页面文字先以默认样式渲染,几百毫秒后突然跳变成主题样式(FOUC) - 在
main.css里连续写多个@import,实际加载链变成 A → B → C,无法并行
link 支持 media、preload、disabled 等属性控制,@import 几乎没有扩展能力
<link> 是 DOM 节点,能被 JS 完全操控;@import 是 CSS 解析器内部行为,JS 拿不到、改不了、监听不了。
你能用 <link> 做这些事:
- 响应式加载:
<link rel="stylesheet" href="mobile.css" media="(max-width: 768px)"> - 预加载关键样式:
<link rel="preload" href="critical.css" as="style" onload="this.rel='stylesheet'"> - 动态启用/禁用:
document.querySelector('link[title="theme"]').disabled = true
而 @import 只接受两种写法:@import url("a.css") 或 @import url("a.css") screen and (min-width: 768px),连缓存 bust(如 ?v=2.1)都得手动拼,稍有空格或分号缺失就整条规则失效。
document.styleSheets 不包含 @import 加载的样式表
调用 document.styleSheets 获取当前所有 CSSStyleSheet 对象时,<link> 加载的会立刻出现在列表里,索引可查、规则可读;但 @import 导入的样式表不会出现在该集合中——它属于“子样式表”,只能通过 cssRules 逐层递归访问,且时机不可靠(可能还没解析完)。
这意味着:
- 你想用 JS 判断某个
@import是否加载完成?基本做不到 - 想用
CSSStyleSheet.disabled = true临时禁用某份导入样式?不行 - 构建工具(如 Vite、webpack)无法静态分析
@import路径,热更新、tree-shaking、预加载提示都会失效
现代项目中应避免用 @import 引入主样式表
@import 不是 <link> 的语法糖替代品,而是不同层级、不同加载机制、不同可控性的两种东西。它不支持 HTTP/2 多路复用优化,不能被大多数构建工具识别,也不兼容 CSS-in-JS 提取逻辑。
唯一还可能见到 @import 的合理场景:
- CSS 框架内部模块化拆分(如旧版 Bootstrap 的
_mixins.css被主文件@import) - 主题切换时,用 JS 动态写入
<style></style>块并内含@import(但此时已不如直接换<link>标签可靠)
最容易被忽略的一点:你在 <style></style> 里写 @import,看起来“只是换种写法”,其实已经把样式加载逻辑从 HTML 解析阶段,推迟到了 CSS 解析阶段——这个延迟对首屏性能的影响,远比多数人预估的要大。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











