最准确方法是用DevTools Network面板筛选stylesheet请求,它涵盖所有实际加载的CSS(含@import子请求),而document.styleSheets.length包含未完成或无效项,querySelectorAll('link[rel="stylesheet"]')则漏掉JS动态插入、@import和preload转正的样式表。

用 DevTools 的 Network 面板直接数 stylesheet 请求
打开 Chrome 或 Edge,按 F12 → 切到 Network 标签 → 刷新页面 → 在筛选栏输入 stylesheet。所有命中 type: stylesheet 的请求就是实际被引入的 CSS 文件(含 link rel="stylesheet" 和 @import 触发的)。
注意:media="print" 或 media="(prefers-color-scheme: dark)" 的 link 仍会出现在这里,它们被下载但不参与屏幕渲染;而 disabled="true" 的 link 不会发起请求,不会被统计。
- 常见误判:看到
main.css后面跟着chunk-abc123.css,别急着当成两个——后者可能是构建工具拆包产物,需点开看Initiator列确认是否由 JS 动态插入 - 如果用了
@import,它会在 Network 中显示为子请求,Initiator显示父 CSS 文件名,这种链式加载会拉长整体阻塞时间 - HTTP/2 下多个
stylesheet请求可能复用同一连接,但请求数量仍等于link标签数(不含@import的深层嵌套)
用 JavaScript 脚本快速统计 document.styleSheets
document.styleSheets 返回的是当前页面所有已解析的样式表对象数组,包括内联 、link 加载的、以及 JS 创建的 CSSStyleSheet。执行以下代码即可获得总数:
console.log('CSS 文件数量:', document.styleSheets.length);
但要注意:这个值包含无效或未加载完成的项。比如 href 404 的 link 仍会出现在 document.styleSheets 中(cssRules 为空),而动态插入后尚未解析的 link 可能还未计入。
- 只统计外链 CSS:过滤出
sheet.href存在且非空的项 - 排除内联样式:
Array.from(document.styleSheets).filter(s => s.href) - 排除禁用样式表:
s.disabled === false
为什么 document.querySelectorAll('link[rel="stylesheet"]') 结果不准
这个选择器只匹配 HTML 中静态写死的 link 标签,漏掉三类关键情况:
- JS 动态插入的
link(如按需加载弹窗样式)—— 它们在 DOM 中存在,但可能还没触发load事件 -
@import引入的 CSS —— 完全不生成link元素,却实实在在增加了一个样式表 - 预加载后才转正的样式:
,初始时是rel="preload",不会被选中
所以单纯数 link[rel="stylesheet"] 往往比真实生效的样式表少 1–3 个,尤其在 SPA 或渐进增强场景下偏差明显。
构建产物里怎么查最终打包了多少 CSS 文件
开发阶段看到 5 个 link,不代表上线后还是 5 个。真正要盯的是构建输出目录(如 dist/ 或 build/)里的实际文件数:
- Vite 项目:检查
dist/assets/*.css,默认会把非异步 CSS 合并为 1–2 个带 hash 的文件 - Webpack 项目:看
mini-css-extract-plugin输出路径,若配置了splitChunks,可能生成vendor.css+main.css - 没用构建工具?那 HTML 里有几个
link,就真有几个 HTTP 请求——这时候必须人工合并或加media条件隔离
最容易被忽略的是:某些框架(如 Next.js)会自动内联 pages/_app.tsx 中 import 的 CSS,它不会出现在 Network 的 stylesheet 列表里,但会进入 document.styleSheets。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











