PATAPATA WORKS

ON・OFFのスイッチをフォームで作ってみる

こういうスイッチのようなフォームは、CSSだけで作成してしまえば使いまわしたりする事も簡単になります。
と、言うわけで早速作ってみたいと思います。

スイッチが動く仕組み

スイッチ部分をCSSで動かす場合どの様に動かせば良いのでしょうか?
フォームの中でスイッチと用途が似ているのはラジオボタンとチェックボックスになります。

チェックボックスやラジオボタンはラベルを使用することで、チェックボックスやラジオボタン自体を押さなくてもボタンを押す事ができます。この仕組を利用してチェックボックス等を書き換えてあげることで好きな形のボタンを作成することが出来るようになります。

さらにもう一つ、チェックボックス等は:checkedと言う擬似クラスを使うことが可能です。この疑似クラスはその名の通り押されている時に適用されるCSSと言う事になります。

この2つを使うことで、手軽にスイッチを作成することが可能です。
と、言うわけで今回はチェックボックスを使ってスイッチを作成してみようと思います。

HTML

<div class="form-switch">
  <label for="switchsample" class="form-switch-items">
    <input type="checkbox" name="switchsample" id="switchsample" class="form-switch-tab" checked="" role="switch">
    <div class="icon"></div>
    <span>スイッチのテキスト</span>
  </label>
</div>

CSS

.form-switch {
  /* --- カスタムプロパティ --- */
  --switch-width: 44px;
  --switch-height: 24px;
  --switch-border-width: 2px;
  --switch-gap: 10px;
  --switch-transition-speed: 0.3s;
  /* ノブのサイズ */
  --switch-knob-size: calc(var(--switch-height) - (var(--switch-border-width) * 2));
  /* ノブの移動距離 */
  --switch-translate: calc(var(--switch-width) - (var(--switch-border-width) * 2) - var(--switch-knob-size));
  /* --- 色の管理 --- */
  --switch-color-off: #ccc;
  --switch-color-on: #007bff;
  --switch-color-focus-outline: #007bff;
}

.form-switch label {
  cursor: pointer;
  user-select: none;
}

.form-switch input[type="checkbox"] {
  display: none;
}

.form-switch-items {
  display: grid;
  grid-template-columns: var(--switch-width) 1fr;
  gap: var(--switch-gap);
  align-items: center;
}

.form-switch-items .icon {
  display: block;
  width: 100%;
  box-sizing: border-box;
  text-align: left;
  line-height: 1;
  height: var(--switch-height);
  border: var(--switch-border-width) solid var(--switch-color-off);
  border-radius: 30px;
  transition: all var(--switch-transition-speed);
}

.form-switch-items .icon::before {
  content: "";
  display: block;
  width: var(--switch-knob-size);
  height: var(--switch-knob-size);
  border-radius: 50%;
  background: var(--switch-color-off);
  transition: all var(--switch-transition-speed);
}

/* ON */
.form-switch-tab:checked + .icon {
  border-color: var(--switch-color-on);
}

.form-switch-tab:checked + .icon::before {
  background: var(--switch-color-on);
  transform: translateX(var(--switch-translate));
}

/* Tabキーで操作した時の挙動用 */
.form-switch-t    ab:focus-visible + .icon {
  outline: 2px solid var(--switch-color-focus-outline);
  outline-offset: 2px;
}

動作の説明

HTMLは普通のチェックボックスですが、<label>で囲んでいるチェックボックスと共に<div class="icon"></div>と言う空のタグが混ざっています。 これが今回のスイッチのアイコンを表示する部分になります。

このスイッチアイコンだけがあればいいので、チェックボックス本体をdisplay:noneで消してしまいます。 チェックボックス自体が消えていても、関連付けされたlabelのお陰でONとOFFの制御を行うことが可能になっています。

アイコン部分の<div>でスイッチの外枠を作り、<div>::beforeで中で動くノブを作成します。これで余計なタグを付け加えずに2種類のオブジェクトを配置することができます。

これで、丸が左側に置かれたアイコンができたので、これからON・OFFでノブが動くようにアニメーションさせていきます。

チェックを入れたかどうかは先程説明したフォームの:checkedを使用します。
:checkedは、<input>本体にしか使えないので、CSS側でフォームに:checkedが入った場合にこの状態を<div class="icon">に伝える必要があります。

.form-switch-tab:checked + .iconと言った感じでCSSをで連結すると、「その要素の直後にこの要素があった時に適用される」と言う意味になります。

これを利用して<input>の直後に<div class="icon">を配置すれば、フォームの動作を<div class="icon">に伝えられる事になります。

これで設定は完了です。変化前と変化後のアニメーションは、transitionで簡単に設定できます。
このような感じで、スイッチのようなボタンを作成することができます。

こんな感じで色々とデザインに関して頑張っておりますので、なにかホームページ制作でお困りのことが有りましたら、パタパタワークスにご相談ください!

それでは!