モダンCSSの機能を使用して、フォームのラジオボタンやチェックボックスを独自のスタイルで実装するテクニック
Post on:2020年2月21日
モダンCSSの機能を使用して、フォームのラジオボタン・チェックボックス・トグルスイッチなどを独自のスタイルで実装するテクニックを紹介します。以前まではdivやspanなど追加のHTMLやJavaScriptが必要でしたが、一切必要ありません。
こういった実装はできないものと思っていたので、驚きました。
Custom Styling Form Inputs With Modern CSS Features
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
モダンCSSの機能を使用した入力フォーム
最近ではセマンティックとアクセシビリティの両方を維持したまま、独自のチェックボックス・ラジオボタン・トグルスイッチなどを実装することができます。追加のHTMLやJavaScriptは一切必要ありません。
以前より簡単になったその実装方法を解説します。
まずは、完成した入力フォームをご覧ください。
もちろん、カラーやエフェクトなど自由にスタイルを適用できます。
See the Pen
2020 Toggles by Aaron Iker (@aaroniker)
on CodePen.
実装は以前より簡単になりました
簡単になった理由は、<input>タグに::beforeや::afterの疑似要素でスタイル設定ができるからです。つまり、<input>に対してスタイルを定義できるため、余分な要素は必要ありません。
以前はこれができなかったため、余分な<div>や<span>が必要でした。
【訳者注】
疑似要素はコンテンツがない要素(input, textarea, imgなど)には利用できないと思っていたのですが、けっこう前から動作するようです。
参考: Can a ::before selector be used with a <textarea>?
また、著者によるとブラウザが「appearance: none;」をサポートしていれば、動作するそうです。ここで紹介する実装方法は「appearance: none;」をサポートするChrome, Safari, Firefoxには期待通り適用され、非サポートのIEではプログレッシブエンハンスメントでデフォルトのスタイルが適用されます。ただし、仕様では確認できない実装方法のため、こういうこともできるんだと頭の片隅に入れておくくらいがよいかもしれません。
HTMLは非常にシンプル
注意すべき点は何もありません。下記のHTMLだけで入力フォームのスタイルを適用できます。
1 2 3 4 5 6 7 8 |
<!-- チェックボックス --> <input type="checkbox"> <!-- ラジオボタン --> <input type="radio"> <!-- トグルスイッチ --> <input type="checkbox" class="switch"> |
最低限のHTMLは上記で終わりですが、もちろん<label>要素を加えて、name属性とid属性を定義することをお勧めします。
1 2 3 4 5 6 7 8 9 10 11 |
<!-- チェックボックス --> <input type="checkbox" name="c1" id="c1"> <label for="c1">Checkbox</label> <!-- ラジオボタン --> <input type="radio" name="r1" id="r1"> <label for="r1">Radio</label> <!-- トグルスイッチ --> <input type="checkbox" class="switch" name="s1" id="s1"> <label for="s1">Switch</label> |
CSSで入力フォームのスタイルを定義
@supportsを使用して、appearance: none;のサポートをチェックします(プレフィックス付きで)。appearanceプロパティは、要素からブラウザのデフォルトのスタイルを削除するものです。プロパティがサポートされていない場合はスタイルは適用されず、デフォルトのスタイルが適用されます。これは全く問題なく、プログレッシブエンハンスメントの良い使用例です。
1 2 3 4 5 6 7 |
@supports(-webkit-appearance: none) or (-moz-appearance: none) { input[type='checkbox'], input[type='radio'] { -webkit-appearance: none; -moz-appearance: none; } } |
2020年現在、appearanceプロパティをサポートするブラウザは下記の通りです。
CSS Appearanceのブラウザのサポート -Can I Use
link要素と同じように、フォーム要素にもさまざまなインタラクティブな状態をスタイルするためのステータスがあります。フォーム要素をスタイルする時にはこれらを考慮しましょう。
- :checked
- :hover
- :focus
- :disabled
例えば、トグルスイッチのスタイルを定義し、ノブを作成し、:checked状態をスタイルする時は下記のようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
/* トグルのコンテナ */ .switch { width: 38px; border-radius: 11px; } /* トグルのノブ */ .switch::after { left: 2px; top: 2px; border-radius: 50%; width: 15px; height: 15px; background: var(--ab, var(--border)); transform: translateX(var(--x, 0)); } /* チェックされた時にカラーとポジションを変更する */ .switch:checked { --ab: var(--active-inner); --x: 17px; } /* 入力が無効になった時にトグルノブの不透明度を下げる */ .switch:disabled:not(:checked)::after { opacity: .6; } |
<input>要素をコンテナのように使用しています。入力の内側のノブは::after疑似要素で作成します。繰り返しになりますが、余分はHTMLは必要ありません!
デモでスタイルを開いてみると、CSSのカスタムプロパティが定義されているのが分かると思います。これは再利用可能な値を管理するための便利な方法です。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@supports(-webkit-appearance: none) or (-moz-appearance: none) { input[type='checkbox'], input[type='radio'] { --active: #275EFE; --active-inner: #fff; --focus: 2px rgba(39, 94, 254, .25); --border: #BBC1E1; --border-hover: #275EFE; --background: #fff; --disabled: #F6F8FF; --disabled-inner: #E1E6F9; } } |
カスタムプロパティを使用しているのには、もう1つ理由があります。要素のステータスに基づいて値を更新する場合にも有効です。ここでは詳しく触れませんが、さまざまなステータスでカスタムプロパティを使用する例をいくつか紹介します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* デフォルト */ input[type='checkbox'], input[type='radio'] { --active: #275EFE; --border: #BBC1E1; border: 1px solid var(--bc, var(--border)); } /* デフォルトを上書き */ input[type='checkbox']:checked, input[type='radio']:checked { --b: var(--active); --bc: var(--active); } /* チェックされておらず無効な場合、ホバー時にボーダーを別のカラーにします。 */ input[type='checkbox']:not(:checked):not(:disabled):hover, input[type='radio']:not(:checked):not(:disabled):hover { --bc: var(--border-hover); } |
アクセシビリティを考慮して、フォームにスタイルを追加する必要があります。デフォルトのoutlineは他のスタイルのように丸くできないため、一旦削除します。その後、box-shadowに沿ったborder-radiusを使用して、outlineのように機能する丸みのあるスタイルにできます。
1 2 3 4 5 6 7 8 9 10 11 |
input[type='checkbox'], input[type='radio'] { --focus: 2px rgba(39, 94, 254, .25); outline: none; transition: box-shadow .2s; } input[type='checkbox']:focus, input[type='radio']:focus { box-shadow: 0 0 0 var(--focus); } |
また、<input>要素のすぐ後に続く<label>要素の位置合わせとスタイル設定も可能です。
1 2 |
<input type="checkbox" name="c1" id="c1"> <label for="c1">Checkbox</label> |
1 2 3 4 5 6 7 8 9 10 11 |
input[type='checkbox'] + label, input[type='radio'] + label { display: inline-block; vertical-align: top; /* 追加のスタイルをここに記述 */ } input[type='checkbox']:disabled + label, input[type='radio']:disabled + label { cursor: not-allowed; } |
入力フォームの完成
これで完成です。
See the Pen
2020 Toggles by Aaron Iker (@aaroniker)
on CodePen.
フォームのカスタムスタイルを作成することの素晴らしさを実感されたと思います。入力フォームに直接疑似要素を使用できるおかげで、最小限のHTMLで実装できます。カスタムプロパティのおかげで、凝ったスタイルの切り替えも必要ありません。また、@supportsのおかげで、ブラウザのサポートもかなり優れています。
全体的に見て、わたし達がこれまでに対処しなければならなかったことよりも遙かに快適なデベロッパー エクスペリエンスだと思います!
sponsors