スイッチの外枠を用意する
トグルスイッチを作るにあたり、まずはスイッチの外側の形をCSSで作っていきたいと思います。
表示結果を確認しやすいように、本番で使われるものよりやや大きめのサイズで作っていきます。
まず、横長の長方形を作った上で四隅の角を最大まで丸めていきます。
この時、最大まで丸めたいからと言って border-radius: 50% としてしまうと、下のサンプルのように要素が楕円形になってしまいます。
※border-radiusで要素の四隅を%(パーセント)を使って一括指定する場合は50%が最大となり、それ以上に角を丸めることはできません。
<div class="switch_outer"></div>
.switch_outer {
width: 120px;
height: 60px;
background-color: lightgray;
border-radius: 50%;
}
このように楕円の形にしてしまわないためには、border-radiusの値を%(割合)ではなく、pxなどの数値で指定する必要があります。
この時、border-radiusの値をheight値の1/2(例では30px)以上にすれば、角が最大まで丸まり、期待通りの表示結果になります。
.switch_outer {
width: 120px;
height: 60px;
background-color: lightgray;
border-radius: 30px;
}
スイッチの外枠となる部分を作ることができました!
ここで、ちょっとしたCSSの調整テクニックを一つご紹介しておきたいと思います。
先ほど作ったトグルスイッチの外枠のように、カプセル💊の形をしたボタンを作る機会は何かと多いですが、先述のようにborder-radiusに指定する値は要素のheight値によって変わります。
ですが、hight値に合わせてborder-radiusの値を指定していると、hight値が変更になるたびにborder-radiusの値も変更しなければならなくなり、メンテナンスも大変になりがちです。
そこで、そのような手間が生じないような調整方法として、infinity valueを使って調整する方法があります。
infinityは、calc()関数の中で使える特別な値で、その名の通り無限大の大きさを指定できるものです。(使用例は下をご参考ください)
.switch_outer {
width: 120px;
height: 60px;
background-color: lightgray;
border-radius: calc(infinity * 1px);
}
このように調整しておけば、height値の変更に合わせてborder-radiusの値を変更する必要がなくなります。
ただし、infinity valueは2023年4月現在、Firefoxには対応していないので、その点は注意が必要です。
この記事が公開された時点(2023/4)で、Firefoxからこのページをご覧いただいている場合、上の表示結果は角が丸まっていない(四角形のままである)ことが確認できるかと思います。
ちなみにですが、Chrome・Safari・Edgeなどその他の主要なブラウザはinfinityに対応しているので、Firefoxを重視しない場合は本番環境で使用しても問題ないでしょう。
POINT!
- ・カプセル状の形を作るには、border-radiusにheight値の半分以上の値を指定しよう!
- ・%(パーセント)を使った指定ではうまくいかないので注意!
- ・height値に関わらず常にカプセル状を維持したい場合は、calc() + infinityを使って調整しよう!
スイッチとなる円を配置する
スイッチの土台ができたので、次は切り替えの役割を果たす円形のスイッチを作っていきましょう。
スイッチの土台(.switch_outer)に子要素を配置し、その子要素(.toggle_switch)をスイッチとして調整していきます。
<div class="switch_outer">
<div class="toggle_switch"></div>
</div>
スイッチとなる要素のwidthとheightを同じ値にして正方形にした上でborder-radiusで角を丸めて正円にし、positionプロパティを使って位置を調整していきます。
positonで位置を調整するにあたり、親要素(.switch_outer)に position: relative を指定して位置調整の基準としておくのを忘れないように注意してください。
また、今回は正方形をまん丸にしたいので、border-radiusの値は50%でOKです。
.switch_outer {
width: 120px;
height: 60px;
background-color: lightgray;
border-radius: 30px;
position: relative;
}
.toggle_switch {
width: 50px;
height: 50px;
border-radius: 50%;
position: absolute;
background-color: white;
top: 0;
bottom: 0;
left: 5px;
margin: auto;
}
これでスイッチとなる部分の準備も完了です!…が、ここでもう一工夫加えていきたいと思います。
フラットなデザインにしたい場合はこれで良いのですが、このままではフラット過ぎてややスイッチっぽさに欠けますよね。
なので、悪目立ちしない程度にスイッチに影をつけることで、少しだけ立体感を出していきたいと思います。
要素に影をつけるには、box-shadowを適用させます。
.toggle_switch {
width: 50px;
height: 50px;
border-radius: 50%;
position: absolute;
background-color: white;
top: 0;
bottom: 0;
left: 5px;
margin: auto;
box-shadow: 1px 1px 7px #B7B7B7, -1px -1px 4px #CECECE inset;
}
スイッチにほんのり影がついて、立体感が生まれました!
要素に影をつける際は、あまり派手にし過ぎずに控えめにしておくのがコツです。(表現したいデザインにもよりますが)
なお、サンプルコードのようにbox-shadowの値を,(カンマ)で区切ることで、1つの要素に対して複数の影をつけることが可能です。
さらに、insetを付け足すと要素の内側に影をつけることができます。
あとはこれにクリックイベントを追加して、スイッチの位置や土台の色をアニメーションさせればトグルスイッチの完成です。
次の章ではJavaScriptも使って、トグルスイッチを仕上げていきたいと思います。
POINT!
- ・正方形の要素の角を丸めて正円にし、positionで位置を調整してスイッチの部分を作ろう!
- ・スイッチの外枠(親要素)を基準にするため、親要素にposision: relativeを指定するのを忘れずに!
- ・スイッチにbox-shadowでほんのり影をつけて、立体感を持たせるとさらにGOOD!
スイッチをアニメーションさせる
スイッチの見た目の調整が終わったら、次はいよいよ切り替えのアニメーションを作っていきます。
アニメーションが必要な部分は次の2つです。
これまでに、スイッチの外枠(.switch_outer)とスイッチ(.toggle_switch)を作ってきましたが、そのどちらにもアニメーションを追加する必要があるということですね。
要素にアニメーションを指定する方法はいくつかありますが、今回はtransitionプロパティを使ってアニメーションを指定していこうと思います。
animationプロパティを使ったアニメーションや、JavaScriptのrequestAnimationFrame()を使ったアニメーションと比べると、transitionを使ったアニメーションは実装が手軽で簡単なのが特徴です。
なのでアニメーションを設定したい場合は、まず最初にtransitionを使って表現できないかどうかを検討すると良いでしょう。
transitionプロパティは、次のような形式で値を指定することができます。
- transitionの指定
- transition: アニメーションさせたいプロパティ 秒数 アニメーションの種類
- 具体例
- transition: background-color 2s ease-in-out
アニメーションの種類には、linear(アニメーションの開始から終了まで等速)、ease-in-out(ゆっくり始まって加速し、最後はまたスピードが緩まる)など色々ありますが、現実の物体の動きを表現したい場合は、ease-in-outにしておくと自然になります。
また、当然ですがtrantisionプロパティを指定するだけではアニメーションにはなりません。
マウスオーバーやclassが追加された時など、特定の条件時のCSS調整も必要となります。
今回は、JavaScriptのclassList.toggle()を使って、“active”クラスを要素に追加したり外したりすることでアニメーションを起こさせるようにしてみましょう。
以上を踏まえて下のサンプルのコードを読み解いていけば、どこがどうなっているのかが分かるかと思います。
<div class="switch_outer">
<div class="toggle_switch"></div>
</div>
.switch_outer {
width: 120px;
height: 60px;
background-color: lightgray;
border-radius: 30px;
position: relative;
cursor: pointer;
transition: background-color .2s ease-in-out;
}
.switch_outer.active {
background-color: #51E373;
}
.toggle_switch {
width: 50px;
height: 50px;
border-radius: 50%;
position: absolute;
background-color: white;
top: 0;
bottom: 0;
left: 5px;
margin: auto;
box-shadow: 1px 1px 7px #B7B7B7, -1px -1px 4px #CECECE inset;
transition: left .3s ease-in-out;
}
.toggle_switch.active {
left: 65px;
}
//スイッチの外枠とスイッチの要素を取得
const switchOuter = document.querySelector(".switch_outer");
const toggleSwitch = document.querySelector(".toggle_switch");
//クリックでacitveクラスを追加/削除
switchOuter.addEventListener("click", () => {
switchOuter.classList.toggle("active");
toggleSwitch.classList.toggle("active");
});
オンとオフを切り替えるトグルスイッチの完成です!
ここから先は、コードの解説や補足説明を記していきます。
スイッチの外枠(.switch_outer)には、transitionでbackground-colorがアニメーションされるように設定し、スイッチ(.toggle_switch)には、leftがアニメーションになるように設定しています。
秒数はそれぞれ、0.2秒と0.3秒にしていますが、この数値に正解があるわけではないので、アニメーションを確認しながら微調整を加えていくと良いでしょう。
なお、アニメーション後のleftプロパティの値が65pxになるのは、初期状態が5px + スイッチの幅が50px = 55pxで、スイッチの外枠(120px)からその55pxを引いた値が65pxになるからです。
また、クリックできる要素であることをわかりやすくするために、スイッチの外枠の要素に対し、cursorプロパティの値をpointerに指定しています。
JavasCriptの方では、classList.toggle()を使って、要素がクリックされるたびにactiveクラスを追加・削除されるようにしています。
classListのtoggle()メソッドは、引数に指定された文字列のclassが要素のclassに存在しなければ追加し、存在していれば削除するという処理を行います。
toggle()を使ってclassの追加と削除を行い、それを利用して要素をアニメーションさせる方法は、ハンバーガーメニューやドロップダウンメニューなどあらゆる場面で使われるので、基本的な使い方をマスターしておくと何かと便利です。
ちなみにですが、ハンバーガーメニューの実装方法は別の記事で解説しているので、興味がある方は下のリンクからどうぞ!
【JavaScript】ハンバーガーメニューの基本的な動きを実装してみよう!
POINT!
- ・transitionを指定することで、特定のプロパティの値が変化したときにアニメーションになる!
- ・transitionには、アニメーションさせたいプロパティ・秒数・アニメーションの種類を指定できる!
- ・classList.toggle()で、要素へのクラスの追加・削除が簡単にできる!