Bootstrap 5 Tutorial
v5.3.0Bootstrap 5 Tutorial
Customizing Bootstrap 5
Why Customize Bootstrap?
While Bootstrap provides excellent defaults, customization allows you to create unique designs that match your brand identity while maintaining all the benefits of the framework.
Default Bootstrap
Standard Bootstrap appearance
Light Customization
Modified colors and styles
Heavy Customization
Complete design overhaul
Customization Methods
Four Approaches to Customization
1. CSS Overrides
Override Bootstrap styles with custom CSS.
/* Override in custom CSS */
.btn-primary {
background-color: #8a2be2;
border-color: #8a2be2;
}2. CSS Variables
Use Bootstrap's CSS custom properties.
/* Override CSS variables */
:root {
--bs-primary: #8a2be2;
--bs-primary-rgb: 138, 43, 226;
}3. Sass Variables
Customize Bootstrap at build time with Sass.
// Customize Sass variables
$primary: #8a2be2;
$enable-rounded: false;
@import "bootstrap";4. Build Tools
Use Bootstrap's official build tools.
# Clone Bootstrap repo
git clone https://github.com/twbs/bootstrap.git
# Customize and build
npm run cssRecommendation:
For most projects, use Sass variables for build-time customization and CSS variables for runtime theming (like dark mode). CSS overrides are good for quick fixes, and build tools are for advanced use cases.
Customizing with Sass Variables
Sass-Based Customization
Bootstrap 5 is built with Sass, allowing you to customize virtually every aspect before compilation.
Basic Sass Customization
// custom.scss
// 1. Override default variables
$primary: #8a2be2; // Custom purple
$secondary: #20b2aa; // Custom teal
$success: #00ab66; // Custom green
$info: #17a2b8; // Keep default
$warning: #ffc107; // Keep default
$danger: #dc3545; // Keep default
$light: #f8f9fa; // Keep default
$dark: #212529; // Keep default
// 2. Customize components
$border-radius: 0.5rem; // Larger border radius
$border-radius-lg: 0.75rem;
$border-radius-sm: 0.25rem;
// 3. Customize typography
$font-family-sans-serif: 'Inter', system-ui, -apple-system, sans-serif;
$font-size-base: 1.1rem; // Slightly larger base font
$headings-font-weight: 700;
// 4. Disable features you don't need
$enable-rounded: true; // Keep rounded corners
$enable-shadows: true; // Enable shadows
$enable-gradients: false; // Disable gradients
$enable-transitions: true;
// 5. Import Bootstrap
@import "bootstrap/scss/bootstrap";Advanced Sass Customization
// advanced-custom.scss
// Custom color palette
$custom-colors: (
"indigo": #6610f2,
"purple": #6f42c1,
"pink": #d63384,
"orange": #fd7e14,
"teal": #20c997,
"cyan": #0dcaf0
);
// Add to theme colors map
$theme-colors: map-merge($theme-colors, $custom-colors);
// Custom spacing scale
$spacer: 1rem;
$spacers: (
0: 0,
1: $spacer * .25, // 0.25rem
2: $spacer * .5, // 0.5rem
3: $spacer, // 1rem
4: $spacer * 1.5, // 1.5rem
5: $spacer * 3, // 3rem
6: $spacer * 4.5, // 4.5rem
7: $spacer * 6 // 6rem
);
// Custom breakpoints
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
xxl: 1400px,
xxxl: 1600px // Custom breakpoint
);
// Custom container sizes
$container-max-widths: (
sm: 540px,
md: 720px,
lg: 960px,
xl: 1140px,
xxl: 1320px,
xxxl: 1500px // Custom container size
);
// Import Bootstrap
@import "bootstrap/scss/bootstrap";Build Process with Sass:
# Using npm scripts in package.json
{
"scripts": {
"build-css": "sass scss/custom.scss:dist/css/bootstrap.css",
"watch-css": "sass --watch scss/custom.scss:dist/css/bootstrap.css"
}
}
# Run build
npm run build-css
# Watch for changes
npm run watch-css# Using command line directly
sass scss/custom.scss css/custom.css
# With compression
sass scss/custom.scss css/custom.min.css --style=compressed
# With source maps
sass scss/custom.scss css/custom.css --source-map
# Watch mode for development
sass --watch scss/custom.scss:css/custom.cssImportant Sass Tips:
- Variable order matters: Override variables before importing Bootstrap
- Use map-merge for maps: Don't override entire maps, merge your changes
- Check available variables: See
node_modules/bootstrap/scss/_variables.scss - Test changes: Small changes can have wide-ranging effects
- Keep backups: Version control your custom Sass files
CSS Custom Properties (Variables)
Runtime Customization with CSS Variables
Bootstrap 5 includes CSS custom properties for many values, allowing runtime customization without recompilation.
Basic CSS Variable Overrides
/* Override in your CSS file */
:root {
/* Theme colors */
--bs-primary: #8a2be2;
--bs-primary-rgb: 138, 43, 226;
--bs-secondary: #20b2aa;
--bs-secondary-rgb: 32, 178, 170;
/* Typography */
--bs-font-sans-serif: 'Inter', system-ui, -apple-system, sans-serif;
--bs-body-font-size: 1.1rem;
--bs-body-color: #212529;
/* Spacing */
--bs-border-radius: 0.5rem;
--bs-border-radius-lg: 0.75rem;
--bs-border-radius-sm: 0.25rem;
/* Shadows */
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}
/* For dark mode */
[data-bs-theme="dark"] {
--bs-body-bg: #212529;
--bs-body-color: #adb5bd;
--bs-primary: #6610f2;
}Dynamic CSS Variable Changes
/* CSS: Define themes */
:root {
--theme-primary: #0d6efd;
--theme-border-radius: 0.375rem;
}
.theme-rounded {
--theme-border-radius: 1rem;
}
.theme-flat {
--theme-border-radius: 0;
}
/* Apply to Bootstrap components */
.btn-primary {
background-color: var(--theme-primary);
border-radius: var(--theme-border-radius);
}
/* JavaScript: Change themes dynamically */
// Change primary color
document.documentElement.style.setProperty(
'--theme-primary',
'#8a2be2'
);
// Toggle theme class
document.documentElement.classList.toggle('theme-rounded');
// Load theme from localStorage
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
document.documentElement.setAttribute('data-bs-theme', savedTheme);
}
// Save theme preference
function setTheme(theme) {
document.documentElement.setAttribute('data-bs-theme', theme);
localStorage.setItem('theme', theme);
}When to Use CSS Variables vs Sass:
| Use CSS Variables For | Use Sass Variables For |
|---|---|
| Runtime theming (light/dark mode) | Build-time configuration |
| User-customizable interfaces | Brand colors and typography |
| Dynamic color schemes | Structural changes (grid, breakpoints) |
| JavaScript-controlled styles | Performance-critical optimizations |
| Progressive enhancement | Removing unused components |
Component-Specific Customization
Customizing Individual Components
Buttons
// Sass variables
$btn-padding-y: 0.75rem;
$btn-padding-x: 1.5rem;
$btn-border-radius: 50px;
$btn-font-weight: 600;
// CSS overrides
.btn {
text-transform: uppercase;
letter-spacing: 0.5px;
}
.btn-primary {
box-shadow: 0 4px 6px rgba(13, 110, 253, 0.2);
}Cards
// Sass variables
$card-border-radius: 1rem;
$card-border-width: 0;
$card-box-shadow: 0 10px 20px rgba(0,0,0,0.1);
// CSS overrides
.card {
transition: transform 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
}Custom card with hover effect
Forms
// Sass variables
$input-border-radius: 0.5rem;
$input-border-width: 2px;
$input-focus-border-color: $primary;
// CSS overrides
.form-control {
padding: 0.75rem 1rem;
}
.form-control:focus {
box-shadow: 0 0 0 0.25rem rgba(138, 43, 226, 0.25);
}Creating Custom Components:
// custom-components.scss
// Custom alert variant
.alert-gradient {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: $border-radius-lg;
.alert-link {
color: rgba(255, 255, 255, 0.9);
text-decoration: underline;
}
}
// Custom button variant
.btn-glass {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
&:hover {
background: rgba(255, 255, 255, 0.2);
border-color: rgba(255, 255, 255, 0.3);
}
}
// Custom card variant
.card-hover {
overflow: hidden;
position: relative;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 5px;
background: linear-gradient(90deg, $primary, $success);
}
&:hover {
box-shadow: $box-shadow-lg;
}
}Build Tools & Optimization
Optimizing Your Custom Build
Removing Unused Components
// minimal-custom.scss
// 1. Import Bootstrap functions first
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/mixins";
// 2. Override variables
$primary: #8a2be2;
$font-family-base: 'Inter', sans-serif;
// 3. Import only what you need
// Layout & components
@import "bootstrap/scss/root";
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/type";
@import "bootstrap/scss/images";
@import "bootstrap/scss/containers";
@import "bootstrap/scss/grid";
// Utilities
@import "bootstrap/scss/utilities";
@import "bootstrap/scss/utilities/api";
// Custom components (only what you use)
@import "bootstrap/scss/buttons";
@import "bootstrap/scss/forms";
@import "bootstrap/scss/card";
@import "bootstrap/scss/alert";
// Don't import components you don't use:
// @import "bootstrap/scss/carousel";
// @import "bootstrap/scss/modal";
// @import "bootstrap/scss/dropdown";Using PurgeCSS
Remove unused CSS from your final bundle.
// postcss.config.js
module.exports = {
plugins: [
require('@fullhuman/postcss-purgecss')({
content: [
'./src/**/*.html',
'./src/**/*.vue',
'./src/**/*.jsx',
'./src/**/*.js'
],
defaultExtractor: content =>
content.match(/[A-Za-z0-9-_:/]+/g) || [],
safelist: [
/^bg-/,
/^text-/,
/^border-/,
/:hover$/,
/:focus$/,
/^btn-/,
/^alert-/
]
})
]
}PurgeCSS Tips:
- Use safelist for dynamically added classes
- Test thoroughly after purging
- Monitor bundle size reductions
- Consider critical CSS extraction
Build Size Comparison:
| Build Type | CSS Size | Reduction | Best For |
|---|---|---|---|
| Full Bootstrap | ~200KB (unminified) | 0% | Prototyping, simple sites |
| Minified | ~160KB | 20% | Production (default) |
| Custom (selective import) | 50-100KB | 50-75% | Custom applications |
| Custom + PurgeCSS | 20-50KB | 75-90% | Performance-critical apps |
Theme Creation Tools
Custom Build
Create your own with Sass and build tools
Best Practices & Common Mistakes
Customization Pitfalls to Avoid
❌ Common Mistakes:
- Overriding with !important: Creates specificity wars
- Modifying core files: Updates become impossible
- Not testing updates: Customizations can break
- Ignoring accessibility: Color contrast, focus states
- Over-customizing: Loses Bootstrap's benefits
- No version control: Can't track or revert changes
- Forgetting responsive design: Break customizations on mobile
✅ Best Practices:
- Use Sass variables: For systematic changes
- Create custom files: Don't modify Bootstrap source
- Test across breakpoints: Ensure responsiveness
- Maintain accessibility: Check contrast, keyboard nav
- Document customizations: For team and future you
- Use version control: Track all custom changes
- Optimize selectively: Only include what you need
- Keep it maintainable: Simple, consistent customizations
Customization Checklist:
Customization Strategy Recommendations
- Start with Sass variables: For brand colors, typography, and spacing
- Use CSS variables for theming: Light/dark mode, user preferences
- Create custom component variants: Extend rather than override
- Optimize for production: Remove unused components, use PurgeCSS
- Test systematically: Each customization can have unintended effects
- Maintain upgrade path: Keep customizations separate from Bootstrap source
- Consider performance: More customizations = larger CSS = slower load times
- Balance uniqueness and consistency: Don't sacrifice usability for creativity
Quick Reference
$primary: #8a2be2;- Sass variable override--bs-primary: #8a2be2;- CSS variable override@import "bootstrap";- Import after variablesnpm run build- Compile Sassdata-bs-theme="dark"- Theme attributemap-merge()- Sass map merging