[React] CSSでiOSのUISwitchライクなSwitchを作る
CSSでiOSのUISwitchライクなReactコンポーネントを作ってみました。
はじめに
こんにちは。CX事業本部 Delivery部 フロントエンドチームの加藤です。 今回はCSSでiOSのUISwitchライクなReactコンポーネントを作ってみたいと思います。
開発環境
- macOS Monterey 12.6
- CodeSandbox(React Typescriptテンプレートを使用)
作ったコンポーネント
iOSのUISwitchのようにクリックするたびにON/OFFが切り替わります。
コード
Switch.tsx
SwitchのReactコンポーネントです。 現在のON/OFF状態とON/OFFを切り替えた時の処理をpropsで受け取ります。 以下がポイントです。
- ON/OFF状態を持たせるため、
type="checkbox"
のinput
要素を使う input
要素自体はON/OFFの状態を持つだけで、外観のカスタマイズはlabel
要素を使うlabel
要素クリック時にON/OFFを切り替えるためにhtmlFor
でinput
要素とlabel
要素を紐づける
import "./styles.css"; type Props = { checked: boolean; onChange: (checked: boolean) => void; }; export default function Switch(props: Props) { const { checked, onChange } = props; return ( <> <input id="switch" type="checkbox" checked={checked} onChange={() => { onChange(!checked); }} /> <label htmlFor="switch"></label> </> ); }
styles.css
cssです。 実際の開発ではクラスセレクターを使うことが多いかと思いますが、今回は動作確認目的であるため、要素型セレクターを使っています。 以下がポイントです。
input
はON/OFFの状態を持つだけで外観はlabel
が担当するので、input
は非表示にするlabel
を使ってSwitchの外観部分を表現する- 擬似要素
label::before
を使って白丸部分を表現する - 擬似クラス
input:checked
を使って、SwitchがONの時に背景色や白丸左側の余白を変更する - 背景色や余白の変更は
transition
でアニメーションさせる
input { /* チェックボックスは使わないので非表示 */ display: none; } input:checked + label { /* スイッチONの時のSwitchの背景色*/ background-color: #35c659; } input:checked + label::before { /* スイッチONの時の左側余白 */ left: 1.9em; } label { position: relative; background-color: #e9e9ea; /* スイッチOFF時の背景色 */ border-radius: 1em; /* 角丸 */ cursor: pointer; display: flex; align-items: center; font-size: 24px; width: 3.75em; height: 2em; transition: 0.2s; } label::before { position: absolute; background-color: #ffffff; border-radius: 0.85em; content: ""; width: 1.7em; height: 1.7em; left: 0.15em; transition: 0.2s ease-out; }
App.tsx
Switch
コンポーネントを呼び出す上位のコンポーネントです。
ON/OFFをuseState
で管理しています。
import { useState } from "react"; import "./styles.css"; import Switch from "./Switch"; export default function App() { const [switchIsChecked, setSwitchIsChecked] = useState(false); return ( <Switch checked={switchIsChecked} onChange={(checked) => { setSwitchIsChecked(checked); }} /> ); }
おわりに
今回はCSSでiOSのUISwitchライクなReactコンポーネントを作ってみました。 擬似要素と擬似クラスを組み合わせることで実現できました。
以上です。