直接修改 $primary 变量即可更换主题色,但必须在 bootstrap sass 源码引入前覆盖变量;正确顺序是:先导入自定义变量文件,再导入 functions,最后导入 bootstrap 主文件。
直接改 $primary 变量就能换主题色,但得在 bootstrap 源码引入前覆盖
bootstrap 的 sass 主题定制本质就是“提前重定义变量”,不是后期覆盖 css 类。如果你在 @import "bootstrap" 之后写 $primary: #ff6b6b;,完全无效——sass 编译时变量已锁定。
正确做法是:新建一个 _custom.scss(或类似入口文件),按顺序做三件事:
- 先
@import你自己的变量覆盖文件(比如_variables.scss) - 再
@import "bootstrap/scss/functions"; - 最后
@import "bootstrap/scss/bootstrap";
这样 $primary、$body-bg、$font-family-sans-serif 等所有默认变量才能被你的值接管。别图省事只改一个变量就跑,Bootstrap 内部有大量依赖链(比如 $btn-primary-bg 默认取 $primary),漏掉上游变量会导致按钮色没变但边框色异常。
!default 是开关,不是保险丝——不声明 !default 的变量根本不能被覆盖
Bootstrap 官方变量大多带 !default(如 $primary: #0d6efd !default;),这是它允许你覆盖的前提。但注意:部分内部计算变量(比如 $theme-colors 映射表)不带 !default,你不能直接重赋值,必须从源头变量入手。
常见踩坑点:
- 试图直接改
$theme-colors: ("primary": #007bff) !default;→ 编译报错或静默失败 - 改了
$primary却忘了同步改$primary-rgb→ 导致rgba($primary-rgb, .5)报错,因为$primary-rgb还是旧值 - 用深色模式时只改
$body-bg,但没动$body-color→ 文字和背景对比度崩了
查变量是否可覆盖,最稳方式是翻 Bootstrap 的 scss/_variables.scss 源码,Ctrl+F 搜 !default。
自定义主题要生效,必须确保编译时加载的是 Sass 源码,不是已编译的 CSS
如果你用的是 npm 安装的 Bootstrap,路径必须指向 node_modules/bootstrap/scss/,而不是 node_modules/bootstrap/dist/css/。后者是纯 CSS 文件,改任何 Sass 变量都毫无意义。
典型错误配置:
- Vite 项目里在
styles.css中@import "bootstrap/dist/css/bootstrap.min.css";→ 此路不通 - Webpack 中
style-loader+css-loader加载了 CSS,却没配sass-loader→ Sass 文件压根没编译 - 用了 Bootstrap CDN 链接 → 只能靠 JS 或覆盖类名硬改,Sass 变量彻底失效
验证是否走对路:改一个明显变量(比如 $body-bg: pink;),保存后页面背景变粉,才算真正接入 Sass 流程。
深色主题、多主题切换别硬套变量,优先用 prefers-color-scheme + CSS 自定义属性
Sass 变量是编译时静态的,一套构建产物只能有一种主题。想运行时切主题(比如用户点击切换深色模式),硬靠 Sass 生成多套 CSS 文件会极大增加维护成本和包体积。
更务实的做法:
- 保留 Sass 控制基础设计系统(字体、间距、主色系),但把可变色值抽成 CSS 自定义属性(
--bs-primary: #0d6efd;) - 用
@media (prefers-color-scheme: dark)或 JS 切换html[data-theme="dark"],然后批量重设这些属性 - Bootstrap 5.3+ 已内置部分暗色支持(如
.bg-body-tertiary),可配合使用,减少重复劳动
强行用 Sass 多次编译 dark/light 版本,容易导致 class 名冲突、JS 组件状态错乱,尤其当用到 data-bs-* 属性控制行为时。










