アコーディオンは、見出しをクリックすることで隠れている内容を表示・非表示にできるUIです。一般的なアコーディオンでは内容が瞬時に切り替わりますが、スライドアニメーションを加えると、表示領域が上下に滑らかに伸縮しながら開閉します。急に内容が現れたり消えたりしないため、画面の変化を自然に見せることができます。
今回紹介するのは、内容がスッとスライドして開閉するアコーディオンです。見出しをクリックすると内容が上から下へ広がり、もう一度クリックすると下から上へ縮みながら閉じます。開閉時間は600ms(0.6秒)に設定し、フェードによる透明度の変化は加えず、高さの変化だけで動きを表現しています。
スライドアニメーションは、CSSのgrid-template-rowsとtransitionを組み合わせて実装します。JavaScriptではクリックした項目の開閉状態を切り替えるだけなので、複雑な高さの計算は必要ありません。また、複数の項目を同時に開くことができ、それぞれ独立して開閉できます。
この記事では、HTML・CSS・JavaScriptを使って、スライドアニメーション付きアコーディオンを作る方法を紹介します。実際のデモで開閉の動きを確認しながら、アニメーションの仕組みや開閉速度の調整方法を解説します。
デモ
Q 他のアイコンを使いたい場合はどうするの?
無料のSVGアイコン作成ツールを使って、用途に合ったアイコンを作成できます。
コードをコピーして使おう!
<!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">
<!-- JavaScriptファイル -->
<script src="script.js" defer></script>
</head>
<body>
<!-- アコーディオン全体 -->
<div class="slide-accordion_wrap">
<!-- 1つ目の項目 -->
<div class="slide-accordion_item">
<!-- 開閉ボタン -->
<button class="slide-accordion_button" type="button" aria-expanded="false">
<!-- 見出し -->
<span class="slide-accordion_label">アコーディオンとは?</span>
<!-- 開閉アイコン -->
<span class="slide-accordion_icon" aria-hidden="true">
<!-- 閉じているときのプラスアイコン -->
<span class="slide-accordion_icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<!-- 開いているときのマイナスアイコン -->
<span class="slide-accordion_icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<!-- 開閉する内容 -->
<div class="slide-accordion_content">
<div class="slide-accordion_content-inner">アコーディオンは、見出しをクリックして内容の表示・非表示を切り替えられるUIです。</div>
</div>
</div>
<!-- 2つ目の項目 -->
<div class="slide-accordion_item">
<!-- 開閉ボタン -->
<button class="slide-accordion_button" type="button" aria-expanded="false">
<!-- 見出し -->
<span class="slide-accordion_label">スライド開閉の特徴は?</span>
<!-- 開閉アイコン -->
<span class="slide-accordion_icon" aria-hidden="true">
<!-- 閉じているときのプラスアイコン -->
<span class="slide-accordion_icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<!-- 開いているときのマイナスアイコン -->
<span class="slide-accordion_icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<!-- 開閉する内容 -->
<div class="slide-accordion_content">
<div class="slide-accordion_content-inner">内容の表示領域が上下に滑らかに伸縮します。フェードを使わず、高さの変化だけで自然な開閉を表現しています。</div>
</div>
</div>
<!-- 3つ目の項目 -->
<div class="slide-accordion_item">
<!-- 開閉ボタン -->
<button class="slide-accordion_button" type="button" aria-expanded="false">
<!-- 見出し -->
<span class="slide-accordion_label">開閉速度は変更できる?</span>
<!-- 開閉アイコン -->
<span class="slide-accordion_icon" aria-hidden="true">
<!-- 閉じているときのプラスアイコン -->
<span class="slide-accordion_icon-closed">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 4v16 M4 12h16"/>
</svg>
</span>
<!-- 開いているときのマイナスアイコン -->
<span class="slide-accordion_icon-open">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 12h16"/>
</svg>
</span>
</span>
</button>
<!-- 開閉する内容 -->
<div class="slide-accordion_content">
<div class="slide-accordion_content-inner">CSSのtransitionで指定している600msを変更すると、開閉速度を調整できます。数値を小さくすると速く、大きくするとゆっくり動きます。</div>
</div>
</div>
</div>
</body>
</html>
コードをコピーする場合 使用するコードのタブを選び、「このタブをコピー」をクリックすると、現在表示中のコードをコピーできます。 サンプル一式を取得する場合 HTML・CSSなどすべてのファイルが必要な場合は、「サンプル一式をダウンロード」をクリックしてください。
Q ダウンロードしたけど、これをネット上で動かすにはどうするの?
Googleアカウントがあれば、InfinityFreeで無料サーバーを作成して、ダウンロードしたサンプルをネット上で動かせます。
InfinityFreeを初めて利用する場合は①から、すでにサーバーを作成している場合は②へ進んでください。
ファイル構成と設置方法
スライドアコーディオンのサンプルは、HTML・CSS・JavaScriptの3つのファイルで構成されています。HTMLに3つの開閉項目とプラス・マイナスのSVGアイコンを配置し、CSSで表示デザインとスライドアニメーションを設定しています。JavaScriptはクリックされた項目の開閉状態を切り替える役割を持ち、複数の項目をそれぞれ独立して操作できる仕組みです。
sample/
├── index.html
├── style.css
└── script.js
各ファイルの役割
index.htmlには、アコーディオンの見出し、開閉する文章、プラス・マイナスのSVGアイコンを記述しています。style.cssでは、各項目の枠線や余白、文字色に加え、grid-template-rowsを使った開閉アニメーションを設定しています。script.jsでは、クリックされた項目にis-openクラスを付け外しし、開閉状態を管理しています。
設置方法・使い方
「サンプル一式をダウンロード」からZIPファイルをダウンロードして展開します。展開したindex.html・style.css・script.jsを同じフォルダに配置し、ブラウザでindex.htmlを開くとアコーディオンが表示されます。見出しをクリックすると内容が下方向へスライドして開き、もう一度クリックすると上方向へ縮みながら閉じます。ほかの項目を開いても、すでに開いている項目は閉じず、複数の内容を同時に表示できます。
高さを変化させてスライド開閉する仕組み
スライドアニメーションは、style.cssのgrid-template-rowsで実現しています。閉じているときは0frで内容の表示領域を縮め、開いたときは1frに変更して内容の高さまで広げます。transitionを指定することで、この高さの変化が瞬時に切り替わらず、滑らかな動きになります。
/* 開閉する内容 */
.slide-accordion_content {
display: grid; /* 高さをアニメーションさせるためにグリッドを使用 */
grid-template-rows: 0fr; /* 初期状態では内容を閉じる */
transition: grid-template-rows 600ms cubic-bezier(0.4, 0, 0.2, 1); /* 開閉時間600ms。値を小さくすると速く、大きくすると遅くなる */
background: #ffffff; /* 内容の背景色 */
color: #4b5563; /* 内容の文字色 */
font-size: 16px; /* 内容の文字サイズ */
font-weight: 400; /* 内容の文字の太さ */
line-height: 1.8; /* 内容の行間 */
}
/* 開いたときの高さ */
.slide-accordion_item.is-open .slide-accordion_content {
grid-template-rows: 1fr; /* 内容の高さに合わせて広げる */
}
このコードでは、内容の高さをJavaScriptで計算する必要がありません。文章の長さに合わせて表示領域が広がるため、各項目の文章量が異なっていても同じ仕組みで開閉できます。また、透明度を変更するopacityは使用していないため、フェードせずに高さだけが変化します。
クリックした項目だけを開閉する仕組み
script.jsでは、各ボタンにクリックイベントを設定しています。クリックされたボタンの親要素を取得し、その項目のis-openクラスだけを切り替えます。
/* クリックしたボタンの親項目を取得 */
const item = button.parentElement;
/* クリックした項目だけを開閉する */
item.classList.toggle("is-open");
/* 開閉状態をアクセシビリティ属性へ反映 */
button.setAttribute(
"aria-expanded",
item.classList.contains("is-open") ? "true" : "false"
);
classList.toggle("is-open")は、クラスが付いていなければ追加し、付いていれば削除する処理です。このクラスの有無によってCSSの開閉設定が切り替わります。ほかの項目のクラスは変更しないため、複数のアコーディオンを同時に開いたままにできます。aria-expandedも開閉状態に合わせて更新し、ボタンが開いているか閉じているかを支援技術へ伝えます。
カスタマイズできる内容
見出しや開閉する文章は、index.htmlのslide-accordion_labelとslide-accordion_content-innerを書き換えることで変更できます。項目を増やしたい場合は、slide-accordion_item全体を複製して文章を変更します。JavaScriptは各ボタンをまとめて取得しているため、項目を追加するたびにクリック処理を書き足す必要はありません。
枠線や角丸、文字色などのデザインはstyle.cssで変更できます。slide-accordion_itemのborderやborder-radiusを変更すると項目の外観が変わり、slide-accordion_iconのcolorを変更するとプラス・マイナスアイコンの色を調整できます。
数値調整
開閉速度は、style.cssのslide-accordion_contentにあるtransition: grid-template-rows 600ms cubic-bezier(0.4, 0, 0.2, 1);で調整できます。600msは0.6秒を表し、300msにすると速く、900msにするとゆっくり開閉します。開くときと閉じるときの両方に同じ時間が適用されます。
全体の最大横幅はslide-accordion_wrapのmax-width: 700px;で設定しています。値を大きくすると横に広がり、小さくするとコンパクトになります。また、slide-accordion_itemのmargin: 0 0 12px;を変更すると、各項目の上下間隔を調整できます。
レスポンシブ対応
style.cssでは、アコーディオン全体をwidth: 100%;とmax-width: 700px;で設定し、画面幅に合わせて縮小できるようにしています。さらに、画面幅が640px以下になるとメディアクエリが適用され、見出しとアイコンの間隔が16pxから12pxに変わります。長い見出しは折り返され、アイコンは縮小されないため、スマートフォンでも開閉ボタンを操作できます。
コメント