优先用 让私有样式尽早生效且不阻塞 js;仅在组件专属 css 中复用变量时用 @import,注意其路径相对性、前置书写及串行加载陷阱。

什么时候该用 @import,什么时候必须用 <link>
@import 是 CSS 规则,只能写在 CSS 文件里或 <style></style> 块中;<link> 是 HTML 标签,必须写在 HTML 的 里。项目启动阶段想让私有样式(比如 theme.css 或 variables.css)尽早生效、不阻塞 JS 执行,优先选 <link>。如果只是在某个组件专属 CSS 文件里复用一套颜色变量(比如 src/components/Button/button.css 里要引入 src/styles/_colors.css),才用 @import。
@import 的路径和加载顺序陷阱
在 CSS 中写 @import 时,路径是相对于当前 CSS 文件的位置,不是 HTML 页面位置。比如 components/Button/button.css 里写 @import "../styles/vars.css"; 才对,写成 @import "/styles/vars.css"(带根路径)在多数构建工具里会报 @import not found 错误。另外:@import 必须写在所有实际样式的前面,否则整个规则会被浏览器忽略;它还会导致串行加载——A.css 里 @import B.css,B 加载完 A 才开始解析,可能拖慢渲染。
- Webpack/Vite 等工具默认不支持 CSS 中的
@import跨目录解析,需配css-loader的url: false或启用postcss-import - 不要在
@import后面直接写媒体查询,比如@import "print.css" print;兼容性差,建议改用<link rel="stylesheet" href="print.css" media="print">
<link> 加载私有样式表的关键参数
用 <link> 引入私有样式时,rel 必须是 "stylesheet",href 建议用相对路径(如 ./styles/theme.css)或构建后生成的哈希路径(如 styles/theme.a1b2c3.css)。避免使用 file:// 协议或绝对 URL,本地开发易跨域失败。若样式表只用于打印,加 media="print";若想异步加载但不阻塞渲染,可加 media="print" onload="this.media='all'" 配合 JS 切换(即“lazy load CSS”模式)。
-
rel="preload"+as="style"可提前拉取,但必须配合onload注入,否则不会应用:css" onload="this.rel='stylesheet'"> - 多个
<link>按 HTML 中出现顺序执行,CSSOM 构建依赖这个顺序,所以重置样式(reset.css)必须在主题样式(theme.css)之前
构建工具下私有样式表的实际落地方式
现代前端项目基本不用纯手工写 <link> 或 @import。Vite 中直接在 main.js 里 import "@/styles/theme.css",Webpack 同理;这样样式能参与 HMR、提取、压缩、CSS Scope 处理。只有当需要动态切换主题(比如白天/黑夜)、或第三方组件库强制要求外链 CSS 时,才手动操作 <link> 标签。此时注意:旧 <link> 节点要先 remove() 再 append 新的,否则残留样式会冲突。
立即学习“前端免费学习笔记(深入)”;
- 不要在 Vue/React 组件的
useEffect或mounted里反复创建<link>,容易内存泄漏 - 通过
document.querySelector('link[href*="theme"]')定位已有主题 link,比遍历所有 link 更可靠
@import 的相对路径错一级,或 <link> 插入顺序颠倒,就可能导致变量未定义或覆盖失效。










