[基礎課程] Bootstrap5 教學(二):工具、通用、表單


本章節先跳至較為基礎操作的 Utilities 通用類型(各種局部調整或快建立公式),再介紹 Helpers 工具(主要為一些常使用的輔助調整),以及,最後回到 Forms 表單(完整的表單互動系統)進行說明。


通用 Utilities

屬於通用性質且十分常見的一些外觀零件公式,算是整個 Bootstrap 你最常用到且需要去記住的公式表,這些通用類別會幫助你進行設計 Bootstrap 時輕鬆快速的套弄出視覺效果。

API

本節主要闡述如何使用官方原始 SASS 編譯檔之自定義類別調整各值之教學,將不做介紹。

背景色 Background

可對背景進行指定色使用 .bg-{color} 完成,同時若需要漸層效果額外添加 .bg-gradient

.bg-{color} /*背景色*/
color: primary, secondary, success, danger, warning, info, light, dark, white, transparent;

.bg-gradient /*套上漸層色,原理採用疊上透明垂直漸層之 image*/

如果如果你有自己的背景 CSS,也可嘗試添加 .bg-gradient 套上漸層效果

邊框 borders

使用 .border 能對一個 box 進行添加邊框線,效果為 border:1px solid #dee2e6 。也能控制方向呈現部分邊框。

.border  /* 四邊產生 1px 的灰色邊框線 */
.border-{direction} /* 只有該處有邊框線 */
direction: top, end, bottom, start

反之.border-0border: 0!important;之無邊框效果。

.border-0  /* 邊框線為無 */
.border-{direction}-0 /* 只有該處邊框線為無 */
direction: top, end, bottom, start

若是調整顏色可以使用 .border-{color} 。這只是調整顏色,該元素還是需要 .border 先負責產生邊框線。

.border-{color}  /* 指定邊框顏色 */
color: primary, secondary, success, danger, warning, info, light, dark, white

控制邊框粗度為 border-* 其等級為 1 ~ 5,級距差為 1px。

.border-{number}  /* 指定邊框粗度 */
number: 1, 2, 3, 4, 5

圓角化的處理使用 .rounded ,能對邊框線產生 border-radius: .25rem 效果,也能指定部分區域原角,或是成特定形狀。

.rounded  /* 圓角化效果為 0.25rem */

.rounded-{direction} /* 部分圓角化 */
direction: top, end, bottom, start

.rounded-circle /* 圓形 */
.rounded-pill /* 橢圓形 */

.rounded-{number} /*原角尺寸*/
number: 0(無圓角), 1, 2, 3

顏色 colors

算是十分重要且實用的公式,官方還把顏色取了名字(請習慣他)。大多數跟顏色有關的參數都逃脫不了這些顏色名稱。另外提醒應對於亮色字配高對比的暗背色,反之亦然。同時這些顏色會對應 :hover:focus 有對應色變。

.text-{color} /*文字色 */
color: primary, secondary, success, danger, warning, info, light, dark, body, muted, white;

.text-{black|white}-50 /*對黑與白多設計一種透明度為 0.5 的黑白字效果*/

顯示 display

前一章節已提早完整介紹過,本處不再說明。

彈性盒 flex

前一章節已提早完整介紹過,本處不再說明。

浮動 float

與 CSS 觀念相同,同樣具有響應式使用。

/* float */
.float-{value} /* 設定 float */
.float-{breakpoint}-{value} /* 響應式 float */

value: start, end, none
breakpoint: sm, md, lg, xl, xxl

互動 Interactions

HTML 部分元素提供可互動的事件(包含 select 選取與 click 點擊)反應。

  • 原理透過 CSS3 屬性 user-select 能指定該文字段落能否被反白選取 (網頁初始值 user-select:auto)
  • 原理透過 CSS3 屬性 pointer-events 能指定滑鼠事件的響應(網頁初始值 pointer-events: auto)
/* user-select */
.user-select-{value}
value: all, auto, none)

/* Pointer Events */
.pe-{value}
value: none, auto
https://getbootstrap.com/docs/5.0/utilities/interactions/
<div class="container">
<h1>User Select on Text</h1>
<p class="user-select-all">Can select and be all range</p>
<p class="user-select-auto">Default behavior</p>
<p class="user-select-none">Can't selected</p>

<h1>Pointer Event on Mouse</h1>
<p><a href="#" class="pe-none">Can't clicked</a></p>
<p><a href="#" class="pe-auto">Default behavior</a></p>

<h1>Pointer Event 繼承與優先</h1>
<div class="pe-none">
<a href="#"> a 繼承 pe-none</a> <br>
<a href="#" class="pe-auto"> a.pe-auto </a>
</div>
</div>

Pointer Event 如不想被點選,你應該添加例如 a[tabindex="-1" aria-disabled="true"],確保鍵盤或視障軟體受到禁用。

溢出處理 overflow

與 CSS 觀念相同,只提供四種常用模式。

/* overflow */
.overflow-{value} /* 設定 overflow */
value: auto, hidden, visible(網頁初始值), scroll

位置 position

與 CSS 觀念相同,提供五種常用模式。

/* position */
.position-{value} /* 設定 position */
value: static, relative, absolute, fixed, sticky

除此之外還提供定位參數使用,並可搭配 translate 完成偏移 -50%。

.{direction}-{number}
direction: top, bottom, start, end
number: 0, 50, 100 (單位%)

.translate-middle /* 效果為 transform:translate(-50%,-50%) */
.translate-middle-x /* 效果為 transform:translateX(-50%) */
.translate-middle-y /* 效果為 transform:translateY(-50%) */
https://getbootstrap.com/docs/5.0/utilities/position/#examples
<div class="container d-flex vh-100 justify-content-evenly align-items-center">
<button type="button" class="btn btn-primary position-relative">
Mails <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-secondary">+99 <span
class="visually-hidden">unread messages</span></span>
</button>

<button type="button" class="btn btn-dark position-relative">
Marker
<svg width="1em" height="1em" viewBox="0 0 16 16"
class="position-absolute top-100 start-50 translate-middle mt-1 bi bi-caret-down-fill" fill="#212529"
xmlns="http://www.w3.org/2000/svg">
<path d="M7.247 11.14L2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z" />
</svg>
</button>

<button type="button" class="btn btn-primary position-relative">
Alerts <span
class="position-absolute top-0 start-100 translate-middle badge border border-light rounded-circle bg-danger p-2"><span
class="visually-hidden">unread messages</span></span>
</button>
</div>

陰影 Shadow

提供元素產生陰影效果應用,此效果可能對一些元件無效 (Bootstrap 禁止了部分),除非到 scss/_variables.scss 檔案位置調整 $enable-shadows 為 true。

.shadow-none /*無陰影*/
.shadow-sm /*小陰影*/
.shadow /*陰影*/
.shadow-lg /*大陰影*/

尺寸 sizing

版面上事後調整元素尺寸是常見的事,這裡提供設定寬高的固定公式。

/* by percent */
.w-{value} /* 指定該寬度為多少百分比 */
.h-{value} /* 指定該高度為多少百分比(前提為負容器有固定高) */
value: 25, 50, 75, 100, auto
.mw-100 /* max-width:100% */
.mh-100 /* max-height:100% */

/* by viewport */
.vw-100 /* width:100vw */
.vh-100 /* height:100vw */
.min-vw-100 /* min-width:100vw */
.min-vh-100 /* min-height:100vw */

間距 spacing

前一章節已提早完整介紹過,本處不再說明。

文字 text

文字對齊的方式稍早有提到,這裡再完整複習一下:

.text-{value} /* text-align */
.text-{breakpoint}-{value} /* 響應式 text-align */

value: start, end, center
breakpoint: sm, md, lg, xl, xxl

自第五版開始以移除。text-justify 效果 (text-align:justify 主要是英文字適當填滿空間)。

文字換行或斷行處理,前提是要先發生 overflow 溢出現象:

.text-wrap /* 臨界至寬度時,文字自動換行 */
.text-nowrap /* 臨界至寬度時,文字不換行讓他溢出 */

.text-break /* 當英文單字之字母過長時,必要時允許斷行 */

文字大小寫:

.text-lowercase /* 英文全轉小寫 */
.text-uppercase /* 英文全轉大寫 */
.text-capitalize /* 僅判讀英文各單字第一字母轉大寫 */

文字尺寸,同等 h1~h6 尺寸只是沒有粗體與行高:

.fs-{number}  /* font-size: 2.5rem ~ 1rem */

number: 1, 2, 3, 4, 5, 6

文字粗斜體效果:

.fw-{value} /* 粗體 */
value: bold, bolder, normal, light, lighter

.fst-{value} /*斜體*/
value: italic, normal

行高效果,控制段落元素之行間高度。

.lh-1     /* line-height:1 */
.lh-sm /* line-height:1.25 */
.lh-base /* line-height:1.5 */
.lh-lg /* line-height:2 */

其他效果

.text-monospace /* 套用 monospace 字型,通常適合程式代碼使用 */
.text-reset /* 清除自己文字屬性,方便由父元素繼承 */

.text-decoration-{value} /* 裝飾線之底線、刪除線、無裝飾線 */
value: underline, line-through, none

垂齊對齊 Vertical align

這裡的文字垂直對齊只對字行有效,是指 inline(非 block),像是 inline, inline-block, inline-table, table>td 等標籤類型。通常用在 table 的儲存格之文字十分顯卓。

.align-{value} /*垂直對齊位置*/
value: baseline, top, middle, bottom, text-top, text-bottom

可視性 visibility

前一章節已提早完整介紹過,本處不再說明。

工具 Helpers

工具大多為在設計網頁時常用的調整技巧所集結收入,透過工具來進行局部相關調整代碼效果使用。

清除浮動 clearfix

Bootstrap 設計出一種使用限制,必需對父元素使用 .clearfix 來包住任何 float 對象,能讓子元素的任何 float 不會影響父元素之後的 HTML 元素。原理為:

透過偽元素進行clear:both行為使得這個區域結尾時會消除所有浮動現象。同時 after 本身有 block 會撐回原元素的空間。

bootstrap.css(官方樣式)
.clearfix::after {
display: block;
clear: both;
content: "";
}

使用範例:

<div class="bg-info clearfix">
<div class="float-left bg-danger">Example Button floated left</div>
<div class="float-right bg-danger">Example Button floated right</div>
</div>

只要記得使用任何浮動之前,創造父元素來宣告 clearfix,如此一來父容器以外不會有浮動現象,同時父容器內部也不會有錯覺現象。

舉凡超連結 a 元素皆可指定顏色並帶 hover 差異色。

.link-{color}
color: primary, secondary, success, danger, warning, info, light, dark

比例 Ratio

原本為舊版 embed 通用,現在主要能對任何媒體類型 (iframe, embed, video, object, div, img) 進行比例控制,根據寬度值來推算出高度限定為何。重點如下:

  • 你需要一個父容器設定 div.ratio 才能觸發。
  • 同父容器上需指定比例值 ratio-*,共計 4 種選擇提供。注意此容器仍需要 .ratio 不可缺。
  • 若需自訂比例可透過 style 屬性綁定 [style=--aspect-ratio:*] , 單位為 % 百分比
/* embed responsive*/
.ratio /* 綁定父容器進行比例觸發 */
.ratio-{value} /*設定比例*/
value: 21x9, 16x9, 4x3, 1x1

[style=--aspect-ratio:{custom_value}%] /* 指定自訂比例,單位為數字百分比

外觀優化已包含了除邊線 (frameborder=”0”) 與響應調整寬度(換言之你不用手動固定 embed 的寬了,但高度仍需設定)。

<style>
div>div {
background: #ccc;
}
</style>

<div class="container">
<h1>ratio 預設為寬 100 若不固定尺寸會填滿空間</h1>
<div class="ratio ratio-16x9">
<iframe src="https://www.youtube.com/embed/zpOULjyy-n8?rel=0" title="YouTube video" allowfullscreen></iframe>
</div>
<div class="d-inline-block w-25 ratio ratio-1x1">
<div>1x1</div>
</div>
<div class="d-inline-block w-25 ratio ratio-4x3">
<div>4x3</div>
</div>
<div class="d-inline-block w-25 ratio ratio-16x9">
<div>16x9</div>
</div>
<div class="d-inline-block w-25 ratio ratio-21x9">
<div>21x9</div>
</div>
<div class="d-inline-block w-25 ratio" style="--aspect-ratio:33.3%">
<div>custom 33.3% = 3x1</div>
</div>
</div>

響應式雖然沒有提供,若有需要可自行編寫。例如:當 md 模式時 (768px up) 會變成 2x1

@media (min-width: 768px){
.ratio-4x3 {
--aspect-ratio: 50%;
}
}

常用定位 Position

與通用類別的 position 不同,這裡做為工具單元則提供些常用的固定方式,像是永遠保持上面、下面、撞到頂端則保持上面,這些都是網站常見到的一些手法。

.fixed-top /*保持上面*/
.fixed-bottom /*保持下面*/
.sticky-top /*撞到頂端則保持上面*/

/*僅針對 sticky-top 提供響應斷點*/
.sticky-{breakpoint}
breakpoint: sm, md, lg, xl

視覺隱藏 visually-hidden

與 css 屬性 visibility 不同,這裡是直接將元素縮到極小尺寸使畫面看不見,卻可讓視障閱讀程式能讀取到。

.visually-hidden /*隱藏於畫面上*/
.visually-hidden-focusable /*隱藏於畫面上,唯獨 focus 狀態(鍵盤選取)時才呈現*/

如某個連結範圍想擴大到外部容器去,可以對此連結添加 .stretched-link ,此連結會產生一個偽元素:after 會以 position:absolute 方式塞滿整個空間(上層沒有定位的話),因此 需要在父元素 上綁定一個position:relative 使得影響範圍限定在這個父元素內。

範例為:

<div class="w-50 position-relative bg-dark text-white">
<div>
<h5 class="mt-0">延伸連結區域之範例</h5>
<p>整個黑色是由一個上層元素綁定 position-relative,使得作用僅限於上層元素(黑色區域),上層範圍可以很祖先。</p>
<a href="#" class="stretched-link">我是連結反應</a>
</div>
</div>

containing block:
absolute 當進行向上尋找 relative 參考定位時,遇到非指定元素持有以下屬性則會導致參考至此發生預期之外的定位。

  • 持有非 position:static 屬性
  • 持有 transform 或 perspective 屬性
  • 持有 filter 屬性 (Firefox)

文字截斷 Text truncation

當有限的寬度下發生溢位現象時,可賦予 .text-truncate ,將提供以下屬性使其產生 … 之替代,注意唯獨對非 block 模式無效。

.text-truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
https://getbootstrap.com/docs/5.0/helpers/text-truncation/
<!-- Block level -->
<div class="row">
<div class="col-2 text-truncate">
Praeterea iter est quasdam res quas ex communi.
</div>
</div>

<!-- Inline level -->
<span class="d-inline-block text-truncate" style="max-width: 150px;">
Praeterea iter est quasdam res quas ex communi.
</span>

表單 Forms

表單為 Bootstrap 最大的特色 UI,雖然元素與 Class 複雜度高,初學者可以先透過範例複製貼上所用即可。

為了簡化代碼,本篇將參考官方手冊做以下事情:

  1. 替換 id 名稱或目標名為 lokiXXX,更容易理解此處可自訂名稱。
  2. 移除 aria-* 系列 標籤屬性(為視障軟體或機器判讀所用)減少代碼量,但仍建議工作上保留此屬性。
  3. 移除不重要的 id,避免誤會 id 必要性。

接下來會介紹各種表單元素的基本公式,以及某些需求場合下你應該試著用 div 父元素來包住 input 與 label 元素成為一個元素群組之呈現排版。元素群組模式除了基本的 div,最後還會提供 div.input-groupdiv.form-floating 兩種表單群組的排版技巧。

概觀 Overview

form 的公式雖然複雜且多樣化,然而公式不一定要跟著套用,這跟外觀是否好看所決定。

https://getbootstrap.com/docs/5.0/forms/overview/#overview
<form class="container">
<div class="mb-3">
<label class="form-label" for="lokiMail">Email address</label>
<input class="form-control" id="lokiMail" type="email">
<div class="form-text">We'll never share your email with anyone else.</div>
</div>
<div class="mb-3">
<label class="form-label" for="lokiPassword">Password</label>
<input class="form-control" type="password" id="lokiPassword">
</div>
<div class="mb-3 form-check">
<input class="form-check-input" id="lokiCheck" type="checkbox">
<label class="form-check-label" for="lokiCheck">Check me out</label>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>

input 欄位組合建議為 label.form-label + input.form-control + div.form-text 分別代表標題、欄位、描述文字。

  • label.form-label 為提供 margin-bottom 間隔
  • input.form-control 為 blcok 滿寬與外觀優化
  • div.form-text 為提供 margin-top 間隔與文字調整,非必要可省略此元素。可套用 block 或 inline 類型。

check|radio 欄位組合建議 div.form-check > input:checkbox.form-check-input + label.form-check-label 分別代表欄位與內文。

  • div.form-check 為父元素使用與適當排版
  • input:checkbox.form-check-input 提供耐看的打勾視窗
  • label.form-check-label 提供內文使用,但沒有任何屬性效果(可省略 class)

禁用 Disabled

如果要大片禁用,可以添加容器並指定屬性為 fieldset[disabled] (fieldset 算是表單中的語意標籤,代表相關資訊的組合)。

<form>
<fieldset disabled>
<legend>Disabled fieldset example</legend>
<div class="mb-3">
<label for="lokiInput" class="form-label">Disabled input</label>
<input type="text" id="lokiInput" class="form-control" placeholder="Disabled input">
</div>
<div class="mb-3">
<label for="lokiSelect" class="form-label">Disabled select menu</label>
<select id="lokiSelect" class="form-select">
<option>Disabled select</option>
</select>
</div>
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="lokiCheck" disabled>
<label class="form-check-label" for="lokiCheck">Can't check this</label>
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</fieldset>
</form>

親和性 Accessibility

這裡是指網頁友善化,將網頁結構能被輔助技術給解析回報給客戶。盡可能的以 HTML5 語意標籤來完成,包含 label 與 button 這類具備定義的元素標籤作為 描述字

  • 有些情況下 label 元素保留語意卻不想呈現時,可使用 .visually-hidden 隱藏。
  • 無法提供 label 元素作為描述自,自身可透過屬性 aria-label 來補述語意。
  • 同上,或者可用屬性 title 來補述語意。
  • 屬性 aria-labelledby 能協助根據哪個元素提供為 label 之用。
  • 沒有 label 或以上補述方法時,那些輔助技術可能會透過元素的 placeholder 屬性來理解描述字為何

Input & Textarea (Form controls)

能控制 input 或 textarea 的外觀變化,你必須先綁定 .form-control 才能開始操作。

尺寸控制方式,有以下三種變化控制欄位高度:

https://getbootstrap.com/docs/5.0/forms/form-control/#sizing
<input type="text" class="form-control form-control-lg" placeholder=".form-control-lg">
<input type="text" class="form-control" placeholder="Default input">
<input type="text" class="form-control form-control-sm" placeholder=".form-control-sm">

禁用欄位效果,添加屬性 disabled 即可:

https://getbootstrap.com/docs/5.0/forms/form-control/#disabled
<input class="form-control" type="text" placeholder="Disabled input" disabled>
<input class="form-control" type="text" placeholder="Disabled readonly input" disabled readonly>

僅供閱讀(可互動不可輸入),添加 readonly 即可。若不想暗化可將 form-control 更改為 .form-control-plaintext

https://getbootstrap.com/docs/5.0/forms/form-control/#readonly
<input class="form-control" type="text" placeholder="Readonly input here..." readonly>
<input class="form-control-plaintext" type="text" placeholder="Readonly input here..." readonly>

檔案(單一或多筆)上傳的呈現效果與前面相同,包含三種尺寸與禁用效果:

<div class="mb-3">
<label for="lokiSingleFile" class="form-label">Default file input example</label>
<input class="form-control" type="file" id="lokiSingleFile">
</div>
<div class="mb-3">
<label for="lokiMultiFile" class="form-label">Multiple files input example</label>
<input class="form-control" type="file" id="lokiMultiFile" multiple>
</div>
<div class="mb-3">
<label for="lokiDisabled" class="form-label">Disabled file input example</label>
<input class="form-control" type="file" id="lokiDisabled" disabled>
</div>
<div class="mb-3">
<label for="lokiSizeSM" class="form-label">Small file input example</label>
<input class="form-control form-control-sm" id="lokiSizeSM" type="file">
</div>
<div>
<label for="lokiSizeLG" class="form-label">Large file input example</label>
<input class="form-control form-control-lg" id="lokiSizeLG" type="file">
</div>

若 input 為 color 類型,請添加.form-control-color 重定寬值:

<label for="lokiColor" class="form-label">Color picker</label>
<input type="color" class="form-control form-control-color" id="lokiColor" value="#563d7c">

HTML5 的新標籤 datalist 資料清單,提供 input 作建議參考,結構為 input[list=ID]+datalist#ID>option*n

<label for="lokiDataList" class="form-label">Datalist example</label>
<input class="form-control" list="lokiOptions" id="lokiDataList" placeholder="Type to search...">
<datalist id="lokiOptions">
<option value="San Francisco">
<option value="New York">
<option value="Seattle">
<option value="Los Angeles">
<option value="Chicago">
</datalist>

Select

控制 select 的外觀變化,你必須先綁定 .form-select 才能開始操作。

對尺寸控制方式,有以下三種變化控制欄位高度:

<select class="form-select mb-3">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>

<select class="form-select form-select-lg mb-3">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>

<select class="form-select form-select-sm">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>

multiple, size, disabled 三種 select 外觀:

<select class="form-select mb3" multiple>
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>

<select class="form-select mb3" size="3">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>

<select class="form-select" disabled>
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>

select 能指定屬性 multiple (4 筆)或 size=N

Checkbox & Radio

Bootstrap 對於勾選類的表單 input 有重新設計外觀與互動變化。checkbox 使用技巧為:

  • 使用 div.form-check 父元素包覆 input 與 label 為組合
  • label 使用 label.form-check-label
  • 勾選類 input(checkbox | radio) 使用 input.form-check-input

對於 checked, Indeterminate(需由 JS 觸發), disabled 型態外觀如下:

<div class="container">
<h1 class="border-bottom my-5">CheckBox Demo</h1>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="lokiCheckbox">
<label class="form-check-label" for="lokiCheckbox">Default checkbox</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="lokiChecked" checked>
<label class="form-check-label" for="lokiChecked">Checked checkbox</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="lokiIndeterminate">
<label class="form-check-label" for="lokiIndeterminate">Indeterminate checkbox</label>
<script>
document.getElementById("lokiIndeterminate").indeterminate = true;
</script>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="lokiDisabled" disabled>
<label class="form-check-label" for="lokiDisabled">Disabled checkbox</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="lokiCheckedDisabled" checked disabled>
<label class="form-check-label" for="lokiCheckedDisabled">Disabled checked checkbox</label>
</div>

<h1 class="border-bottom my-5">Radio Demo</h1>
<div class="form-check">
<input class="form-check-input" type="radio" name="lokiDemo" id="lokiValue1">
<label class="form-check-label" for="lokiValue1">Default radio</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="lokiDemo" id="lokiValue2" checked>
<label class="form-check-label" for="lokiValue2">Default checked radio</label>
</div>

<div class="form-check">
<input class="form-check-input" type="radio" name="lokiDemoDis" id="lokiValue3" disabled>
<label class="form-check-label" for="lokiValue3">Disabled radio</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="lokiDemoDis" id="lokiValue4" checked disabled>
<label class="form-check-label" for="lokiValue4">Disabled checked radio</label>
</div>
</div>

開關效果 Switches

checkbox 的另一種外觀表現,同樣的公式結構下對父元素額外再添加 .form-switch 產生視覺效果。

<div class="container">
<h1 class="border-bottom my-5">Switches feat.CheckBox Demo</h1>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="lokiSwitch1">
<label class="form-check-label" for="lokiSwitch1">Default switch checkbox input</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="lokiSwitch2" checked>
<label class="form-check-label" for="lokiSwitch2">Checked switch checkbox input</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="lokiSwitch3" disabled>
<label class="form-check-label" for="lokiSwitch3">Disabled switch checkbox input</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="lokiSwitch4" checked disabled>
<label class="form-check-label" for="lokiSwitch4">Disabled checked switch checkbox input</label>
</div>
</div>

行內排列 Inline

前面例子的排列效果皆以 block 排列方式堆疊,若在設計上有 linline 行內排列需求。請試著對父元素添加 .form-check-inline 將會提供 inline-block 屬性並 Margin-right 空間。

<div class="container">
<h1 class="border-bottom my-5">CheckBox Inline Demo</h1>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="lokiInlineCheck1" value="option1">
<label class="form-check-label" for="lokiInlineCheck1">1</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="lokiInlineCheck2" value="option2" checked>
<label class="form-check-label" for="lokiInlineCheck2">2</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="lokiInlineCheck3" value="option3" disabled>
<label class="form-check-label" for="lokiInlineCheck3">3 (disabled)</label>
</div>

<h1 class="border-bottom my-5">Radio Inline Demo</h1>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="lokiRadio" id="lokiInlineRadio1" value="option1">
<label class="form-check-label" for="lokiInlineRadio1">1</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="lokiRadio" id="lokiInlineRadio2" value="option2" checked>
<label class="form-check-label" for="lokiInlineRadio2">2</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="lokiRadio" id="lokiInlineRadio3" value="option3" disabled>
<label class="form-check-label" for="lokiInlineRadio3">3 (disabled)</label>
</div>
</div>

無描述字時 Without labels

沒有 label 情況下也可直接使用 input.form-check-input ,且父元素也能移除(但將變回 inline 元素)。但對於語意來說失去 label 時應該透過親和屬性 [aria-label=] 來補足 label 語意。

整合按鈕 Toggle Buttons

此外觀效果為引用 Button 元件(下章節才會介紹) 功能,進行另一種 checkbox 與 raido 視覺變化,相對原本公式結構完全不同做法:

  • 不需要父容器來包覆 label 與 input,直接兩者寫出即可
  • 對勾選型 input 添加公式成為 input.btn-check ,使其效果將會隱藏於畫面上無法操作。
  • 對 label 添加公式成為 label.btn,使其外觀為按鈕模式。
  • 持有 label.btn 可添加色系,選擇 btn-{color}btn-ouline-{color} 兩種色彩模式。
  • 透過 label 的 for 屬性來連動 input 的 checked 狀態變化。
  • label 的啟用色變化來自 input 的 checked 狀態。
  • 建議 input 添加屬性 [autocomplete=”off”] 避免瀏覽器自動填入造成誤會。
<div class="container">
<h1 class="border-bottom my-5">CheckBox feat.Buttons</h1>
<input type="checkbox" class="btn-check" id="lokiBtn1">
<label class="btn btn-danger" for="lokiBtn1">Single toggle</label>

<input type="checkbox" class="btn-check" id="lokiBtn2" checked>
<label class="btn btn-danger" for="lokiBtn2">Checked</label>

<input type="checkbox" class="btn-check" id="lokiBtn3" disabled>
<label class="btn btn-danger" for="lokiBtn3">Disabled</label>

<h1 class="border-bottom my-5">Radio feat.Buttons</h1>
<input type="radio" class="btn-check" name="myRadio" id="lokiValue1" checked>
<label class="btn btn-success" for="lokiValue1">Checked</label>

<input type="radio" class="btn-check" name="myRadio" id="lokiValue2">
<label class="btn btn-success" for="lokiValue2">Radio</label>

<input type="radio" class="btn-check" name="myRadio" id="lokiValue3">
<label class="btn btn-success" for="lokiValue3">Disabled</label>

<input type="radio" class="btn-check" name="myRadio" id="lokiValue4" disabled>
<label class="btn btn-success" for="lokiValue4">Radio</label>
</div>

Range

範圍型的表單 input 在套用 Bootstrap 公式 input.form-range 後為 block 滿寬效果,以及大幅度的視覺設計。

<div class="container">
<h1 class="border-bottom my-5">Range DEMO</h1>
<label class="form-label" for="lokiRange1">Example range | <b>Value:50</b></label>
<input class="form-range" id="lokiRange1" type="range">

<label class="form-label" for="lokiRange2">Disabled range | <b>Value:50</b></label>
<input class="form-range" id="lokiRange2" disabled type="range">

<label class="form-label" for="lokiRange3">Example range | <b>Value:3</b></label>
<input class="form-range" min="0" max="5" id="lokiRange3" type="range">

<label class="form-label" for="lokiRange4">Example range | <b>Value:2.5</b></label>
<input class="form-range" id="lokiRange4" min="0" max="5" step="0.5" type="range">
</div>

<script>
document.querySelectorAll("input").forEach(e => {
e.oninput = () => e.previousElementSibling.children[0].textContent = "Value:" + e.value;
});
</script>

range 能指定屬性 min=N, max=M, step=R

欄位群組 Input group

input-group 唯一種群組排版效果,需將 label 與 input 整合成同一個欄位並群組化,群組內能任意整合 input 或 一般補述文字(非 label) ,觀念為:

  • 透過父元素 div.input-group 進行包覆 (flex 設計),主要是改良 input 的外觀為主,因此可放入多個 input 或一般文字(通常為 span) 做補述。
  • label 元素不會放入 div.input-group 內,該 input-group 主要是改變 input 結構而不是整體 label+input 之排版。
  • 子元素之一般文字元素透過 span.input-group-text 來形成該 input 之補述。
  • 位置順序根據子元素排列順序決定。
  • 根據親和性設計,無 label 情況下 input 元素可追加 aria-label=描述 屬性表達該欄位之描述。
  • 根據親何性設計,input 元素可追加 aria-describedby="ID" 屬性使該欄位之補述文字為何處 ID。
<div class="container">
<div class="input-group mb-3">
<span class="input-group-text" id="lokiMessage1">@</span>
<input class="form-control" aria-describedby="lokiMessage1" aria-label="lokiTitle1" type="text">
</div>

<div class="input-group mb-3">
<input class="form-control" aria-describedby="lokiMessage2" aria-label="lokiTitle2" type="text">
<span class="input-group-text" id="lokiMessage2">@example.com</span>
</div>

<label class="form-label" for="lokiInput">Your vanity URL</label>
<div class="input-group mb-3">
<span class="input-group-text" id="lokiMessage3">https://example.com/users/</span>
<input class="form-control" aria-describedby="lokiMessage3" id="lokiInput" type="text">
</div>

<div class="input-group mb-3">
<span class="input-group-text">$</span>
<input class="form-control" aria-label="lokiTitle3" type="text">
<span class="input-group-text">.00</span>
</div>

<div class="input-group mb-3">
<input class="form-control" aria-label="lokiTitle4" type="text">
<span class="input-group-text">@</span>
<input class="form-control" aria-label="lokiTitle5" type="text">
</div>

<div class="input-group">
<span class="input-group-text">With textarea</span>
<textarea class="form-control" aria-label="lokiTitle6"></textarea>
</div>
</div>

自動換行 Wrapping

預設情況下 input-group 的 flex 參數被 Bootstrap 修改為允許發生換行。若您不想要這樣做,可自行透過 flex 通用類別改回 .flex-nowrap

<div class="container">
<h1>Please RWD this Page</h1>
<label class="form-label" for="lokiInput1">Try Wrap (Default)</label>
<div class="input-group mb-3">
<span class="input-group-text">https://example.com/users/</span>
<input class="form-control" type="text">
<span class="input-group-text">https://example.com/users/</span>
</div>

<label class="form-label" for="lokiInput2">Try No-Wrap</label>
<div class="input-group flex-nowrap">
<span class="input-group-text">https://example.com/users/</span>
<input class="form-control" type="text">
<span class="input-group-text">https://example.com/users/</span>
</div>
</div>

尺寸 Sizes

能對整體 input-group 調整欄位高度。此參數需額外添加

.input-group.input-group-sm   /*small*/
.input-group /*default*/
.input-group.input-group-lg /*large*/

選填表單 Checkboxes and radios

也可以不使用 span 補述文字,改用 checkbox 或 radio 來追加輸入欄位使用。將原 span.input-group-text 元素轉為 div.input-group-text>input:{checkbox|radio}.form-check-input

<div class="container">
<h1>Checkbox feat.prepend</h1>
<div class="input-group mb-3">
<div class="input-group-text">
<input class="form-check-input" aria-label="lokiLabelA1" type="checkbox">
</div>
<input class="form-control" aria-label="lokiLabelA2" type="text">
</div>

<h1>Radio feat.prepend</h1>
<div class="input-group">
<div class="input-group-text">
<input class="form-check-input" aria-label="lokiLabelB1" type="radio">
</div>
<input class="form-control" aria-label="lokiLabelB2" type="text">
</div>
</div>

多項 inputs 與 addons

如前面所述,在 input-group 內支援多項目的 input.form-control.input-group-text 隨使用者自訂排序。

<div class="container">
<h1>Multi input and addons</h1>
<div class="input-group mb-3">
<span class="input-group-text">$</span>
<span class="input-group-text">0.00</span>
<input type="text" class="form-control">
<span class="input-group-text">$</span>
<span class="input-group-text">0.00</span>
</div>
</div>

注意的是驗證功能時(後續介紹)若想對 input 進行動態驗證時,只能支援單筆 input 的 input-group,所以不建議這樣用多項 input。

整合元件 button & dropdowns

部分元件元素也能放置在 input-group 內一同排列,像是按鈕、下拉選單、分段按鈕等元素組合(這些相關元件於下個章節介紹)。

<div class="container">
<h1>Button addons</h1>
<div class="input-group mb-3">
<button class="btn btn-outline-secondary" type="button" id="button-addon1">Button</button>
<input type="text" class="form-control">
</div>

<h1>dropdown addons</h1>
<div class="input-group mb-3">
<input type="text" class="form-control">
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">Dropdown</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Separated link</a></li>
</ul>
</div>

<h1>Segmented buttons</h1>
<div class="input-group mb-3">
<button type="button" class="btn btn-outline-secondary">Action</button>
<button type="button" class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown">Toggle Dropdown</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Separated link</a></li>
</ul>
<input type="text" class="form-control">
</div>
</div>

整合自訂版本的 select 與 input:file

可整合 select.form-select 元素或 input:file.form-control 元素使用。

<div class="container">
<h1>Select addons</h1>

<div class="input-group mb-3">
<select class="form-select" id="lokiSelect1">
<option selected>Choose...</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<label class="input-group-text" for="lokiSelect1">Options</label>
</div>

<div class="input-group mb-3">
<button class="btn btn-outline-secondary" type="button">Button</button>
<select class="form-select" aria-label="lokiLabel1">
<option selected>Choose...</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
</div>

<h1>Input:file addons</h1>

<div class="input-group mb-3">
<input type="file" class="form-control" id="lokiFile1">
<label class="input-group-text" for="lokiFile1">Upload</label>
</div>

<div class="input-group mb-3">
<button class="btn btn-outline-secondary" type="button" id="lokiBtn1">Button</button>
<input type="file" class="form-control" aria-describedby="lokiBtn1" aria-label="lokiLabel2">
</div>
</div>

input:file 的 HTML5 屬性 multiple 為多檔案上傳,注意以陣列型態設定,例如 name[]。
這裡官方原文提到 custom 是因為 Bootstrap v5 版本的 select 與 input:file ,皆為重改瀏覽器外觀介面的自訂版本,而舊 v4 版本還保留瀏覽器版本共兩種可選用。因此官方文件還保留 custom 字眼。但對於現在來說只剩下自訂外觀介面,因此不用去在意 custom 字眼。

浮動標籤 Floating labels

form-floating 為另一種群組排版效果,同樣需將一對 label 與 input 整合成同一個欄位,透過互動產生浮動行為之提示標題。作用條件如下:

  • 透過父元素 div.form-floating 進行包覆 (position 設計),父元素內只會拿來放一對 label 與 input 沒有例外。
  • 子元素使用 input.form-control 與 普通 label 即可。
  • 注意 input 一定要提供 placeholder 屬性,才能產生作用。
  • 注意順序一定要 input + label,否則 CSS 的兄弟選擇器會失敗而無法產生作用。

然而根據原理如下:

  • 透過偽元素 input.form-control::placeholder 設定 color:transparent 字為無色。
  • label 元素會 absolute 重新定位到原本 input 的 placeholder 處,產生假重疊,真正的 placeholder 字看不見。
  • focus 事件、否定選擇器 (:not)、偽元素 (:placeholder-shown) 三者完成轉場,每當 input.form-control 發生 focus 且處在不是 placeholder 顯示時,其指定兄弟選擇器 ~ 找到 label 做轉場動畫。
  • 透過轉場移動 label 的位置與外觀。
  • focus 事件不存在動畫反轉。
<div class="container">
<div class="form-floating mb-3">
<input class="form-control" id="lokiFloatlabel1" placeholder="隨便不重要" type="email">
<label for="lokiFloatlabel1">Email address</label>
</div>
<div class="form-floating mb-3">
<input class="form-control" id="lokiFloatlabel2" placeholder="隨便不重要" type="password">
<label for="lokiFloatlabel2">Password</label>
</div>
<form class="form-floating mb-3">
<input class="form-control" id="lokiFloatlabel3" placeholder="隨便不重要" value="test@example.com" type="email">
<label for="lokiFloatlabel3">Input with value</label>
</form>
<form class="form-floating">
<input class="form-control is-invalid" id="lokiFloatlabel4" placeholder="隨便不重要" value="test@example.com" type="email">
<label for="lokiFloatlabel4">Invalid input</label>
</form>
</div>

Textarea 應用

也可套用在 textarea 元素上,將 input.form-control 改為 textarea.form-control。注意的是預設高度相對較矮(原根據 input 所設計的),你可自行調整高度修改。

<div class="container">
<div class="form-floating mb-3">
<textarea class="form-control" placeholder="隨便不影響" id="lokiFloatLabel1"></textarea>
<label for="lokiFloatLabel1">Message Writing Here...</label>
</div>
<div class="form-floating">
<textarea class="form-control" placeholder="隨便不影響" id="lokiFloatLabel2" style="height: 100px"></textarea>
<label for="lokiFloatLabel2">Message Writing Here...</label>
</div>
</div>

Select 應用

套用在 select.form-select 也可以,唯一差別因為沒有 placehoder 屬性,所以會直接定位在最終處上。

<div class="container">
<div class="form-floating">
<select class="form-select" id="lokifloat1">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<label for="lokifloat1">Works with selects</label>
</div>
</div>

Grid 排版

可輕鬆將 div.form-floating 整合到 Grid 排版系統內,只要注意 div 各自角色為何。

<div class="container">
<div class="row g-2">
<div class="col-md">
<div class="form-floating">
<input type="email" class="form-control" id="lokiLabel1" placeholder="隨便" value="mdo@example.com">
<label for="lokiLabel1">Email address</label>
</div>
</div>
<div class="col-md">
<div class="form-floating">
<select class="form-select" id="lokiLabel2" aria-label="Floating label select example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<label for="lokiLabel2">Works with selects</label>
</div>
</div>
</div>
<hr>
<h1 class="text-center">試著找出兩者差異</h1>
<hr>
<div class="row g-2">
<div class="col-md form-floating">
<input type="email" class="form-control" id="lokiLabel3" placeholder="隨便" value="mdo@example.com">
<label for="lokiLabel3">Email address</label>
</div>
<div class="col-md form-floating">
<select class="form-select" id="lokiLabel4" aria-label="Floating label select example">
<option selected>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<label for="lokiLabel4">Works with selects</label>
</div>
</div>
</div>

排版技巧 Layout

前一單元所介紹的都是表單零件外觀呈現,本節將提供多種的排版技巧選擇,協助你設計整個表單。

簡單的表單與通用類別應用

直接使用你的 HTML 認知來設計表單,大致有以下重點說明:

  • 所有套用 .form-control 的元素都會是 block 與 width:100% 效果。
  • Bootstrap 對 <form> 沒有特別設計因此 HTML 相關特性都保留,例如提交仍注意 buttom 元素自帶 submit 連動(除非持有 type 屬性)。
  • 對 form 元素添加屬性 disabled 會導致整個表單禁用。
  • 可使用 Margin 通用類別來做排版技巧,這是最直覺的排版加強技巧。例如建議使用 mb-3 增加空間感。

網格與間格 Grid & Gutter

使用 Grid 系統 row>col 輕鬆進行版面空間分配,並可搭配 gutter 參數調整欄位之間的距離,尤其在響應式網頁上有良好的表現能力。

<div class="container">
<form class="row g-3">
<div class="col-md-6">
<label for="inputEmail4" class="form-label">Email</label>
<input type="email" class="form-control" id="inputEmail4">
</div>
<div class="col-md-6">
<label for="inputPassword4" class="form-label">Password</label>
<input type="password" class="form-control" id="inputPassword4">
</div>
<div class="col-12">
<label for="inputAddress" class="form-label">Address</label>
<input type="text" class="form-control" id="inputAddress" placeholder="1234 Main St">
</div>
<div class="col-12">
<label for="inputAddress2" class="form-label">Address 2</label>
<input type="text" class="form-control" id="inputAddress2" placeholder="Apartment, studio, or floor">
</div>
<div class="col-md-6">
<label for="inputCity" class="form-label">City</label>
<input type="text" class="form-control" id="inputCity">
</div>
<div class="col-md-4">
<label for="inputState" class="form-label">State</label>
<select id="inputState" class="form-select">
<option selected>Choose...</option>
<option>...</option>
</select>
</div>
<div class="col-md-2">
<label for="inputZip" class="form-label">Zip</label>
<input type="text" class="form-control" id="inputZip">
</div>
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="gridCheck">
<label class="form-check-label" for="gridCheck">
Check me out
</label>
</div>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary">Sign in</button>
</div>
</form>
</div>

水平表單

透過 grid 調整為同一個 row 內兩組 col 做水平排列時,可對 label 添加 .col-form-label 使 label 高度與 input 高度一致垂直至中。如 input 有尺寸時亦提供對應的尺寸高度。

.col-form-label-sm  /*對應 input.form-control.form-control-sm 之高度*/
.col-form-label /*對應 input.form-control 高度*/
.col-form-label-lg /*對應 input.form-control.form-control-lg 之高度*/
https://getbootstrap.com/docs/5.0/forms/layout/#horizontal-form
<form class="container">
<div class="row mb-3">
<label for="inputEmail3" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="inputEmail3">
</div>
</div>
<div class="row mb-3">
<label for="inputPassword3" class="col-sm-2 col-form-label">Password</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="inputPassword3">
</div>
</div>
<fieldset class="row mb-3">
<legend class="col-form-label col-sm-2 pt-0">Radios</legend>
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="radio" name="gridRadios" id="gridRadios1" value="option1" checked>
<label class="form-check-label" for="gridRadios1">
First radio
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="gridRadios" id="gridRadios2" value="option2">
<label class="form-check-label" for="gridRadios2">
Second radio
</label>
</div>
<div class="form-check disabled">
<input class="form-check-input" type="radio" name="gridRadios" id="gridRadios3" value="option3" disabled>
<label class="form-check-label" for="gridRadios3">
Third disabled radio
</label>
</div>
</div>
</fieldset>
<div class="row mb-3">
<div class="col-sm-10 offset-sm-2">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="gridCheck1">
<label class="form-check-label" for="gridCheck1">
Example checkbox
</label>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Sign in</button>
</form>

欄位尺寸與自動分配

整合 grid 的欄位空間觀念,舉例以下狀況:

  • .col-7>input + .col.input + .col.input : 空間分配扣除 7 剩餘 5,三者 input 比例為 7 + 2.5 + 2.5
  • .row.align-items-center > .col-auto*n : 每個 input 會自動根據內容寬度為主,若部分高度不一致則依賴交軸對齊進行置中。
  • .row.align-items-center > .col-{number}*n + .col-auto*n : 同上話題,即使包含指定寬度的欄位也能自動分配。
  • .row.row-cols-lg-auto > .col-12*n : 斷點 LG 模式時會自動內容寬欄位,否則會滿寬為主。
  • .row.row-cols-lg-auto.g-3.align-items-center > .col-12*n : 同上,欄位的水平垂直都撐開間隔,且確保所有欄位零件都垂直對齊至中。

驗證 Validation

驗證主要是當表單進行提交時若欄位輸入錯誤或未填時禁止提交完成,並反向回饋到欄位畫面上說明錯誤的輸入缺失。驗證的顯示方法可以分為兩種,一種是瀏覽器提供的基本驗證功能,另一種是由 Bootstrap 搭配 JS 語法完成。

瀏覽器預設的驗證

要觸發瀏覽器預設的驗證事件有以下條件:

  • 需驗證的表單元素先添加屬性 required,同時搭配 input[type=*] 屬性來提供正規表達規則判斷,一旦不符合則直接回應預設之回應文字。
  • 需自訂回應文字可透過 HTML約束驗證 API,藉由 JavaScript 操作 setCustomValidity 來設計想要的正規表達規則與放送自訂回應文字,範例如下:
    <div class="container">
    <form class="row g-3">
    <div class="col-md-6">
    <label for="lokiName" class="form-label">Name</label>
    <input type="text" class="form-control" id="lokiName" required>
    </div>
    <div class="col-md-6">
    <label for="lokiPWD" class="form-label">Password</label>
    <input type="password" class="form-control" id="lokiPWD" required>
    </div>
    <div class="col-12">
    <button class="btn btn-primary" type="submit">Submit</button>
    </div>
    </form>
    </div>

    <script>
    document.addEventListener("DOMContentLoaded", function () { // 另一種 document.ready 的方法
    document.querySelector("#lokiName").oninvalid = function () {
    //當進行驗證事件時,如果不通過在指定物件變數獲得 false,顯示自訂提示字
    if (!this.validity.valid) this.setCustomValidity("你沒名字嗎?");
    }
    document.querySelector("#lokiName").oninput = function () {
    //當使用者進行編寫時,清除提示字。將不再顯示輸出
    this.setCustomValidity("");
    }

    //本身還是會有基本的 text 不留白的檢查
    document.querySelector("#lokiPWD").oninput = function () {
    //當使用者進行編寫時,進行另一種正規檢查而更改提示字
    this.setCustomValidity("");
    let mystr = new RegExp('\\d{4}$');
    if (!mystr.test(this.value)) this.setCustomValidity("只能 4 個數字");
    }
    });
    </script>

Bootstrap 驗證功能

也可改用 Bootstrap 的驗證功能自訂回應文字(同樣依賴 HTML 的驗證事件),原理為透過 input 對象(或 select,textarea 皆適合)之偽類 :valid(正確:綠) 和 :invalid(錯誤:紅) 來觸發指定之兄弟元素進行 display 呈現文字。因此你需要自己先編寫腳本來處理驗證,接著自行添加 class 至指定元素位置來顯示驗證。注意如下:

  • 由於 HTML5 本來有自己的表單驗證,使用 Bootstrap 驗證前需先關閉該功能,其對元素添加屬性 form[novalidate] 即可取消 HTML 驗證。
  • Bootstrap 的驗證呈現方式透過 form.was-validated 來切換,也就是你需要透過 JS 添加移除該 class(可試著先手動添加看看其效果),添加的時機通常是 submit 當下之處理。
  • 在 Ajax 應用技巧下(不離開網頁的後端串接),當你 callback 後已不需要驗證動作時,該做的事就是移除 form.was-validated 這個 class 名稱。
  • form.was-validated 狀態下,預設提供兩種驗證文字風格 (feedback 與 tooltip)。如需自訂回應文可添加元素 .valid-feedback.invalid-feedback 來規劃回應文字。
  • 同上,另一種風格為提示泡泡效果為 div.{valid-tooltip|invalid-tooltip},需確保父容器有 position:relative 可提供參考定位(如果是使用 .col 來排版就已有此參數)。
  • 舉例 javascript 腳本如何對提交時進行驗證後回饋畫面:
    <div class="container">
    <form class="row g-3 lokiValidation" novalidate>
    <div class="col-md-6">
    <label for="lokiInput1" class="form-label">Text1</label>
    <input type="text" class="form-control" id="lokiInput1" value="Mark" required>
    <!-- <div class="valid-feedback">good Message!!</div>
    <div class="invalid-feedback">fail Message!!</div> -->
    </div>
    <div class="col-md-6">
    <label for="lokiInput2" class="form-label">Text2</label>
    <input type="text" class="form-control" id="lokiInput2" value="" required>
    <div class="valid-feedback">good Message!!</div>
    <div class="invalid-feedback">fail Message!!</div>
    </div>
    <div class="col-12">
    <button class="btn btn-primary" type="submit">Submit form</button>
    </div>
    </form>
    </div>

    <script>
    document.querySelectorAll('.lokiValidation').forEach(function (nod) { //找到所有持有指定 class 之各項元素
    nod.addEventListener('submit', function (event) { //監測 submit 時,做以下事情
    if (!this.checkValidity()) { //如果這個元素的 checkValidity 為 false,代表驗證不通過
    event.preventDefault(); //取消當下的 event 預設行為
    event.stopPropagation(); //取消當下的傳遞與冒泡事件
    }
    this.classList.add('was-validated'); //顯示驗證文字結果,出現之場合看個人需求
    });
    });
    </script>

伺服器驗證

前面的操作是透過前端(建議)來做驗證處理(控制 submit 事件的後續步驟)。如果你的驗證是使用伺服器來做驗證(重新產生畫面),另一種替代方法為直接對控制單筆添加 input.{is-valid|is-invalid} (綠|紅)觸發來單項 input 的驗證顯示。如此一來可在沒有 form.was-validated 狀態下,由後端來決定哪些驗證提示做響應文字 (div.valid-feedback.invalid-feedback)。

響應驗證的元素

以下元素在驗證時皆會變色

input
textarea.form-control
select.form-select
div.form-check

公式表整理

基本欄位

應用場合 公式 適用位置
一般欄位 .form-label label
一般欄位 .form-control input,select,textarea
一般欄位 .form-text div(描述字)
選填型欄位 .form-check div(checkbox,radio 容器)
選填型欄位 .form-check-input input:checkbox,input:radio
選填型欄位 .form-check-label label(for checkbox or radio)
選單型欄位 .form-select select
範圍型欄位 .form-range input:range

追加調整

追加公式 整體公式寫法 適用位置
追加 *.form-control 之尺寸調整 .form-control.form-control-{sm|lg} input,select,textarea
追加 input:color 之排列方式 .form-control.form-control-color input:color
追加 *.form-select 之尺寸調整 .form-select.form-select-{sm|lg} input,select,textarea
追加 input:checkbox 容器外觀改為切換 .form-check.form-switch div(for checkbox|radio 的主容器)
追加 input:checkbox 容器排列改為行內 .form-check.form-check-inline div(for checkbox|radio 的主容器)

特殊應用

需求 組合公式 說明
全禁用 form > fieldset[disabled] 整個表單禁止操作
單一禁用 *[disabled] 對該元素禁止操作
僅顯示 *[readonly] 對該元素無法輸入
純顯示 *.form-control-plaintext 對該元素呈現為提示
按鈕型 checkbox input:checkbox.btn-check + label.btn.btn-{color} 將 checkbox 改為 button 按鈕效果

排版技巧

Input Group

項目 公式 適用位置
容器 .input-group div
容器添加高度 .input-group-{sm|lg} div.input-group
文字 .input-group-text div.input-group>span
欄位 .form-control div.input-group>*
文字上的選填欄位 .form-check-input .input-group-text>input:{checkbox|radio}
Button 元件 參考 button 元件介紹 div.input-group>*
dropdowns 元件 dropdowns div.input-group>*

Floating labels

項目 公式 適用位置
容器 .form-floating div
欄位 .form-control div.input-group>*
欄位標題 div.input-group>* ~ label

Grid System

項目 公式 適用位置
容器 .row div
欄位 .form-control div.row>.col-*>*
欄位標題 .form-label div.row>.col-* > label
添加col高度與欄位標題齊高 .col-form-label-{sm|lg} div.row>.col-*

驗證

項目 公式 適用位置
輸出全部表單驗證資訊(依HTML判斷) .was-validated form[novalidate]
輸出單一欄位驗證資訊(判斷為正確) .is-valid input,textarea,select
輸出單一欄位驗證資訊(判斷為錯誤) .is-invalid input,textarea,select
驗證正確之資訊文字 .valid-feedback input,textarea,select ~ *
驗證正確之資訊文字 .invalid-feedback input,textarea,select ~ *
驗證正確之資訊泡泡 .valid-tooltip input,textarea,select ~ *
驗證正確之資訊泡泡 .invalid-tooltip input,textarea,select ~ *