一個 CSS 切換按鈕是透過將原生 HTML 核取方塊以 appearance: none 隱藏,然後繪製一個軌道和一個圓形旋鈕來建構的。旋鈕的大小等於軌道高度減去兩倍的內邊距,其勾選狀態的位移則等於軌道寬度減去軌道高度。CSS 切換開關產生器會自動套用此模式:它將一個真實的 <input type="checkbox"> 包裝在 <label> 內部,提供同步的 CSS 來繪製藥丸形軌道和圓形旋鈕,並讓你能調整寬度、高度、邊距、持續時間和三種顏色,同時由即時預覽進行切換。幾何運算式會直接顯示在產生的宣告中,因此這些數值能一目了然地接受審查,而非藏在元件依賴項中。由於此控制項仍然是原生核取方塊,螢幕閱讀器、空白鍵啟動、焦點以及表單提交都能繼續正常運作,無需任何 ARIA 狀態同步。接下來的文章將逐步介紹產生器接受哪些輸入、如何執行、它執行的精確算術,以及在將此切換開關交付至設定畫面前值得執行的無障礙檢查。

css create toggle button
css create toggle button

為什麼原生核取方塊勝過 Div 作為 CSS 切換

切換開關是二元表單狀態,而不是一次性動作按鈕。在 HTML 中表達二元狀態最乾淨的方式就是 <input type="checkbox">,它已經提供勾選狀態、空白鍵啟動、焦點處理、表單提交以及可預期的螢幕閱讀器宣告。用 <div> 取代該輸入意味著必須使用自訂 JavaScript 重新建立上述每一項行為,再加上 role="switch" 與 aria-checked 等 ARIA 屬性,再加上焦點管理,再加上表單整合。這種取捨幾乎總是得不償失:一個自訂小工具若在其中任一面向有所偏差,即使 CSS 看起來正確,仍會在無障礙稽核中失敗。

此產生器保留了原生輸入,僅重新設定表面樣式。CSS 使用 appearance: none 來移除預設的核取方塊繪製,但底層元素仍會持續呈現勾選狀態與標準鍵盤行為。<input> 會嵌入在可見的標籤文字內,因此整個標籤區域皆可點擊,且該控制項已具有可存取名稱。由於語意上並未隱藏任何內容,框架適配器可以在 React 中將 class 改為 className,在 Vue 中維持相同的標籤結構,同時繼承正確的語意。這是任何其他切換教學開始之前值得理解的設計選擇,因為它決定了最終控制項是否需要 JavaScript。對於此工具產生的基本二元情況,答案是否定的:由於基本核取方塊狀態不需要 JavaScript,因此程式碼片段中不包含任何 JavaScript。

輸入限制與各控制項接受的值

此產生器會在繪製前驗證每一個輸入。預先閱讀限制可避免拒絕原本有效的組合,下表是此工具將接受之內容的唯一真實來源。

輸入 接受的值 限制
軌道寬度 36 至 120 整數像素 必須至少比高度大 8 px
軌道高度 20 至 64 整數像素 決定旋鈕直徑
內邊距 2 至 8 整數像素 必須在軌道內留下正向旋鈕空間
轉場持續時間 0 至 2000 整數毫秒 0 會停用可見的插補效果
關閉顏色 6 位數 HEX 必要格式 #RRGGBB
開啟顏色 6 位數 HEX 必要格式 #RRGGBB
旋鈕顏色 6 位數 HEX 必要格式 #RRGGBB

無效的組合會以純邏輯方式拒絕,而非產生負值大小或落在軌道外的旋鈕。例如,寬度 48 搭配高度 44 會失敗,因為寬度未至少超出高度 8 像素。三種顏色需要完整的六位數輸入;像 #abc 的三位數簡寫以及像 red 的具名關鍵字皆不接受,這能讓輸出對下游工具與設計權杖保持明確無歧異。所有運算皆在瀏覽器本機執行,因此設定與程式碼不會被上傳、持久保存或傳送至元件產生服務。

如何在 CSS 中建立切換按鈕

請依照下列步驟,無需手動撰寫幾何運算,即可產生具無障礙性、像素精準的切換程式碼。此工具完全在瀏覽器中執行,因此不會有任何資料離開頁面。

  1. 開啟產生器,在點擊預覽切換狀態的同時設定軌道寬度、軌道高度、內邊距、轉場持續時間、關閉顏色、開啟顏色與旋鈕顏色。預覽會即時反映每一項變更。
  2. 從 CSS 輸出面板複製 CSS,再從 HTML 輸出面板複製 HTML。這兩個面板彼此獨立,每個複製按鈕會各自要求剪貼簿權限。若剪貼簿存取被拒,可見的程式碼仍可供手動選取。
  3. 將 CSS 貼到你的樣式表,並將 HTML 貼到你的模板或元件中。將範例標籤(例如 Enable feature)替換為你實際要切換的二元設定,例如 Email notificationsDark mode
  4. 在產品中驗證狀態措辭、鍵盤操作、焦點對比、縮放、強制色彩、減少動畫偏好以及持久化行為。透過點擊軌道或標籤來切換預覽,然後按下 Tab 移動焦點,再按空白鍵翻轉狀態。
  5. 若你將此切換開關整合進 React、Vue 或其他框架,請在該環境中重新測試鍵盤行為。受控狀態的接線方式若 checked 與 change 處理函式不相符,可能會破壞原生互動,因此請確認在框架包裝此輸入後,空白鍵仍能進行切換。
  6. 若狀態變更會執行網路操作,請在此 CSS 之外處理等待中與失敗狀態。一個顯示為綠色卻聲稱已啟用 Dark mode 但實際儲存失敗的開關,比清楚的錯誤訊息更糟糕。

旋鈕背後的幾何原理

此工具並非從隱藏的樣式指南中挑選旋鈕大小或位移;這兩個數值直接來自兩條簡短的方程式,並寫入像素宣告之中。旋鈕大小等於軌道高度減去兩倍的邊距,位移距離等於軌道寬度減去軌道高度。

計算範例:軌道寬度 64 像素、軌道高度 32 像素、內邊距 4 像素。代入第一個公式,旋鈕大小為 32 減去 2 乘以 4,等於 24 像素。代入第二個公式,位移距離為 64 減去 32,等於 32 像素。邊距加旋鈕加位移加邊距為 4 加 24 加 32 加 4,等於 64 像素,與所選寬度相符,確認了內邊距會出現在兩端。

同一算術也說明了為什麼寬度必須至少超出高度 8 像素。在最小邊距 2 的情況下,20 像素高軌道中最小的旋鈕為 16 像素,而「寬度必須至少比高度大 8 像素」的規則迫使該情況下的寬度至少為 28。這 8 像素的緩衝能吸收邊距的實際變化,並讓開啟與關閉位置在視覺上一目了然地保持區分。軌道使用等於其高度一半的藥丸形邊框圓角,而圓形 ::after 旋鈕則以其自身大小的一半作為圓角,因此這兩個形狀在任何接受的尺寸下都能保持完美的圓形。背景顏色與 transform 皆共用同一個轉場持續時間,並使用 ease 時間函式關鍵字,這就是為什麼將持續時間設為零會移除可見的插補效果,而不會改變最終狀態。對於要求減少動畫偏好的使用者,請在目標樣式表中將 transition-duration 覆寫為零,因為複製的基準樣式並未包含媒體查詢。

交付前的無障礙與行為檢查

視覺對稱並不等同於可用,而此產生器刻意不產生狀態變體,讓所屬產品自行決定。請確認開啟與關閉不僅能透過顏色區分,特別是在相鄰的標籤文字未能明確表達目前狀態時。一列僅顯示 Notifications 而未說明切換開關目前是否為開啟狀態的設計,會讓螢幕閱讀器使用者與明眼使用者都難以判斷。當後果影響重大時,請在標籤旁加上明確的狀態文字,如 On 或 Off,或採用如 Enable 與 Disable 的動詞慣例。

請根據實際頁面背景(而非僅針對預覽)測試軌道顏色與焦點外框的對比。focus-visible 外框會保留在原生輸入上,並使用所選的開啟顏色,從軌道偏移而非被移除。在中性預覽中突出的顏色,可能在有色的頁面介面下消失;透過 顏色對比檢查工具 檢查頁面背景是浮現此類不符的最快方式。請驗證 200% 的縮放,因為部分瀏覽器在使用者放大頁面時會縮小焦點環與切換開關標籤。請驗證強制色彩模式與高對比主題,因為 Windows 高對比模式與 Chrome 強制色彩會以系統調色盤項目取代作者設定的顏色,藥丸形旋鈕可能因此失去其邊緣。請在行動裝置上測試觸控目標,因為可見軌道小於建議的 44 乘 44 像素目標;若周圍標籤的邊距過小,請將控制項包裝在更大的可點擊容器中。

Common Pitfalls When Wiring the Switch

A few patterns come up often enough to be worth calling out by name. The generator does not include hover, active, disabled, invalid, loading, or read-only presentations, so a production settings screen needs to add its own. Disabled controls in particular should make the disabled reason obvious; a grayed-out switch with no helper text looks broken rather than inactive. Keep error or help text associated with the field through aria-describedby or by placing it inside the same label region, and avoid changing server state before the user has received clear feedback.

Do not use a switch when a one-time action button or a multi-option choice is more accurate. A switch promises persistent state, so a Run report button or a Choose theme radio group should not be dressed as a toggle. For a related pattern, the checkbox styling guide walks through the same appearance: none approach for plain agree-to-terms boxes, which share the accessibility expectations but not the binary state wording. The native behavior is documented at MDN's appearance reference and in the W3C CSS Basic User Interface Level 4 appearance-switching section, both of which describe why the property exists and what user agents strip when it is set.

Treat the generated snippet as appearance only. The tool does not generate application settings logic, ARIA state synchronization for a non-native widget, analytics, persistence, API calls, or optimistic rollback. Those responsibilities belong to the product that consumes the switch, and the lack of JavaScript is intentional: a switch that promises Dark mode but failed to save is a worse user experience than a clear error message, so keep state management where it can fail loudly.

If you're weighing options, Average Color of an Image: Get the Exact HEX Locally covers this in detail.