CSS样式失效主因是加载顺序错位、框架scoped与全局样式冲突、构建工具导致CSS并行加载不可控、缓存机制使旧样式残留;需通过DevTools检查覆盖规则、加载时序及响应头。

确认是不是真的被覆盖,还是根本没加载
打开浏览器开发者工具 → Elements 面板选中目标元素 → 右侧 Styles 面板里找带删除线(strikethrough)的样式声明。如果 .btn 被划掉,且旁边文件名指向你写的 app.css,但该 <link> 标签在组件库(如 element-plus.css)之前,那才是顺序问题;如果文件名是 404 或根本没出现在 Styles 面板里,说明 CSS 根本没加载成功——先去 Network 面板确认状态码是不是 200。
Vite/React/Vue 中 import 顺序 ≠ HTML 里 link 顺序
你在 main.tsx 或 main.js 里写 import 'element-plus/dist/index.css',又在后面 import './styles/app.css',这看似对了,但 Vite 的 HMR 热更新、CSS 注入插件(比如 vite-plugin-css-injected-by-js)可能把后者插入到 最末尾,天然晚于静态 <link>。React 项目用 createRoot 渲染前动态注入样式也一样——它总比 HTML 里写的 <link> 晚。
- 检查最终生成的 HTML(不是源码),看实际
<link>顺序是否符合预期 - Vite 用户:禁用或配置
css.preprocessorOptions中可能干扰注入的插件 - React/Vue 全局引入时,把组件库 CSS 放在所有自定义样式 之后,而不是之前
:deep() 单独写等于没写
Vue 3 的 :deep() 不是全局开关,它必须挂在一个当前组件真实存在的选择器下才有效。比如你在 <style scoped></style> 里只写 :deep(.el-button),编译后这条规则会直接消失;必须写成 .my-form :deep(.el-button),其中 .my-form 是你模板里真实加在容器上的 class。
-
:deep()里不能写空格分隔的选择器,:deep(.el-input .el-input__inner)无效,只能写:deep(.el-input__inner) - 第三方组件若用动态类名(如
v-bind:class="['el-button', type && `el-button--${type}`]"),得 inspect 实际渲染出的 class,不能照文档抄 - React 没有
:deep(),要用!important或提升权重(如body .el-button)
真正难的不是调顺序,是让顺序在构建、热更、部署全链路稳定
本地开发时改个 import 顺序就生效,打包后却失效,往往是因为构建工具把 CSS 提取合并了——Webpack 的 MiniCssExtractPlugin 按 JS import 顺序打包,Vite 的 build.rollupOptions.output.manualChunks 可能按模块拆分打乱原始顺序。Laravel Mix 里用 mix.styles() 单独引入 CSS,它会被排在 app.css 后面,形成隐性覆盖。这些环节里,顺序不是写出来就固定的,而是由构建配置、插件行为、甚至 HMR 生命周期共同决定的。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











