今回はアコーディオンのコードを「htmlのみ」「js使用」「Vue使用」の3通りほど記録しておきたいと思います。
実はアコーディオンについて色々な記事を拝見してみたのですが、「アコーディオンってその簡単な見た目とは裏腹に意外とコーディングが大変」という声をいくつか目にしました。
簡単にこの機能を実装するだけであれば今回1つ目に書かせていただくhtmlのみのコードがありますが、見た目や動きにこだわろうとするほど確かに大変だなと今回やってみて思いましたね。
また、2つ目はjs使用版、3つ目にVue使用版を書いていますが、こちらも見づらい余計な装飾は省いて出来るだけシンプルなコードにしています。
1、htmlのみの簡易アコーディオン
まず1つ目はhtmlのみ。details、summaryタグを使用した最もシンプルなコードです。一応最後にCSSでリストの点を消したりなど最低限の見た目だけ整えていますが、このCSSはなくとも動きます。
<body>
<ul>
<li>
<details>
<summary>質問1: アコーディオンとは何ですか?</summary>
<p>回答1: クリックで開閉する仕組みのことです。</p>
</details>
</li>
<li>
<details>
<summary>質問2: JavaScriptは必要ですか?</summary>
<p>回答2: いいえ、HTMLだけで動きます。</p>
</details>
</li>
<li>
<details>
<summary>質問3: HTMLとCSSだけでどこまでできますか?</summary>
<p>回答3: HTMLとCSSでスムーズな開閉アニメーションまで作ることができます。</p>
</details>
</li>
</ul>
<script src="〇〇.js"></script>
</body>
(下記cssはなくても動きます。)
li {
list-style-type: none;
padding: 10px 0;
}
summary, p {
padding: 10px;
margin: 0 auto;
border: 1px solid #000;
width: 300px;
}
2、jsを使ったアコーディオン
次にjavascriptを使ったアコーディオンです。こちらも三項演算子でできる限りシンプルな形で書いています。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>js式アコーディオン</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="accordion">
<div class="item">
<button class="question">質問1: アコーディオンとは何ですか?<span>+</span></button>
<div class="answer"><p>回答1: クリックで開閉する仕組みのことです。</p></div>
</div>
<div class="item">
<button class="question">質問2: JavaScriptは必要ですか?<span>+</span></button>
<div class="answer"><p>回答2: いいえ、HTMLだけで動きます。</p></div>
</div>
<div class="item">
<button class="question">質問3: HTMLとCSSだけでどこまでできますか?<span>+</span></button>
<div class="answer"><p>回答3: HTMLとCSSでスムーズな開閉アニメーションまで作ることができます。</p></div>
</div>
</div>
<script src="slider.js"></script>
</body>
</html>
@charset "utf-8";
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 50px;
font-family: sans-serif;
}
.accordion {
width: 600px;
margin: 0 auto;
}
.item {
border-bottom: 1px solid #ccc;
}
.question {
width: 100%;
padding: 20px 10px;
border: none;
background: none;
text-align: left;
font-size: 16px;
cursor: pointer;
display: flex;
justify-content: space-between;
}
.question span {
font-size: 20px;
}
.answer {
display: none;
padding: 0 10px 20px;
}
.answer p {
margin: 0;
}
const questions = document.querySelectorAll(".question");
questions.forEach((question) => {
question.addEventListener("click", (e) => {
const btn = e.currentTarget;
const answer = btn.nextElementSibling;
const isOpen = answer.style.display === "block";
answer.style.display = isOpen ? "none" : "block";
btn.querySelector("span").textContent = isOpen ? "+" : "-";
});
});
3、Vueを使ったアコーディオン
最後にVue(2)を使ったアコーディオンです。こちらもシンプルさを優先し、isOpenでフラグだけ立たせて状態管理しているものです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Vue2アコーディオン サンプル</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- ヘッダーをクリックすると、isOpenの値がtrue/falseで反転する -->
<div id="app">
<div class="accordion">
<div class="accordion-header" @click="isOpen=!isOpen">
<span>質問1: アコーディオンとは何ですか?</span>
<span>{{ isOpen ? '▲' : '▼' }}</span>
</div>
<!-- Vueのtransitionタグで包むことで、CSSアニメーションを適用する -->
<transition name="fade">
<div class="accordion-body" v-show="isOpen">
<p>回答1: クリックで開閉する仕組みのことです。</p>
</div>
</transition>
</div>
</div>
<script src="aco.js"></script>
</body>
</html>
@charset "utf-8";
#app {
font-family: sans-serif;
max-width: 400px;
margin: 50px auto;
}
.accordion-header {
background-color: #f1f1f1;
padding: 15px;
cursor: pointer;
display: flex;
justify-content: space-between;
border: 1px solid #ccc;
user-select: none;
}
.accordion-body {
border: 1px solid #ccc;
border-top: none;
padding: 15px;
background-color: #fff;
}
/* アニメーション用のCSS(Vueのtransitionと連動) */
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s ease, transform 0.3s ease;
}
.fade-enter, .fade-leave-to {
opacity: 0;
transform: translateY(-10px);
}
// Vueインスタンス。初期状態はfalse(閉じている)
new Vue({
el: '#app',
data: {
isOpen: false
}
});
htmlとcssだけでもっと良いアニメーションアコーディオンが作れるようですが、今回はここまでにしておきたいと思います。
それではご覧いただきありがとうございました。