2026年5月20日
2026年5月20日
WordPressでタブ切り替えコンテンツを実装する方法
はじめに
タブ切り替えUIは、限られたスペースに複数のコンテンツを整理して表示できるUIパターンです。スペック比較・FAQ・カテゴリ別コンテンツの表示に適しています。
症状・原因
- タブで切り替わるコンテンツを実装したい
- ショートコードでタブをエディタから追加したい
- URLのハッシュでタブを指定して開きたい
- アクセシビリティに対応したタブにしたい
解決手順
ステップ1:タブのCSS
/* style.css */
.tab-wrapper {
margin: 24px 0;
}
.tab-list {
display: flex;
gap: 0;
border-bottom: 2px solid #c3c4c7;
list-style: none;
padding: 0;
margin: 0;
overflow-x: auto;
}
.tab-button {
padding: 10px 20px;
border: none;
border-bottom: 2px solid transparent;
background: none;
cursor: pointer;
font-size: 14px;
color: #50575e;
white-space: nowrap;
margin-bottom: -2px;
transition: color 0.2s, border-color 0.2s;
}
.tab-button[aria-selected="true"] {
color: #2271b1;
border-bottom-color: #2271b1;
font-weight: 600;
}
.tab-button:hover {
color: #2271b1;
}
.tab-panel {
padding: 20px 0;
display: none;
}
.tab-panel.is-active {
display: block;
}
ステップ2:JavaScriptでタブ切り替え
// js/tab.js
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.tab-wrapper').forEach(function(wrapper) {
const buttons = wrapper.querySelectorAll('.tab-button');
const panels = wrapper.querySelectorAll('.tab-panel');
function activateTab(index) {
buttons.forEach(function(btn, i) {
const isActive = i === index;
btn.setAttribute('aria-selected', isActive ? 'true' : 'false');
btn.setAttribute('tabindex', isActive ? '0' : '-1');
});
panels.forEach(function(panel, i) {
panel.classList.toggle('is-active', i === index);
panel.setAttribute('hidden', i === index ? null : 'hidden');
});
}
buttons.forEach(function(btn, index) {
btn.addEventListener('click', function() {
activateTab(index);
// URLハッシュを更新
const hash = btn.getAttribute('data-tab-hash');
if (hash) history.replaceState(null, '', '#' + hash);
});
// キーボード操作(左右矢印キー)
btn.addEventListener('keydown', function(e) {
if (e.key === 'ArrowRight') {
activateTab((index + 1) % buttons.length);
buttons[(index + 1) % buttons.length].focus();
}
if (e.key === 'ArrowLeft') {
activateTab((index - 1 + buttons.length) % buttons.length);
buttons[(index - 1 + buttons.length) % buttons.length].focus();
}
});
});
// URLハッシュで初期タブを指定
const hash = location.hash.replace('#', '');
if (hash) {
const target = wrapper.querySelector(`[data-tab-hash="${hash}"]`);
if (target) {
const idx = Array.from(buttons).indexOf(target);
if (idx >= 0) activateTab(idx);
}
}
});
});
ステップ3:ショートコードで実装
// functions.php
add_shortcode('tabs', function(array $atts, ?string $content = null): string {
$id = 'tabs-' . wp_rand(1000, 9999);
return '<div class="tab-wrapper" id="' . esc_attr($id) . '">'
. do_shortcode($content ?? '')
. '</div>';
});
add_shortcode('tab', function(array $atts, ?string $content = null): string {
$atts = shortcode_atts(['title' => 'タブ', 'hash' => ''], $atts, 'tab');
static $index = 0;
$title = esc_html($atts['title']);
$hash = sanitize_title($atts['hash'] ?: $atts['title']);
$btn_id = 'tab-btn-' . (++$index);
$pnl_id = 'tab-pnl-' . $index;
return '<button class="tab-button" role="tab" id="' . $btn_id . '"
aria-controls="' . $pnl_id . '" aria-selected="false"
tabindex="-1" data-tab-hash="' . esc_attr($hash) . '">'
. $title . '</button>'
. '<div class="tab-panel" role="tabpanel" id="' . $pnl_id . '"
aria-labelledby="' . $btn_id . '" hidden>'
. wp_kses_post(do_shortcode($content ?? ''))
. '</div>';
});
使用例(投稿エディタで):
[tabs]
[tab title="概要" hash="overview"]概要の内容[/tab]
[tab title="機能" hash="features"]機能の内容[/tab]
[tab title="料金" hash="price"]料金の内容[/tab]
[/tabs]
ステップ4:スクリプトのエンキュー
// functions.php
add_action('wp_enqueue_scripts', function(): void {
wp_enqueue_script(
'tab-content',
get_template_directory_uri() . '/js/tab.js',
[],
filemtime(get_template_directory() . '/js/tab.js'),
true
);
});
注意事項
role="tablist"・role="tab"・role="tabpanel"のARIA属性を正確に設定してください。スクリーンリーダーがタブUIとして認識します- タブボタンにはキーボード操作(左右矢印キー)を実装してください。WAI-ARIAのタブパターンの要件です
- ショートコードの
static $indexはリクエスト内でのみ有効です。同じページに複数のタブがある場合でも一意のIDを保証します
まとめ
タブUIは role="tab" + aria-selected + 矢印キー対応で実装します。CSSは .tab-button[aria-selected="true"] でアクティブスタイルを定義し、パネルは .is-active クラスで表示切り替えします。URLハッシュ連動で直リンクから特定タブを開くことができます。