input要素でON/OFFのスイッチを作成してみよう
VuefityやMaterial UIなどのフレームワークを利用していると下記のようなスイッチコンポーネントが含まれているのでアプリケーションに簡単に実装することができます。
このスイッチはどのような仕組み利用して作成することができるのか疑問を持った人もいるかと思います。仕組みを理解して自作のスイッチを作成したいという人向けに本文書を作成しました。本文書を読み終えるとOFFの状態からONの状態に遷移する(その逆も)スイッチを作成することができます。
目次
スイッチ作成のポイント
スイッチを作成するためにいくつかのポイントを理解しておく必要がありますがその中でも重要な4つのポイントを先に記述していきます。
- input要素のtype属性をcheckboxに設定する
- label要素とinput要素を関連付けを行う
- input要素はブラウザ上では非表示にする
- スイッチのボールの移動はtransformを利用する
上記のポイントを理解することができれば本文書を読み終えた後はスイッチの作成は簡単だなと思ってもらえると思います。
自作のスイッチの作成
index.htmlファイルを作成して以下のコードを記述します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<title>Switch Toggle Button</title>
</head>
<body>
<h1>スイッチボタン</h1>
<label for="switch">
<input type="checkbox" id="switch" />
スイッチ
</label>
</body>
</html>
input要素のtypeをcheckboxに設定しているので四角いチェックボックスがブラウザ上に表示されます。
label要素のfor属性とinput要素のid属性の関係
label属性のforの値とinput要素のidの値が一致する場合はlabel要素(文字列のスイッチ)をクリックしてもチェックボックスの選択と非選択を切り替えることができます。しかしforの値とidの値が一致しない場合はlabel要素の文字列をクリックしても何も変化はなく四角いチェックボックスをクリックした時だけ選択、非選択を切り替えることができます。この仕組みを理解しておくことでブラウザ上に小さなチェックボックスが表示されてなくてもチェックボックスの選択、非選択の切り替えができることを理解することができます。
input要素を非表示に
label属性のforの値とinput要素のidの値が一致する場合はlabel要素の文字列をクリックすることでチェックボックスの選択と非選択を切り替えることができるためチェックボックスを画面上に表示させておく必要はありません。
input要素のチェックボックスをブラウザ上から見えないように設定を行います。label要素にclass名switch_labelを設定しCSSを適用します。
<label for="switch" class="switch_label">
<input type="checkbox" id="switch" />
スイッチ
</label>
style.cssではswitch_labelクラスに一時的にpositionのrelativeを設定し、input要素にpositionのabsoluteとwidthとheightを0にします。
.switch_label {
position: relative;
}
input[type='checkbox'] {
position: absolute;
width: 0;
height: 0;
}
input要素はlabel要素を基準にpositionのabsoluteを設定しているので左上には存在しますがwidthとheightが0なのでブラウザ上には表示されません。チェックボックスは消えましたがスイッチの文字列をクリックするとinput要素のcheckboxの選択、非選択は切り替わっています。後ほど本当に切り替わっているかどうかは後ほどCSSを利用して明らかになります。
スイッチのベースを設定
スイッチのベース(ボールを含む横長の要素)を設定するためにdiv要素を追加します。追加したdiv要素にはbaseというclass名をつけます。
<label for="switch" class="switch_label">
<input type="checkbox" id="switch" />
<div class="base"></div>
スイッチ
</label>
style.cssでbaseクラスにCSSを適用します。
.base {
width: 56px;
border-radius: 16px;
height: 32px;
background-color: #ddd;
}
ベースは下記のような形になります。
スイッチの文字列とベースを横並べにするために新たにdiv要素を追加して親要素であるlabelのswitch_labelクラスでflexを設定します。文字列スイッチはspan要素で包みCSSを適用できるようにtitleクラスを設定します。
<label for="switch" class="switch_label">
<div>
<input type="checkbox" id="switch" />
<div class="slider"></div>
</div>
<span class="title">スイッチ</span>
</label>
style.cssではswitchクラスととtitleクラスにCSSを適用します。
.switch_label {
display: flex;
align-items: center;
}
input[type='checkbox'] {
position: absolute;
width: 0;
height: 0;
}
.base {
width: 56px;
border-radius: 15px;
height: 32px;
background-color: #ddd;
}
.title {
margin-left: 4px;
}
スイッチのベースと文字列の”スイッチ”が横並びになります。
スイッチのベースカラーの切り替え
スイッチのベースの背景色をチェックボックスの選択、非選択で切り替わるように設定を行います。input要素のチェックボックスは見えていないだけでスイッチの文字列をクリックすると選択、非選択が切り替わります。その特性を利用してチェックボックスがチェックされた時(input:checked)にbaseクラスの背景色が別の色になるように設定を行います。
input:checked ~ .base {
background-color: rgb(219, 234, 254);
}
設定後スイッチの文字列をクリックするとベースの背景色が薄いグレーから薄いブルーになることが確認できます。再度クリックするとまた元の色に戻ります。スイッチの文字列だけではなくベース自身をクリックしても色が変わります。どちらもlabel要素の中に含まれているためです。
この設定で四角いチェックボックスが表示されなくても選択、非選択が本当に切り替わっていることがわかりました。
スイッチのボールの設定
ベースの設定が完了したので次にスイッチにボールを追加します。スイッチのボールを表示されるdiv要素を追加し、classのcircleを設定します。
<label for="switch" class="switch_label">
<div>
<input type="checkbox" id="switch" />
<div class="circle"></div>
<div class="base"></div>
</div>
<span class="title">スイッチ</span>
</label>
style.cssにcircleクラスを追加します。widthとheightを24pxに設定し円で表示させるためにborder-radiusでwidth, heightの半分の値である12pxを設定します。
.circle {
position: absolute;
top: 4px;
left: 4px;
width: 24px;
height: 24px;
border-radius: 12px;
background-color: gray;
}
ベース、ボールのサイズの関係は下記の図のようになります。
ブラウザで確認するとpositionのabsoluteを設定していますが基準となるpositionが設定されていないためブラウザが基準となりブラウザの左上に表示されます。
スイッチのベース上にボールを表示するためにinput要素とdiv要素(.circle、.base)を包んでいるdiv要素にswitchクラスを設定します。
<label for="switch" class="switch_label">
<div class="switch">
<input type="checkbox" id="switch" />
<div class="circle"></div>
<div class="base"></div>
</div>
<span class="title">スイッチ</span>
</label>
style.cssにswitchクラスを設定しpositionをrelativeに設定します。
.switch {
position: relative;
}
ボールの基準がブラウザからswitchクラスを持つdiv要素に変わったためベースの上に設定したボールが表示されます。
ボールの移動
スイッチのベースの背景色はinput:checkedを利用してクリックするごとに色を変更することができるように設定しました。ボールの場合はクリックすると表示する場所を移動させる必要があります。移動させるためにtransformプロパティを利用します。
x方向に100%つまりボール一つ分移動するように設定を行います。
input:checked ~ .circle {
transform: translateX(100%);
}
スイッチの文字列、またはスイッチのベース、ボールどこをクリックしてもボールが右側に移動することが確認できます。
再度クリックすると元の状態に戻ります。ここまでの設定でスイッチは完成です。
ボールの色の設定
ボールの色もクリックに合わせて変更できるように設定します。デフォルトは白でクリックするとブルーになるように設定を行います。
.circle {
position: absolute;
top: 4px;
left: 4px;
width: 24px;
height: 24px;
border-radius: 12px;
background-color: white;
}
input:checked ~ .base {
background-color: rgb(219, 234, 254);
}
input:checked ~ .circle {
transform: translateX(100%);
background-color: blue;
}
クリック前のカラーは薄いグレーのベースにボールは白です。
クリックを行うとベースは薄いブルーになり、ボールはブルーになります。
transitionの設定
クリックをするとすぐに色が変わるのでtransitionを利用してゆっくりと色が変わるように設定を行います。
.circle {
position: absolute;
top: 4px;
left: 4px;
width: 24px;
height: 24px;
border-radius: 12px;
background-color: white;
transition: 0.5s;
}
input:checked ~ .base {
background-color: rgb(219, 234, 254);
transition: 0.5s;
}
クリックするとゆっくりと色が変化していくことを確認してください。
文字列の変更
”スイッチ”という文字列を設定していますがcheckboxが選択されているかされていないかで文字列が変わるように設定を行います。クリックに合わせて文字列の変更を行うためにJavaScriptを利用します。
デフォルト状態での文字列をスイッチからOFFに変更します。
<label for="switch" class="switch_label">
<div class="switch">
<input type="checkbox" id="switch" />
<div class="circle"></div>
<div class="base"></div>
</div>
<span class="title">OFF</span>
</label>
JavaScriptについてはJavaScriptファイルを別で準備することもできますがコードが短いのでindex.htmlにscriptタグを追加します。
//略
</label>
</body>
<script>
</script>
</html>
チェックボックスの選択、非選択はinput要素から取得することができるのでgetElementByIdを使ってinput要素に設定されているidの値を設定します。
const checkbox = document.getElementById('switch');
イベントリスナーを利用してチェックボックスの変更を監視します。”OFF”の文字列はtitleクラスを持つdivに含まれているのでquerySelectorを利用して要素を取得しています。checkbox.checkedにはチェックボックスが選択された場合はtrueそうでない場合はfalseが含まれます。checkbox.checkedの値によってtitleに表示する文字列を切り替えています。trueの場合はON, falseの場合はOFFが表示されます。
const checkbox = document.getElementById('switch');
checkbox.addEventListener('click', () => {
const title = document.querySelector('.title');
title.textContent = checkbox.checked ? 'ON' : 'OFF';
});
クリックするとONに更新され、再度クリックするとOFFに更新されることを確認してください。これでToggle Switchの完成です。
スイッチの作成方法にはさまざまありますが、冒頭で説明したポイントを理解することができればCSSを設定することで見栄えの異なるオリジナルのスイッチを作成することができます。これまでスイッチを作成したことがない人もぜひオリジナルのスイッチ作成にチャレンジしてみてください。