# CSSのみのタブ切り替えのCSS実装

> radioボタンと:has()だけで作るタブUI。JSなしでパネルが切り替わり、キーボードの矢印キー操作もradio標準のまま使えます。

- カテゴリ: ナビゲーション
- URL: https://www.css-dictionary.com/recipes/css-tabs/

## HTML

```html
<div class="tabs">
  <input type="radio" name="tab" id="tab-a" checked>
  <label for="tab-a">概要</label>
  <input type="radio" name="tab" id="tab-b">
  <label for="tab-b">仕様</label>
  <input type="radio" name="tab" id="tab-c">
  <label for="tab-c">レビュー</label>

  <div class="panel panel-a">gapはFlexbox・Grid共通で使える余白プロパティです。</div>
  <div class="panel panel-b">値は1つ（全方向）または2つ（行・列）で指定します。</div>
  <div class="panel panel-c">「marginの相殺に悩まなくなった」と好評です。</div>
</div>
```

## CSS

```css
.tabs {
  width: 320px;
  border: 1px solid #e2d8c2;
  border-radius: 8px;
  background: #fff;
  overflow: hidden;
}

.tabs input {
  position: absolute;
  opacity: 0;
}

.tabs label {
  display: inline-block;
  padding: 10px 18px;
  font-size: 14px;
  color: #5c5445;
  cursor: pointer;
  border-bottom: 2px solid transparent;
}

.tabs .panel {
  display: none;
  padding: 16px;
  font-size: 13px;
  line-height: 1.7;
  border-top: 1px solid #e2d8c2;
}

/* :has()でコンテナから「どのタブが選択中か」を参照する */
.tabs:has(#tab-a:checked) label[for="tab-a"],
.tabs:has(#tab-b:checked) label[for="tab-b"],
.tabs:has(#tab-c:checked) label[for="tab-c"] {
  color: #b0413e;
  font-weight: 600;
  border-bottom-color: #b0413e;
}

.tabs:has(#tab-a:checked) .panel-a,
.tabs:has(#tab-b:checked) .panel-b,
.tabs:has(#tab-c:checked) .panel-c {
  display: block;
}

.tabs input:focus-visible + label {
  outline: 2px solid #b0413e;
  outline-offset: -2px;
}
```

## 仕組みの解説

タブの状態はradioボタンが持ちます。:has() が使える現在は「.tabs:has(#tab-a:checked) .panel-a」のように、コンテナ起点で選択中のタブに対応するパネルだけを display: block にできるため、旧来の「inputとpanelを兄弟に並べる」HTML構造の制約から自由になりました。radioなのでタブ間の移動は矢印キーがそのまま効きます。

## 実装のポイント

本格的なタブにはrole="tablist"とJSでのフォーカス管理が推奨されます（WAI-ARIA準拠）。この方式は設定画面など軽量な表示切り替え向けです。

## AIに依頼するときの文例

JSを使わないCSSのみのタブUIを作ってください。radioボタンで状態を持ち、:has()を使ってコンテナ起点で選択中のラベルの強調とパネルの表示を切り替えてください。フォーカスリングも付けてください。

## 使っているプロパティ

- [pseudo-has](https://www.css-dictionary.com/property/pseudo-has.md)
- [display](https://www.css-dictionary.com/property/display.md)
- [border](https://www.css-dictionary.com/property/border.md)
- [pseudo-focus-visible](https://www.css-dictionary.com/property/pseudo-focus-visible.md)

