Custom Boostrap :魔改Boostrap!客製化Boostrap

Wendy Chang
Wendy Loops
Published in
13 min readMar 28, 2023

公司說想要以BS為基底,製作屬於公司的design system,具有統一性、開發也比較快速,摸索了幾天終於搞清楚怎麼魔改BSㄌ,趕緊分享一波因為我會忘記^^

安裝Vue3跟其他套件

// 建立新專案 記得安裝scss
vue ui

// 安裝 bs & 支援bs的popper
npm i --save bootstrap @popperjs/core

// 安裝scss相關套件
npm i --save-dev autoprefixer css-loader postcss-loader sass sass-loader style-loader

因為bs的底層css是用scss寫的,所以要安裝可以解析scss的套件。

Scss跟Sass的差別?

新增custom.scss

官方建議不要修改bs原始的scss,以以下結構新增custom.scss

your-project/
├── scss
│ └── custom.scss // 新增custom.scss
└── node_modules/
└── bootstrap
├── js
└── scss

根據官方文件貼上以下要import的各種東西:

// Custom.scss
// Option B: Include parts of Bootstrap

// 1. Include functions first (so you can manipulate colors, SVGs, calc, etc)
@import "../node_modules/bootstrap/scss/functions";

// 2. Include any default variable overrides here

// 3. Include remainder of required Bootstrap stylesheets
@import "../node_modules/bootstrap/scss/variables";

// 4. Include any default map overrides here

// 5. Include remainder of required parts
@import "../node_modules/bootstrap/scss/maps";
@import "../node_modules/bootstrap/scss/mixins";
@import "../node_modules/bootstrap/scss/root";

// 6. Optionally include any other parts as needed
@import "../node_modules/bootstrap/scss/utilities";
@import "../node_modules/bootstrap/scss/reboot";
@import "../node_modules/bootstrap/scss/type";
@import "../node_modules/bootstrap/scss/images";
@import "../node_modules/bootstrap/scss/containers";
@import "../node_modules/bootstrap/scss/grid";
@import "../node_modules/bootstrap/scss/helpers";

// 7. Optionally include utilities API last to generate classes based on the Sass map in `_utilities.scss`
@import "../node_modules/bootstrap/scss/utilities/api";

// 8. Add additional custom code here

main.js引入,使之可以全局使用:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

// 引入bs
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap/dist/js/bootstrap.min.js'
import 'bootstrap'

// 引入 custom.scss
import '../scss/custom.scss'

createApp(App).use(router).mount('#app')

如果要套用dropdown那些JS動畫效果,要記得把popper跟bundle.js引入。

import '@popperjs/core'
import 'bootstrap/dist/js/bootstrap.bundle'

這樣就大致完成了!接著是魔改bs的部分。

自訂主色輔色

根據設計師給的色號將primary改成所要用的顏色,之後只要用xxx-primary xxx-secondary,就會自動套用上所需的顏色。

魔改前可以進到node_modules/boostrap/scss中觀摩一下bs是怎麼自動產生一大堆class還有如何設定大量的變數。

_variables.scss中,可以看到bs預設的主色是藍色:$primary: $blue !default;而藍色是這個色號:$blue: #0d6efd !default;

!default是說如果沒有特別設定的話,預設值就會是前面那個值。

我的作法是,因為公司的主色是藍色,所以我重新設定$blue,然後讓$primary: $blue,同理因為輔色是橘色,所以也用相同的寫法。官方建議把預設變數複寫在這個區段:

// custom.scss
// 2. Include any default variable overrides here

$blue: #347ab6;
$orange: #eb823d;

$primary: $blue;
$secondary: $orange;

之後只要class有primary或secondary都會自動套入我們設定的色號,同理其他什麼info啊、waring也可以這樣設定。
但有些element還是要細修,之後再來介紹。

色票自然產生

bs的顏色濃淺是程式算出來產生的,寫在_variables.scss中:

$blue-100: tint-color($blue, 80%) !default;
$blue-200: tint-color($blue, 60%) !default;
$blue-300: tint-color($blue, 40%) !default;
$blue-400: tint-color($blue, 20%) !default;
$blue-500: $blue !default;
$blue-600: shade-color($blue, 20%) !default;
$blue-700: shade-color($blue, 40%) !default;
$blue-800: shade-color($blue, 60%) !default;
$blue-900: shade-color($blue, 80%) !default;

但如果想應用$blue-100~$blue-900的話,bs預設是沒有設定可以直接使用的class,所以這裡我們要自己設定。
bs的class是用map-merge產生的,寫在_utilities.scss裡:

// _utilities.scss

$utilities: map-merge(
$utilities,
"color": (
property: color,
class: text,
local-vars: (
"text-opacity": 1
),
values: map-merge(
$utilities-text-colors,
(
"muted": $text-muted,
"black-50": rgba($black, .5), // deprecated
"white-50": rgba($white, .5), // deprecated
"reset": inherit,
)
)
),
)
);

根據官方文件,把以下code貼到custom.scss中就好了:

@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/utilities";

//貼的位置要注意

//把所有顏色引入
$all-colors: map-merge-multiple($blues, $indigos, $purples, $pinks, $reds, $oranges, $yellows, $greens, $teals, $cyans);

$utilities: map-merge(
$utilities,
(
"color": map-merge(
map-get($utilities, "color"),
(
values: map-merge(
map-get(map-get($utilities, "color"), "values"),
(
$all-colors
),
),
),
),
)
);

@import "bootstrap/scss/utilities/api";

同理background-color也是:

    "background-color":
map-merge(
map-get($utilities, "background-color"),
(
values:
map-merge(
map-get(map-get($utilities, "background-color"), "values"),
($all-colors)
),
)
),

如果要取用color: $blue-200這個色號,就只要設定text-blue-200這個class;background-color: $blue-200的話,就只要設定bg-blue-200,這樣就完成了,以後設定都很方便。

        <div class="bg-blue-100">$blue-100</div>
<div class="bg-blue-200">$blue-200</div>
<div class="bg-blue-300">$blue-300</div>
<div class="bg-blue-400">$blue-400</div>
<div class="bg-primary text-white">$blue-500</div>
<div class="bg-blue-600 text-white">$blue-600</div>
<div class="bg-blue-700 text-white">$blue-700</div>
<div class="bg-blue-800 text-white">$blue-800</div>
<div class="bg-blue-900 text-white">$blue-900</div>

魔改 Button

前面已經設定好主色輔色,但如果直接套用btn btn-primary的話,還是會跟預設的bs一樣:

<button type="button" class="btn btn-primary">Button Title</button>
還是boostrap藍QQ

@ mixin

定義好mixin後,可以用@ include來取用,bs的mixin寫在boostrap/scss/mixin中,先來看看button的mixin有三個:

// _button.scss

@mixin button-variant
@mixin button-outline-variant
@mixin button-size

看起來都設定好了,我們不用動它,接著去看boostrap/scss/_button.scss,看button是怎麼取用這些@mixin

// _button.scss

.btn{
// 設定btn 的大小外觀
}

// 自動產生btn-primary, btn-secondary那些顏色btn
@each $color, $value in $theme-colors{
// 沒事我們不要去動它
}

因為我只需要primary secondary還有灰階的顏色,所以我直接在把class name下在custom.scss中:

// custom.scss

.btn-primary {
@include button-variant($blue, $blue);
}
.btn-secondary {
@include button-variant(#6c757d, #6c757d);
}

mixin中,button-variant有很多變數,直接在()中丟入參數的話,會按照順序套用到mixin裡,所以第一個$blue會是 $background,第二個$blue會是$border;同理btn-secondary也是一樣的。

因為設計師要的橘色按鈕設計稿希望border顏色跟bgc不一樣,所以@include就會寫成這樣:

.btn-warning {
@include button-variant(
$orange-500, // $backgorund
$orange-700, // $border
white, // $color

// 沒有按照順序的要加入變數再設定
$hover-color: white,
$disabled-color: white,
$active-color: white
);
}

outline風格的button也是這樣做,可以玩玩看!

其他element就看design system需要哪些,再去做客製化,流程都跟魔改button差不多~
其實只要大概了解bs產生class的流程,就可以做到大部分的客製化,除非design system跟bs差很多,不然我覺得了解到這樣就好了~

--

--

Wendy Chang
Wendy Loops

什麼都寫ㄉ前端工程師 / 影片剪輯師 / 自媒體經營者