テック技報最新号へ →
CSS

CSS 製トグルの元 checkbox は display: none ではなく opacity: 0 で隠し、:focus-visible でリングを描く

見た目を自作するために <input type="checkbox"> を display: none にするとフォーカスごと消えて Tab キーやスクリーンリーダーから操作できなくなるので、opacity: 0 で見えなくするだけにして、フォーカス時のリングは自作の見た目側に描く。

@iutech_jp · 2026-10-20
#アクセシビリティ#フォーム#チェックボックス#トグル#focus-visible

どんな時に使う?

  • チェックボックスやラジオボタンを、トグルスイッチ・カード型の選択肢など独自の見た目に作り替える時
  • 既存サイトで「トグルが Tab で選べない」「Space で切り替わらない」と指摘された時
  • AI に生成させたトグルのコードをレビューする時(display: none で隠しているコードは多い)

コード

html
<label class="toggle">
  <input type="checkbox" class="toggle__input">
  <span class="toggle__track" aria-hidden="true"></span>
  通知を受け取る
</label>
css
.toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
}

/* 元の checkbox は見えなくするだけ。存在とフォーカスは残す */
.toggle__input {
  position: absolute;
  inset: 0;          /* ラベル全体に重ねてクリックも受けられるように */
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.toggle__track {
  width: 2.5em;
  height: 1.4em;
  border-radius: 999px;
  background: #ccc;
}

.toggle__input:checked + .toggle__track {
  background: #1a7f37;
}

/* キーボード操作の時だけフォーカスリングを見た目側に描く */
.toggle__input:focus-visible + .toggle__track {
  outline: 2px solid #1a7f37;
  outline-offset: 2px;
}
  • display: none や visibility: hidden はフォーカス対象からもアクセシビリティツリーからも外れる。opacity: 0 なら要素は残るので、Tab で選んで Space で切り替えられ、スクリーンリーダーにも「チェックボックス」として読まれる。
  • 元の input は見えないので、フォーカスリングは隣の見た目要素に :focus-visible + .track で描く。:focus ではなく :focus-visible にすると、マウスクリック時にはリングが出ない。

注意点・対応状況

  • opacity: 0 の input がレイアウトの邪魔になる場合は、いわゆる「visually-hidden」パターン(clip-path: inset(50%) と 1px サイズなど)で隠してもよい。どちらも「フォーカスできる状態のまま見えなくする」点が要点。
  • appearance: none で checkbox 自体の見た目を消して、その input に直接スタイルを当てる方法もある(隠す必要が無くなる)。
  • 状態をスクリーンリーダーに「オン/オフ」と読ませたい場合は role="switch" を付ける。
  • 元の投稿はトグル生成ツールの紹介を兼ねた図解カード。上のコードは図解の「原因・直し方」から組み立て直したもの。

出典

X の元の投稿を開く