@import和link的优先级由实际解析顺序决定而非语法本身;link并行加载先解析,@import串行阻塞后解析,故同权重下后者覆盖前者。

@import 和 link 的优先级不是由语法决定的,而是由加载顺序决定的
很多人误以为 @import 引入的样式天然权重更低,其实 CSS 规范里根本不存在“@import 权重低于 link”这条规则。真正起作用的是「源顺序(source order)」:浏览器按样式规则实际被解析的先后顺序来决定覆盖关系。只要两个规则选择器权重相同(比如都是 .btn),后解析的那个就会生效。
但关键陷阱在于:@import 的解析时机晚于同级 link —— 即使它在 HTML 中写得更早,也改变不了这个事实。
-
<link href="base.css">和<style>@import "theme.css";</style>同时存在时,base.css先解析,theme.css后解析 → 后者覆盖前者 - 但如果
<link href="base.css">和<link href="theme.css">并列,且theme.css在 DOM 中排在后面,则它同样会覆盖base.css中同权重规则 - 真正拉开差距的是嵌套:
main.css通过@import "theme.css"引入,而 HTML 中有<link href="base.css">和<link href="main.css">,最终顺序是:base.css→main.css自身规则 →theme.css
为什么 @import 总是“慢半拍”?
这不是浏览器故意卡你,而是加载模型差异导致的确定性行为:
-
link是 HTML 解析器遇到就立刻发起请求,并行下载,解析完即应用 -
@import必须等它所在的上下文(CSS 文件或<style>块)完全下载并解析完毕,才开始请求被导入的文件 → 天然串行阻塞 - 哪怕
@import url("a.css") screen and (max-width: 768px)"写了媒体查询,浏览器仍会无条件下载a.css,只是不应用;而<link media="...">真的会跳过下载 - 动态插入
<style>@import...</style>完全无效 —— 浏览器只在初始 CSS 解析阶段处理@import,运行时忽略
哪些场景下 @import 会意外破坏样式预期?
常见于构建工具未显式告警、但实际引入了多层 @import 的项目:
立即学习“前端免费学习笔记(深入)”;
- 第三方 UI 库的 CSS 文件内部用了
@import加载主题或图标字体,导致首屏关键样式延迟 800ms+(弱网实测) - 开发时用
@import快速合并多个样式,上线后发现某些类名被覆盖,查了半天才发现是theme.css被reset.css里的同名规则覆盖了,而你以为theme.css是最后加载的 - Webpack/Vite 构建时把
@import提前合并了,本地没问题,但直接跑未构建的源码时出现 FOUC(Flash of Unstyled Content) - 想用 JS 动态切换深色主题,写了
document.createElement('link')没问题,但试图用style.innerHTML = '@import ...'就永远不生效
实际项目中该怎么做?
一句话:所有外链 CSS 都走 link,彻底隔离 @import 到构建流程或彻底不用。
- HTML 中只保留
<link rel="stylesheet" href="...">,按期望覆盖顺序排列 - 需要条件加载(如 print / mobile)必须用
<link media="...">,别信@import后面加媒体查询 - 要用
rel="preload"提前拉取关键 CSS?只有link支持,@import无此能力 - 如果必须复用某套 CSS 逻辑(比如多主题),用构建工具做 import 合并,而非运行时
@import
最易被忽略的一点:DevTools 的 Computed 面板里看到的最终样式,才是真实生效顺序 —— 不要靠文件名或注释猜,直接看 Styles 侧边栏里哪条被划掉、哪条高亮。


















