# Bootstrap 5 客製化
[Bootstrap Utility API 文檔](https://getbootstrap.com/docs/5.1/utilities/api/#css-variable-utilities)
## 基本配置
**1. 創建資料夾**
```
mkdir 1029
```
**2. 初始化項目**
```
npm init -y
```
**3. 安裝 Bootstrap**
```
npm i bootstrap
```
**4. 安裝延伸模組 ( Live Sass Compiler )**

**5. 新增一 SCSS 檔 ( custom.scss ),並引入 Bootstrap 必要程式碼**
```
// custom.scss
@import "../node_modules/bootstrap/scss/functions";
@import "../node_modules/bootstrap/scss/variables";
// Custom Variables Code
@import "../node_modules/bootstrap/scss/utilities";
// Custom Utilities Code
@import "../node_modules/bootstrap/scss/bootstrap.scss";
```
**6. 儲存後,點擊 Watch Sass 編譯出 CSS 檔 ( custom.css )**

**7. 新增一 HTML 檔 ( index.html ),並引入該 CSS 檔**
```
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./scss/custom.css">
</head>
<body>
...
</body>
</html>
```
## 通用
通用類別變數都加在我們的 `_utilities.scss` 樣式表的 $utilities 變數中。每組通用類別如下所示:
```
$utilities: (
"opacity": (
property: opacity,
values: (
0: 0,
25: .25,
50: .5,
75: .75,
100: 1,
)
)
);
```
輸出:
```
.opacity-0 { opacity: 0; }
.opacity-25 { opacity: .25; }
.opacity-50 { opacity: .5; }
.opacity-75 { opacity: .75; }
.opacity-100 { opacity: 1; }
```
## 變數
文檔中有提到應避免修該 Bootstrap 的核心文件,所以我認為不應該直接更改在`_variables.scss`樣式表中
* **撰寫位置**
```
@import "../node_modules/bootstrap/scss/functions";
@import "../node_modules/bootstrap/scss/variables";
// Custom Variables Code
$box-shadow-xl: 0 1rem 3rem rgba($black, .175);
@import "../node_modules/bootstrap/scss/utilities";
.
.
.
```
* **新增**
```
$theme-colors: (
"custom-color": #900
);
```
* **修改**
```
$theme-colors: (
"primary": #0074d9,
"danger": #ff4136
);
```
* **刪除**
```
$theme-colors: map-remove($theme-colors, "info", "light", "dark");
```
## 屬性
使用 **property** 屬性指定合法的 CSS 屬性,若 **class** 屬性被忽略,則做為 **class** 屬性的預設值,此屬性為**必須**
```
$utilities: (
"text-decoration": (
property: text-decoration,
values: none underline line-through
)
);
```
輸出:
```
.text-decoration-none { text-decoration: none !important; }
.text-decoration-underline { text-decoration: underline !important; }
.text-decoration-line-through { text-decoration: line-through !important; }
```
## 屬性值
使用 **values** 屬性指定特定 **property** 的名稱和規則,此屬性為**必須**
* 作為 **List**
```
values: none underline line-through
```
* 作為 **Map**
```
values: (
0: 0,
25: .25,
50: .5,
75: .75,
100: 1,
)
```
* 作為 **Sass Variables**
```
values: $position-values
```
## 前綴
使用 **class** 屬性更改已編譯 CSS 中所使用的 class 前綴,若 **class : null** 則沒有前綴
```
$utilities: (
"opacity": (
property: opacity,
class: o,
values: (
0: 0,
25: .25,
50: .5,
75: .75,
100: 1,
)
)
);
```
輸出:
```
.o-0 { opacity: 0; }
.o-25 { opacity: .25; }
.o-50 { opacity: .5; }
.o-75 { opacity: .75; }
.o-100 { opacity: 1; }
```
## 狀態
使用 **state** 屬性來生成偽類 ( 若需使用多個偽類則使用空格分隔 )
```
$utilities: (
"opacity": (
property: opacity,
class: opacity,
state: hover,
values: (
0: 0,
25: .25,
50: .5,
75: .75,
100: 1,
)
)
);
```
輸出 :
```
.opacity-0-hover:hover { opacity: 0; }
.opacity-25-hover:hover { opacity: .25; }
.opacity-50-hover:hover { opacity: .5; }
.opacity-75-hover:hover { opacity: .75; }
.opacity-100-hover:hover { opacity: 1; }
```
## 響應式
添加 **responsive** 屬性以生成橫跨所有斷點的響應式通用類別
```
$utilities: (
"opacity": (
property: opacity,
responsive: true,
values: (
0: 0,
25: .25,
50: .5,
75: .75,
100: 1,
)
)
);
```
輸出:
```
.opacity-0 { opacity: 0; }
.opacity-25 { opacity: .25; }
.opacity-50 { opacity: .5; }
.opacity-75 { opacity: .75; }
.opacity-100 { opacity: 1; }
@media (min-width: 576px) {
.opacity-sm-0 { opacity: 0; }
.opacity-sm-25 { opacity: .25; }
.opacity-sm-50 { opacity: .5; }
.opacity-sm-75 { opacity: .75; }
.opacity-sm-100 { opacity: 1; }
}
@media (min-width: 768px) {
.opacity-md-0 { opacity: 0; }
.opacity-md-25 { opacity: .25; }
.opacity-md-50 { opacity: .5; }
.opacity-md-75 { opacity: .75; }
.opacity-md-100 { opacity: 1; }
}
@media (min-width: 992px) {
.opacity-lg-0 { opacity: 0; }
.opacity-lg-25 { opacity: .25; }
.opacity-lg-50 { opacity: .5; }
.opacity-lg-75 { opacity: .75; }
.opacity-lg-100 { opacity: 1; }
}
@media (min-width: 1200px) {
.opacity-xl-0 { opacity: 0; }
.opacity-xl-25 { opacity: .25; }
.opacity-xl-50 { opacity: .5; }
.opacity-xl-75 { opacity: .75; }
.opacity-xl-100 { opacity: 1; }
}
@media (min-width: 1400px) {
.opacity-xxl-0 { opacity: 0; }
.opacity-xxl-25 { opacity: .25; }
.opacity-xxl-50 { opacity: .5; }
.opacity-xxl-75 { opacity: .75; }
.opacity-xxl-100 { opacity: 1; }
}
```
## CSS 變數
使用 **css-var** 屬性,會產生 CSS 變數 ( 應該是根據 class 值 ),用以代替 **property: value** 屬性
```
$utilities: (
"text-opacity": (
css-var: true,
class: text-opacity,
values: (
25: .25,
50: .5,
75: .75,
100: 1
)
),
);
```
## 覆蓋
使用 **相同 key** 覆蓋現有通用類別
```
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/utilities";
$utilities: (
"overflow": (
responsive: true,
property: overflow,
values: visible hidden scroll auto,
),
);
@import "../node_modules/bootstrap/scss/bootstrap.scss";
```
## 加入
可以透過 **map-merge** 將新的通用類別加入到預設的 $utilities map
```
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/utilities";
$utilities: map-merge(
$utilities,
(
"cursor": (
property: cursor,
class: cursor,
responsive: true,
values: auto pointer grab,
)
)
);
@import "../node_modules/bootstrap/scss/bootstrap.scss";
```
## 修改
使用 **map-get 和 map-merge 函式** 修改 $utilities map 中預設的通用類別
```
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/utilities";
$utilities: map-merge(
$utilities,
(
"width": map-merge(
map-get($utilities, "width"),
(
values: map-merge(
map-get(map-get($utilities, "width"), "values"),
(10: 10%, 20: 20%), //以此類推
),
),
),
)
);
@import "../node_modules/bootstrap/scss/bootstrap.scss";
```
## 開啟響應式
使用此 API 可以將目前關閉 responsive 屬性的通用類別啟動
```
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/utilities";
$utilities: map-merge(
$utilities, (
"border": map-merge(
map-get($utilities, "border"),
( responsive: true ),
),
)
);
@import "../node_modules/bootstrap/scss/bootstrap.scss";
```
## 重新命名
使用此 API 可以覆蓋該通用類別的 **class** 屬性
```
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/utilities";
$utilities: map-merge(
$utilities, (
"margin-start": map-merge(
map-get($utilities, "margin-start"),
( class: ml ),
),
)
);
@import "../node_modules/bootstrap/scss/bootstrap.scss";
```
## 刪除
透過 **將鍵值設置為 null** 以刪除任何通用類別
```
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/utilities";
$utilities: map-merge(
$utilities,
(
"width": null
)
);
@import "../node_modules/bootstrap/scss/bootstrap.scss";
```