當你產生 CSS 切換開關時,真正重要的細節是軌道寬度、軌道高度、內距、轉場持續時間,以及三組六位數的 HEX 顏色——因為旋鈕大小等於軌道高度減去兩倍內距,移動距離等於寬度減去高度,而寬度必須至少比高度大 8 像素。除了這些輸入之外的其他視覺屬性,包括圓角半徑、旋鈕直徑和焦點外框,都是由公式衍生,而不是自由選擇。一旦這些輸入通過邊界檢查,產生器會包裝一個原生 checkbox,讓 Space 啟動、焦點、表單送出和勾選狀態語意都直接可用,CSS 只負責改變外觀。這種區別——原生互動與裝飾性 CSS 之間的差別——就是核心細節,因為它決定了最終的控制項是真正的表單欄位,還是一個需要 ARIA 模擬、獨立鍵盤處理和手動狀態同步的假元件。上列的數值就是你做出的完整決策集合;其餘都是運算,本文其餘部分會逐一檢視每個細節,讓你能驗證某個開關在你的實際產品中是否站得住腳。

決定開關外觀的幾何細節
切換開關的實體形狀並非自由選擇——它是你提供三個整數後的算術結果。軌道寬度、軌道高度和內距組合出旋鈕大小與移動距離,你可以直接從複製出來的 CSS 讀出來。旋鈕大小等於軌道高度減去兩倍內距;以 28 像素高的軌道、4 像素的內距為例,會得到 20 像素的旋鈕(28 − 2 × 4 = 20)。移動距離等於軌道寬度減去軌道高度,所以 64 像素寬、28 像素高的軌道在切換時會移動 36 像素(64 − 28 = 36)。合在一起看,內距 + 旋鈕 + 移動距離的式子會化簡為寬度減去內距,這代表同一個選定的內距會出現在軌道兩端的任一狀態下(4 + 20 + 36 = 60,而 64 − 4 = 60)。
邊界檢查會讓這套算術保持誠實。寬度接受 36 到 120 之間的整數像素。高度接受 20 到 64 之間的整數像素。寬度必須至少比高度大 8 像素。內距接受 2 到 8 像素,且必須在軌道內留出正向的旋鈕空間。持續時間接受 0 到 2000 之間的整數毫秒數。三組顏色都必須輸入完整的六位數 HEX。無效的組合會被純邏輯拒絕,而不是產生出負值大小或跑到軌道外的旋鈕,這也是為什麼產生器能把幾何直接以單純的像素宣告呈現,而不必藏在元件依賴背後的原因。軌道使用藥丸狀的圓角,其半徑等於高度的一半;圓形旋鈕則使用其自身大小的一半作為半徑——兩者都直接由上述尺寸決定。
| 輸入 | 範圍 | 類型 | 邊界 |
|---|---|---|---|
| 軌道寬度 | 36–120 px | 整數像素 | 必須 ≥ 高度 + 8 px |
| 軌道高度 | 20–64 px | 整數像素 | 必須留出正向旋鈕空間 |
| 內距 | 2–8 px | 整數像素 | 必須保留正向旋鈕 |
| 持續時間 | 0–2000 ms | 整數毫秒 | 0 會關閉插補效果 |
| 關閉顏色 | 6 位數 HEX | 顏色 | 未勾選時的軌道顏色 |
| 開啟顏色 | 6 位數 HEX | 顏色 | 勾選時的軌道顏色;亦用於 focus-visible 外框 |
| 旋鈕顏色 | 6 位數 HEX | 顏色 | 移動中圓形的顏色 |
如果讀者想看同一套代數從頭到尾跑一遍,CSS 切換開關旋鈕移動距離的計算解析更詳細地說明了「內距 + 旋鈕 + 移動距離 = 寬度 − 內距」這個恆等式。
承載狀態與焦點的顏色細節
三組顏色驅動了視覺狀態:關閉(未勾選時的軌道顏色)、開啟(勾選時的軌道顏色),以及旋鈕(在兩者之間移動的圓形)。這三組顏色都必須輸入完整的六位數 HEX——不接受縮寫、不接受具名顏色、不接受 rgba——因為輸出必須是可以檢視、可預期且可攜帶的。focus-visible 外框會重複使用選定的開啟顏色,並且從軌道向外偏移而不是移除,這能在不犧牲設計的前提下,讓原生 checkbox 對鍵盤使用者保持可見。
這個選擇會帶來一個實際的後果。一個在預覽中看起來很顯眼的鮮豔開啟顏色,放到深色或有圖樣的背景上時可能會消失不見。複製出來的 CSS 不會警告你,所以驗證步驟就是把焦點外框貼到目標主題中,確認它仍然清楚可讀。CSS 切換開關產生器處理的是幾何與對應的轉場;與周遭版面之間的對比,則屬於你自己樣式表的責任。當開啟顏色為了視覺上的柔和而選擇淡色時,只為了焦點外框而把它換成較深的強調色是合理的,這在無障礙元件函式庫中也是常見做法。
產生器不會額外加入獨立的 hover、active、disabled、invalid、loading 或 read-only 樣式,所以關閉、開啟和旋鈕以外的任何顏色決策,都屬於你設計系統的範疇。生產環境的設定畫面應該讓禁用狀態的控制項在視覺上可理解、讓錯誤或說明文字與欄位保持關聯,並在使用者收到明確回饋之前避免變更伺服器狀態。
時間細節:持續時間、緩動與減少動效
轉場持續時間是唯一的動畫控制項,它是一個以毫秒為單位的整數。軌道背景顏色與旋鈕變形會共用同一個選定的持續時間,並搭配 ease 時間關鍵字,讓兩個屬性的動畫保持一致。把持續時間設為 0 會移除可見的插補效果,而不會改變狀態——這對減少動效的覆寫設定來說很實用。
複製出來的基準樣式並不包含媒體查詢,所以如果動畫只是裝飾性質,或使用者已要求減少動效,請在目標樣式表的 @media (prefers-reduced-motion: reduce) 中加上 transition-duration: 0(或 transition: none)。這個細節值得刻意處理,而不是假設工具「會自動處理」。表單控制項上的動畫可能引發前庭不適、可能干擾使用螢幕放大鏡的使用者追蹤移動中的旋鈕,也可能讓人分心而忽略了狀態變更本身的意義。以 200 毫秒滑動的開關一般沒問題;以 2 秒彈跳動畫呈現的開關就不行。0 到 2000 毫秒的範圍涵蓋了兩端,讓你能自行決定設定畫面應該落在這個光譜上的哪個位置。
跨越框架整合仍能存活的無障礙細節
切換開關是一種二元表單狀態,產生器透過包裝原生 checkbox 來表達它。input 保留 type="checkbox",外層 CSS 使用 appearance: none 來移除預設繪製,同時保留原生勾選狀態、Space 啟動、焦點與表單送出。input 嵌在可見的 label 文字中,所以整個標籤區域都可點擊,這個控制項無需額外 ARIA 就擁有可存取名稱。這就是為什麼採用原生 checkbox,而不是 <div role="switch">:原生元素本身已經提供了裝飾性元素必須模仿的語意。根據 MDN 的 appearance 參考資料,appearance: none 會剝除平台外觀,同時保留互動行為——這正是此產生器所依賴的契約。
當你把程式碼片段貼進框架時,要保護的就是這個原生關係。React 使用者可以把 class 改成 className,但語意上的 input 與 label 配對應該維持不變。受控狀態的接線若 checked 與 change 處理函式配對錯誤,可能會打斷原生互動;視覺上的開關看似切換了,但表單值並未改變。整合之後請重新驗證 Tab 焦點、Space 啟動與表單送出。如果狀態變更會觸發網路操作,請在這段 CSS 之外處理 pending 與失敗狀態,不要讓視覺上的開關承諾了一個沒有實際存續的變更。
自訂切換開關需要的不只是合法 CSS,還需要更全面的無障礙與可用性檢查:確認開啟與關閉能透過顏色以外的方式區分,特別是在鄰近文字無法讓狀態一目了然的情況下;測試對比、鍵盤順序、縮放、觸控目標大小、螢幕閱讀器朗讀、forced-colors 模式、高對比、disabled 狀態,以及任何非同步失敗情形。W3C 的 CSS Basic User Interface Level 4 appearance 定義記載了 appearance 值選擇背後的標準依據,是說明 appearance: none 究竟移除了什麼的正式參考。
產生 CSS 與 HTML
- 開啟 CSS 切換開關產生器,設定軌道寬度、高度、內距、持續時間,以及三組顏色——關閉、開啟和旋鈕——同時觀察預覽中的切換隨著你的調整而更新。
- 點擊軌道或標籤,確認預覽與預期的二元設定一致,接著測試鍵盤操作:Tab 進入焦點、Space 切換。
- 分別使用兩個複製按鈕獨立複製 CSS 與 HTML;兩者各自會請求剪貼簿權限,即使遭到拒絕,畫面上仍可手動選取程式碼。
- 把佔位用的標籤文字(範例為 "Enable feature")替換為簡潔且貼近實際情境的狀態,例如 "Email notifications" 或 "Dark mode",讓可存取名稱反映真實的設定。
- 在產品中驗證:狀態用詞明確無歧義、焦點外框在真實頁面背景上仍然清楚可讀、縮放不會破壞版面、forced-colors 模式下指示符仍可見、減少動效的使用者看不到插補效果,而數值是否持久保存,則由你的應用程式自行決定。
工具未涵蓋的持久化與行為細節
產生器僅提供外觀與原生互動。它不會產生應用程式設定邏輯、非原生 widget 的 ARIA 狀態同步、分析功能、持久化、API 呼叫或樂觀回滾。這些責任屬於使用此控制項的產品本身。由於基本的核取方塊狀態不需要 JavaScript,因此複製的程式碼片段中也不包含 JavaScript;此外,並沒有任何內建機制能夠記住開關在頁面重新載入時、跨裝置時,或在網路故障後是處於開啟還是關閉狀態。
對於重要的設定,請將其持久化儲存於伺服器端,並在請求進行期間顯示一個待處理狀態。對於不重要的設定,本地的核取方塊狀態可能就已足夠,但應明確記錄這一點,以免使用者感到意外。常見的混淆來源在於:當儲存失敗時,由於框架將 checked 狀態回滾為舊值,開關會在視覺上回到先前的位置 —— 應將視覺效果與明確的成功或錯誤回饋搭配使用,而不是僅仰賴樂觀變更。
如果您的應用程式需要記錄是誰在何時更改了哪個設定的稽核軌跡,請在產生器之外擷取該資訊。一筆簡短的日誌條目、一個伺服器時間戳記,以及一則確認訊息,是承擔此責任的正確層級。CSS 無從得知,也不應該得知使用者是誰。對於需要將決策追溯回已記錄產物的團隊來說,為產生的 CSS 切換開關設計的記錄工作流程概述了如何保留實際出貨至正式環境的程式碼、標籤與組態的副本。