Sass Customization
1. Lesson Introduction
(1) Prerequisites
- Comprehensive practice of an enterprise website homepage (Lesson 19)
- Basic usage of Node.js and the npm package manager
- Concepts of CSS variables and preprocessors
(2) 🎯 What You'll Learn
- Setting up a Bootstrap Sass development environment
- Customizing brand colors, spacing, and typography through variable overriding
- Selectively importing Bootstrap components to reduce file size
- Extending custom utility classes
- Writing a complete Sass compilation script
(3) Pain Point
Bob's company brand color is purple (not Bootstrap's default blue), and all buttons, links, and borders need to be changed to the brand color. Using the CDN method, Bootstrap's preset styles cannot be modified, requiring manual overriding of a large amount of CSS every time.
(4) Solution
The previous 19 lessons used the CDN method to include Bootstrap, with all styles being presets. This lesson begins Phase 5—deep customization of Bootstrap through Sass, giving you full control over everything from colors and spacing to component styles. With Sass variable overriding, you only need to change one line: $primary: purple;.
Understanding the Approach: CDN method = eating fast food (quick but no choice). Sass customization = cooking your own meal (slower but adjustable taste). Sass variables are like a seasoning recipe—changing one variable automatically updates all related components.
(5) Benefits
Bob only needs to modify a few Sass variables, and all buttons, links, and borders will automatically change to the brand purple color. Future brand color adjustments only require changing one place for global effect, significantly reducing maintenance costs.
2. Environment Setup
You need a Node.js and npm environment:
# Create project
mkdir my-bootstrap-project
cd my-bootstrap-project
# Initialize
npm init -y
# Install Bootstrap and its dependencies
npm install bootstrap@5.3.3
npm install -D sass
Project directory structure:
my-bootstrap-project/
scss/
custom.scss # Your custom Sass file
dist/
style.css # Compiled CSS
index.html
package.json
3. Basic Variable Overriding
▶ Example: Basic Variable Overriding Demo
scss/custom.scss:
// 1. Override Bootstrap variables (must be before importing bootstrap)
$primary: #6f42c1; // Purple brand color
$success: #20c997; // Teal
$font-family-sans-serif: 'Inter', system-ui, -apple-system, sans-serif;
$border-radius: 0.5rem; // 8px rounded corners
$enable-shadows: true; // Enable shadow utilities
// 2. Import full Bootstrap
@import "../node_modules/bootstrap/scss/bootstrap";
// 3. Custom styles
.custom-hero {
background: linear-gradient(135deg, $primary, darken($primary, 15%));
}
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default. Compile command:
npx sass scss/custom.scss:dist/style.css --style compressed
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sass Custom Bootstrap</title>
<link rel="stylesheet" href="dist/style.css">
</head>
<body>
<div class="container py-5">
<button class="btn btn-primary">Primary (Purple)</button>
<button class="btn btn-success">Success (Teal)</button>
<div class="card shadow-sm mt-3 p-4" style="max-width: 400px;">
<h5>Custom Card</h5>
<p class="text-body-secondary">Border-radius is 0.5rem, shadows enabled.</p>
</div>
</div>
</body>
</html>
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
4. Key Overridable Variables
(1) Colors
// Brand colors
$primary: #6f42c1;
$secondary: #6c757d;
$success: #20c997;
$info: #0dcaf0;
$warning: #ffc107;
$danger: #dc3545;
$light: #f8f9fa;
$dark: #212529;
// Custom colors
$custom-color: #ff6b6b;
$theme-colors: map-merge($theme-colors, (
"custom": $custom-color,
));
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default. After adding a custom color, you can use
btn-custom,text-custom,bg-custom.
(2) Spacing
$spacer: 1rem; // Base spacer (default 1rem = 16px)
$spacers: (
0: 0,
1: $spacer * 0.25, // 4px
2: $spacer * 0.5, // 8px
3: $spacer, // 16px
4: $spacer * 1.5, // 24px
5: $spacer * 3, // 48px
6: $spacer * 4, // 64px (custom)
7: $spacer * 5, // 80px (custom)
);
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
(3) Typography
$font-family-sans-serif: 'Inter', system-ui, -apple-system, sans-serif;
$font-size-base: 1rem; // 16px
$h1-font-size: $font-size-base * 2.5; // 40px
$headings-font-weight: 600;
$line-height-base: 1.7; // More readable
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
(4) Components
$border-radius: 0.5rem;
$border-radius-lg: 0.75rem;
$border-radius-sm: 0.25rem;
$btn-border-radius: $border-radius;
$card-border-radius: $border-radius-lg;
$card-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
5. Selective Component Import
The complete Bootstrap CSS is approximately 250KB (unminified). If you only use some components, you can import only the necessary modules:
// Required
@import "../node_modules/bootstrap/scss/functions";
@import "../node_modules/bootstrap/scss/variables";
@import "../node_modules/bootstrap/scss/variables-dark";
@import "../node_modules/bootstrap/scss/maps";
@import "../node_modules/bootstrap/scss/mixins";
@import "../node_modules/bootstrap/scss/root";
// Optional - pick what you need
@import "../node_modules/bootstrap/scss/reboot";
@import "../node_modules/bootstrap/scss/type";
@import "../node_modules/bootstrap/scss/grid";
@import "../node_modules/bootstrap/scss/forms";
@import "../node_modules/bootstrap/scss/buttons";
@import "../node_modules/bootstrap/scss/card";
@import "../node_modules/bootstrap/scss/navbar";
@import "../node_modules/bootstrap/scss/utilities";
@import "../node_modules/bootstrap/scss/helpers";
// Utilities API (required if using utilities)
@import "../node_modules/bootstrap/scss/utilities/api";
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
6. Utility Class Extension
// Add custom utilities
$utilities: map-merge(
$utilities, (
"cursor": map-merge(
map-get($utilities, "cursor"),
(
values: map-merge(
map-get(map-get($utilities, "cursor"), "values"),
(pointer: pointer, grab: grab)
),
),
),
)
);
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
7. Comprehensive Practical Examples
▶ Example: Complete Custom Theme
// scss/custom-theme.scss — Complete custom theme
// ==========================================
// 1. Brand Colors
$primary: #e83e8c; // Pink
$secondary: #6c757d; // Gray
$success: #28a745; // Green
$info: #17a2b8; // Teal
$warning: #ffc107; // Yellow
$danger: #dc3545; // Red
// 2. Typography
$font-family-sans-serif: 'Inter', system-ui, -apple-system, sans-serif;
$font-size-base: 0.9375rem; // 15px
$headings-font-weight: 700;
$line-height-base: 1.7;
// 3. Spacing
$spacer: 1rem;
$spacers: (
0: 0,
1: $spacer * 0.25,
2: $spacer * 0.5,
3: $spacer,
4: $spacer * 1.5,
5: $spacer * 3,
6: $spacer * 4,
7: $spacer * 5,
);
// 4. Border & Shadow
$border-radius: 0.375rem;
$border-radius-lg: 0.5rem;
$border-radius-sm: 0.25rem;
$enable-shadows: true;
// 5. Component Tweaks
$btn-border-radius: 50rem; // Pill buttons
$card-border-color: rgba(0,0,0,0.08);
$card-box-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.075);
$navbar-dark-color: rgba(255,255,255,0.9);
// 6. Import Bootstrap
@import "../node_modules/bootstrap/scss/bootstrap";
// 7. Custom Extensions
.custom-gradient-bg {
background: linear-gradient(135deg, $primary, darken($primary, 15%));
}
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Custom Theme Demo</title>
<link rel="stylesheet" href="dist/style.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand fw-bold" href="#">Brand</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#nav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="nav">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link active" href="#">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#">About</a></li>
<li class="nav-item"><a class="nav-link" href="#">Pricing</a></li>
</ul>
</div>
</div>
</nav>
<div class="container py-5">
<h1>Custom Bootstrap Theme</h1>
<p class="lead">Brand color: <span class="text-primary fw-bold">Pink (#e83e8c)</span></p>
<div class="d-flex gap-2 mb-4 flex-wrap">
<button class="btn btn-primary">Primary</button>
<button class="btn btn-secondary">Secondary</button>
<button class="btn btn-success">Success</button>
<button class="btn btn-danger">Danger</button>
<button class="btn btn-warning">Warning</button>
<button class="btn btn-info">Info</button>
</div>
<div class="row g-4">
<div class="col-md-4">
<div class="card p-4 shadow-sm">
<h5>Custom Card</h5>
<p class="text-body-secondary">Border-radius: 0.5rem, pill buttons above.</p>
<button class="btn btn-primary rounded-pill">Pill Button</button>
</div>
</div>
<div class="col-md-4">
<div class="card p-4 shadow-sm">
<h5>Spacing Test</h5>
<p class="text-body-secondary">Custom spacers p-6 and p-7 available.</p>
<div class="bg-light p-6 rounded">p-6 (4rem padding)</div>
</div>
</div>
<div class="col-md-4">
<div class="card p-4 shadow-sm bg-primary text-white">
<h5>Gradient BG</h5>
<p class="text-white-50">Using custom-gradient-bg class.</p>
</div>
</div>
</div>
</div>
</body>
</html>
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
▶ Example: Utility Class Extension
// scss/utilities-extend.scss
// ==========================================
$primary: #6f42c1;
@import "../node_modules/bootstrap/scss/functions";
@import "../node_modules/bootstrap/scss/variables";
@import "../node_modules/bootstrap/scss/maps";
@import "../node_modules/bootstrap/scss/mixins";
@import "../node_modules/bootstrap/scss/root";
// Extend utilities
$utilities: map-merge(
$utilities, (
// Add cursor utilities
"cursor": map-merge(
map-get($utilities, "cursor"),
(values: map-merge(
map-get(map-get($utilities, "cursor"), "values"),
(pointer: pointer, grab: grab, zoom: zoom-in)
))
),
// Add opacity utilities
"opacity": (
property: opacity,
values: (0: 0, 25: 0.25, 50: 0.5, 75: 0.75, 100: 1),
),
// Custom width steps
"width": map-merge(
map-get($utilities, "width"),
(values: map-merge(
map-get(map-get($utilities, "width"), "values"),
(15: 15%, 35: 35%, 65: 65%)
))
),
)
);
@import "../node_modules/bootstrap/scss/utilities";
@import "../node_modules/bootstrap/scss/utilities/api";
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Extended Utilities</title>
<link rel="stylesheet" href="dist/utilities-extend.css">
</head>
<body>
<div class="container py-4">
<h5>Custom Cursor Utilities</h5>
<div class="d-flex gap-3 mb-4">
<div class="border p-3 cursor-pointer">cursor-pointer</div>
<div class="border p-3 cursor-grab">cursor-grab</div>
<div class="border p-3 cursor-zoom">cursor-zoom</div>
</div>
<h5>Custom Width Steps</h5>
<div class="w-15 bg-primary text-white p-2 mb-1 rounded">w-15</div>
<div class="w-35 bg-success text-white p-2 mb-1 rounded">w-35</div>
<div class="w-65 bg-info text-white p-2 mb-1 rounded">w-65</div>
<h5>Opacity Utilities</h5>
<div class="d-flex gap-2">
<div class="bg-primary text-white p-3 opacity-100 rounded">100%</div>
<div class="bg-primary text-white p-3 opacity-75 rounded">75%</div>
<div class="bg-primary text-white p-3 opacity-50 rounded">50%</div>
<div class="bg-primary text-white p-3 opacity-25 rounded">25%</div>
</div>
</div>
</body>
</html>
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
▶ Example: Sass Dark Mode
// scss/dark-theme.scss
// ==========================================
$enable-dark-mode: true;
// Light color overrides
$primary: #0d6efd;
$body-bg: #ffffff;
$body-color: #212529;
// Dark mode overrides
$dark-bg: #0d1117;
$dark-surface: #161b22;
$dark-border: #30363d;
$primary-dark: #58a6ff;
@import "../node_modules/bootstrap/scss/bootstrap";
// Dark theme custom styles
[data-bs-theme="dark"] {
--bs-body-bg: #{$dark-bg};
--bs-body-color: #c9d1d9;
--bs-card-bg: #{$dark-surface};
--bs-border-color: #{$dark-border};
}
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sass Dark Mode</title>
<link rel="stylesheet" href="dist/dark-theme.css">
</head>
<body>
<div class="container py-4">
<div class="d-flex justify-content-between mb-4">
<h5>Sass Dark Mode Demo</h5>
<button class="btn btn-outline-primary btn-sm" onclick="toggleTheme()">
<i class="bi bi-moon"></i> Toggle
</button>
</div>
<div class="row g-3">
<div class="col-md-4">
<div class="card p-4">
<h5>Card Title</h5>
<p>This card adapts to the current theme.</p>
<button class="btn btn-primary">Button</button>
</div>
</div>
<div class="col-md-4">
<div class="card p-4">
<h5>Dark Surface</h5>
<p>Custom dark variables applied via Sass.</p>
<div class="alert alert-info">Info alert</div>
</div>
</div>
<div class="col-md-4">
<div class="card p-4">
<h5>Border Colors</h5>
<p>Card border uses custom $dark-border.</p>
<div class="border p-2 rounded">Bordered box</div>
</div>
</div>
</div>
</div>
<script>
function toggleTheme() {
const html = document.documentElement;
const next = html.getAttribute('data-bs-theme') === 'dark' ? 'light' : 'dark';
html.setAttribute('data-bs-theme', next);
}
</script>
</body>
</html>
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
▶ Example: Component Customization
// scss/component-custom.scss
// ==========================================
$primary: #6f42c1;
$border-radius: 0.5rem;
// Card customization
$card-border-radius: 0.75rem;
$card-cap-bg: transparent;
$card-box-shadow: 0 0.5rem 1.5rem rgba(106, 13, 173, 0.1);
$card-border-color: rgba(106, 13, 173, 0.15);
// Button customization
$btn-padding-y-lg: 0.75rem;
$btn-padding-x-lg: 2rem;
$btn-font-weight: 600;
// Navbar customization
$navbar-padding-y: 1rem;
$navbar-brand-font-size: 1.5rem;
// Form customization
$input-border-radius: 0.5rem;
$input-focus-border-color: $primary;
$input-focus-box-shadow: 0 0 0 0.25rem rgba(106, 13, 173, 0.25);
@import "../node_modules/bootstrap/scss/bootstrap";
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Component Customization</title>
<link rel="stylesheet" href="dist/component-custom.css">
</head>
<body>
<div class="container py-4">
<h5>Custom Cards</h5>
<div class="row g-4 mb-5">
<div class="col-md-4">
<div class="card p-4">
<div class="card-body">
<h5 class="card-title">Purple Theme Card</h5>
<p class="card-text">Rounded 0.75rem, purple border, custom shadow.</p>
<a href="#" class="btn btn-primary">Read More</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card p-4">
<div class="card-body text-center">
<h5 class="card-title">Centered Card</h5>
<p class="card-text">Custom card-cap background removed.</p>
<a href="#" class="btn btn-outline-primary">Details</a>
</div>
</div>
</div>
</div>
<h5>Custom Buttons</h5>
<div class="d-flex gap-2 mb-4">
<button class="btn btn-primary btn-lg">Large Custom</button>
<button class="btn btn-primary">Default</button>
<button class="btn btn-primary btn-sm">Small</button>
</div>
<h5>Custom Forms</h5>
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control mb-2" placeholder="Custom input focus...">
<select class="form-select">
<option>Option 1</option>
<option>Option 2</option>
</select>
</div>
</div>
</div>
</body>
</html>
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
(1) Sass Compilation Flow
graph LR
A[custom.scss<br/>Variable overriding + custom styles] --> B[Sass compiler]
C[bootstrap/scss/] --> B
B --> D[style.css<br/>Full compilation]
D --> E[PurgeCSS]
E --> F[style.min.css<br/>Only used classes remain]
F --> G[Browser loading]
H[--watch mode] -.-> B
I[--style compressed] -.-> D
Output: Bootstrap 5.3 styled component effects (e.g., buttons, cards, carousel, collapse, etc.). The page uses the Bootstrap default theme (light) and responsive grid by default.
(2) Core Variable Reference Table
| Variable Name | Default Value | Purpose | Scope of Impact |
|---|---|---|---|
$primary |
#0d6efd |
Theme primary color | Buttons, links, backgrounds, borders |
$font-size-base |
1rem |
Base font size | Global body text size |
$spacer |
1rem |
Spacing base value | All spacing p-* m-* gap-* |
$border-radius |
0.375rem |
Base border-radius | Buttons, cards, inputs |
$enable-shadows |
true |
Enable shadows | shadow-* utility classes |
$enable-dark-mode |
true |
Dark mode support | data-bs-theme support |
$font-family-sans-serif |
System font stack | Font family | Global body font |
(3) Component Variable Prefix Table
| Component | Variable Prefix | Example Variables |
|---|---|---|
| Button | $btn-* |
$btn-border-radius $btn-padding-y |
| Card | $card-* |
$card-border-radius $card-box-shadow |
| Navbar | $navbar-* |
$navbar-padding-y $navbar-dark-color |
| Form | $input-* |
$input-border-radius $input-focus-box-shadow |
| Modal | $modal-* |
$modal-backdrop-bg $modal-content-border-radius |
| Table | $table-* |
$table-bg $table-striped-order |
| Alert | $alert-* |
$alert-border-radius $alert-link-font-weight |
(4) Build Tool Comparison Table
| Tool | Purpose | Configuration Difficulty | Bootstrap Compatibility | Recommended Scenario |
|---|---|---|---|---|
sass (Dart Sass) |
Compile SCSS to CSS | ⭐ | Officially recommended | Simple projects, Sass only |
| Webpack | Module bundling + Sass compilation | ⭐⭐⭐ | Commonly used | Large SPA projects |
| Vite | Fast build + Sass compilation | ⭐⭐ | Recommended | Modern frontend projects |
| Parcel | Zero-config build | ⭐ | Usable | Rapid prototyping, small projects |
| Gulp | Task runner | ⭐⭐⭐ | Classic combination | Traditional projects, multi-task workflows |
❓ Frequently Asked Questions
node-sass or sass version is compatible with Bootstrap 5.3. It is recommended to use sass (Dart Sass). Use npx sass for compilation commands instead of global installation.--bs-primary, --bs-border-radius, etc., in :root without a compilation tool. However, the Sass approach is more flexible (supports calculations, loops, custom functions).@import bootstrap. Sass variable scope is order-dependent—they must be defined before they are used to take effect._variables.scss; (3) Overrides in custom.scss before @import; (4) Custom styles after @import. Note: CSS variables (--bs-primary) have higher priority than Sass variables. You can use :root { --bs-primary: red; } to override without recompilation.📖 Summary
- Sass customization flow: Install npm → Create
custom.scss→ Override variables → Import Bootstrap → Compile - Key overridable variables for colors, spacing, typography, component border-radius, etc.
- Selective component import to reduce file size
- Compile command:
npx sass scss/custom.scss dist/style.css
📝 Assignment
- ⭐ Create a project using Bootstrap Sass: set the brand color to
#e83e8c(pink), button border-radius to0.25rem, and base font size to15px. - ⭐⭐ Selective component import: only import grid, buttons, cards, forms, and navbar modules. Compile and compare the file size difference with the full Bootstrap.
- ⭐⭐⭐ Custom spacing: add
spacer-6= 4rem andspacer-7= 6rem. Verify ifp-6andmt-7work.
Previous Lesson: Comprehensive Practice: Enterprise Website Homepage · Next Lesson: Dark Mode



