下線アニメーション付きタブ切り替えを作る方法【HTML/CSS/JavaScript・サンプルコード付き】
タブ切り替え
2025.10.04
下線アニメーション付きタブ切り替えを作る方法
HTML・CSS・JavaScriptを使って、アクティブなタブの下線がスムーズに移動するタブ切り替えを作る方法を紹介します。このサンプルでは、タブをクリックするとインジケーターがアニメーションしながら移動し、対応するコンテンツへ切り替わります。また、キーボード操作にも対応しているため、操作性の高いナビゲーションUIを実装したい場合にも便利です。
コードについて
本記事のコードはサンプルコードです。ご利用前に必ず動作確認を行ってください。
免責事項
本コードの利用により発生した損害について、当サイトは一切の責任を負いません。
デモ
下線アニメーション付きタブ切り替え
アクティブなタブの下線がスムーズに移動します。
概要を表示するエリアです。タブをクリックすると下線が移動し、内容が切り替わります。
特徴を表示するエリアです。アクティブなタブの位置に合わせてインジケーターが移動します。
使い方を表示するエリアです。左右キー、Homeキー、Endキーでもタブを操作できます。
サポート情報を表示するエリアです。横スクロールできるタブバーにも対応しています。
コードをコピーして使おう!
<!DOCTYPE html>
<html lang="ja">
<head>
<!-- 文字コードを指定 -->
<meta charset="UTF-8">
<!-- スマホ表示に対応 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ページタイトル -->
<title>下線アニメーション付きタブ切り替え</title>
<!-- CSSファイルを読み込み -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- タブ全体を囲むエリア -->
<div class="animated-tab-underline_wrap">
<!-- タイトル -->
<div class="animated-tab-underline_title">
下線アニメーション付きタブ切り替え
</div>
<!-- 説明文 -->
<p class="animated-tab-underline_text">
アクティブなタブの下線がスムーズに移動します。
</p>
<!-- 横スクロール可能なタブエリア -->
<div class="animated-tab-underline_tabarea">
<!-- タブボタン一覧 -->
<div class="animated-tab-underline_tabs" role="tablist" aria-label="タブメニュー">
<button class="animated-tab-underline_tab is-active" type="button" role="tab" aria-selected="true" tabindex="0" data-tab="overview">
概要
</button>
<button class="animated-tab-underline_tab" type="button" role="tab" aria-selected="false" tabindex="-1" data-tab="feature">
特徴
</button>
<button class="animated-tab-underline_tab" type="button" role="tab" aria-selected="false" tabindex="-1" data-tab="usage">
使い方
</button>
<button class="animated-tab-underline_tab" type="button" role="tab" aria-selected="false" tabindex="-1" data-tab="support">
サポート
</button>
<!-- アクティブタブの下線 -->
<span class="animated-tab-underline_indicator" aria-hidden="true"></span>
</div>
</div>
<!-- 概要タブの内容 -->
<div class="animated-tab-underline_panel is-active" role="tabpanel" data-panel="overview">
概要を表示するエリアです。タブをクリックすると下線が移動し、内容が切り替わります。
</div>
<!-- 特徴タブの内容 -->
<div class="animated-tab-underline_panel" role="tabpanel" data-panel="feature">
特徴を表示するエリアです。アクティブなタブの位置に合わせてインジケーターが移動します。
</div>
<!-- 使い方タブの内容 -->
<div class="animated-tab-underline_panel" role="tabpanel" data-panel="usage">
使い方を表示するエリアです。左右キー、Homeキー、Endキーでもタブを操作できます。
</div>
<!-- サポートタブの内容 -->
<div class="animated-tab-underline_panel" role="tabpanel" data-panel="support">
サポート情報を表示するエリアです。横スクロールできるタブバーにも対応しています。
</div>
</div>
<!-- JavaScriptファイルを読み込み -->
<script src="script.js"></script>
</body>
</html>
/* ページ全体の設定 */
body{
margin:0;
font-family:sans-serif;
background:#ffffff;
}
/* タブ全体を囲むエリア */
.animated-tab-underline_wrap{
max-width:760px;
margin:40px auto;
padding:32px;
border:1px solid #e5e7eb;
border-radius:18px;
background:#f8fafc;
}
/* タイトル */
.animated-tab-underline_title{
font-size:22px;
font-weight:700;
margin-bottom:12px;
text-align:center;
}
/* 説明文 */
.animated-tab-underline_text{
margin-bottom:24px;
color:#4b5563;
text-align:center;
}
/* 横スクロール可能なタブエリア */
.animated-tab-underline_tabarea{
position:relative;
overflow-x:auto;
border-bottom:1px solid #d1d5db;
}
/* タブボタン一覧 */
.animated-tab-underline_tabs{
position:relative;
display:flex;
min-width:max-content;
}
/* タブボタン */
.animated-tab-underline_tab{
padding:14px 22px;
border:none;
background:transparent;
color:#4b5563;
font-weight:700;
cursor:pointer;
white-space:nowrap;
}
/* 選択中のタブボタン */
.animated-tab-underline_tab.is-active{
color:#0b6bff;
}
/* アクティブタブの下線 */
.animated-tab-underline_indicator{
position:absolute;
left:0;
bottom:0;
width:0;
height:3px;
border-radius:999px;
background:#0b6bff;
transition:left 0.3s ease,width 0.3s ease;
}
/* タブの内容 */
.animated-tab-underline_panel{
display:none;
margin-top:20px;
padding:24px;
border:1px solid #d1d5db;
border-radius:14px;
background:#ffffff;
color:#4b5563;
line-height:1.8;
}
/* 選択中のタブの内容 */
.animated-tab-underline_panel.is-active{
display:block;
}
// タブボタンをすべて取得
const animatedTabUnderlineTabs=document.querySelectorAll(".animated-tab-underline_tab");
// タブの内容をすべて取得
const animatedTabUnderlinePanels=document.querySelectorAll(".animated-tab-underline_panel");
// 横スクロールするタブエリアを取得
const animatedTabUnderlineTabArea=document.querySelector(".animated-tab-underline_tabarea");
// 下線インジケーターを取得
const animatedTabUnderlineIndicator=document.querySelector(".animated-tab-underline_indicator");
// アクティブタブの位置に下線を移動する処理
function moveAnimatedTabUnderlineIndicator(activeTab){
const tabRect=activeTab.getBoundingClientRect();
const areaRect=animatedTabUnderlineTabArea.getBoundingClientRect();
const left=tabRect.left-areaRect.left+animatedTabUnderlineTabArea.scrollLeft;
animatedTabUnderlineIndicator.style.left=left+"px";
animatedTabUnderlineIndicator.style.width=tabRect.width+"px";
}
// 指定したタブを表示する処理
function activateAnimatedTabUnderline(targetTab){
const target=targetTab.dataset.tab;
animatedTabUnderlineTabs.forEach(function(tab){
tab.classList.remove("is-active");
tab.setAttribute("aria-selected","false");
tab.setAttribute("tabindex","-1");
});
animatedTabUnderlinePanels.forEach(function(panel){
panel.classList.remove("is-active");
});
targetTab.classList.add("is-active");
targetTab.setAttribute("aria-selected","true");
targetTab.setAttribute("tabindex","0");
document.querySelector('[data-panel="'+target+'"]').classList.add("is-active");
moveAnimatedTabUnderlineIndicator(targetTab);
}
// 各タブボタンにクリックイベントとキーボード操作を設定
animatedTabUnderlineTabs.forEach(function(tab,index){
tab.addEventListener("click",function(){
activateAnimatedTabUnderline(tab);
});
tab.addEventListener("keydown",function(event){
let nextIndex=index;
if(event.key==="ArrowRight"){
nextIndex=index+1;
}
if(event.key==="ArrowLeft"){
nextIndex=index-1;
}
if(event.key==="Home"){
nextIndex=0;
}
if(event.key==="End"){
nextIndex=animatedTabUnderlineTabs.length-1;
}
if(nextIndex<0){
nextIndex=animatedTabUnderlineTabs.length-1;
}
if(nextIndex>=animatedTabUnderlineTabs.length){
nextIndex=0;
}
if(["ArrowRight","ArrowLeft","Home","End"].includes(event.key)){
event.preventDefault();
animatedTabUnderlineTabs[nextIndex].focus();
activateAnimatedTabUnderline(animatedTabUnderlineTabs[nextIndex]);
}
});
});
// 横スクロール時に下線位置を調整
animatedTabUnderlineTabArea.addEventListener("scroll",function(){
const activeTab=document.querySelector(".animated-tab-underline_tab.is-active");
moveAnimatedTabUnderlineIndicator(activeTab);
});
// 画面幅変更時に下線位置を調整
window.addEventListener("resize",function(){
const activeTab=document.querySelector(".animated-tab-underline_tab.is-active");
moveAnimatedTabUnderlineIndicator(activeTab);
});
// 初期表示時に下線位置を設定
moveAnimatedTabUnderlineIndicator(document.querySelector(".animated-tab-underline_tab.is-active"));
ファイル構成と設置方法
このサンプルでは、HTML・CSS・JavaScriptをそれぞれ別ファイルに分けて使用します。index.html、style.css、script.js を同じフォルダに配置してください。
sample/
├── index.html
├── style.css
└── script.js
index.html をブラウザで開くと、下線アニメーション付きタブ切り替えを確認できます。タブをクリックするとアクティブなタブの直下へインジケーターがスムーズに移動し、左右キー・Homeキー・Endキーによるキーボード操作や横スクロールにも対応しています。
下線アニメーション付きタブ切り替えを作る方法【HTML/CSS/JavaScript・サンプルコード付き】
コメント