はじめに
タイトルについて記事にしました。
この記事で得る内容は以下の通りです。
・ CSSの基礎知識が増える
・ アコーディオンメニューの作り方について
例
例えば、こんな画面があったとします
手順
*説明に必要な所だけ記述しています
① アコーディオンメニューをクリックしたら、表示する場所を予め記述します
→ 今回、アコーディオンメニューが%a
だとすると、.answer
配下の%p fuga
.wrapper
.wrapper__text
%i.far.fa-envelope-open
%h2 よくある質問
.wrapper__question
%a
%i.far.fa-question-circle
%p hoge?
.answer
%p fuga
② ①で記述した要素をアコーディオンメニュークリック後に表示させたいので、display: none;
で隠しておきます
.answer {
display: none;
}
③ アコーディオンメニューをクリックしたら.activeクラスをつけると想定して、display: block;
を指定します
.answer.active {
display: block;
}
④ hamlにJavaScriptファイルを読み込む記述と、accordion.jsファイルを新規作成します
= javascript_pack_tag 'accordion'
⑤ accordion.jsに処理を記述します
const accordionMenu = document.querySelectorAll(".wrapper__question > a"); // アコーディオンメニュー発火部分をCSSのセレクタで要素を取得する変数
for (let i = 0; i < accordionMenu.length; i++) { // querySelectcorAllで要素を配列で取得して、変数"accordionMenu"の数だけ処理をfor文で繰り返す
accordionMenu[i].addEventListener("click", function () {
this.nextElementSibling.classList.toggle("active"); // イベントが起こっている要素の次のクラスを切り替える
});
}
⑥ %a
タグにhref
属性があり、クリック後にページがリロードしてしまう場合は、以下のように記述します
const accordionMenu = document.querySelectorAll(".wrapper__question > a");
for (let i = 0; i < accordionMenu.length; i++) {
accordionMenu[i].addEventListener("click", function (e) { // ファンクションに引数"e"(名前は自由)を持たせタグのイベントを取得する
e.preventDefault(); // hrefのイベントをキャンセルする
this.nextElementSibling.classList.toggle("active");
});
}
アコーディオンメニューの機能自体はこれで完成していますが、右端の矢印を回転させる処理を記述します
⑦ accordion.js及び、index.scssを以下のように記述します
const accordionMenu = document.querySelectorAll(".wrapper__question > a");
for (let i = 0; i < accordionMenu.length; i++) {
accordionMenu[i].addEventListener("click", function () {
this.classList.toggle("active"); // クリックした要素(a)自体に"active"クラスを切り替える
this.nextElementSibling.classList.toggle("active");
});
}
a.active::after {
transform: rotate(180deg);
}
これでアコーディオンメニューをクリックしたら、矢印がクルクル回転する様になりました
参考(今回のコード)
.wrapper
.wrapper__text
%i.far.fa-envelope-open
%h2 よくある質問
.wrapper__question
%a
%i.far.fa-question-circle
%p hoge?
.answer
%p fuga
= javascript_pack_tag 'accordion'
.wrapper {
text-align: center;
padding: 4rem 0;
letter-spacing: 2px;
&__text {
i {
font-size: 1.5rem;
margin-right: -5px;
vertical-align: 3px;
}
h2 {
font-size: 1.75rem;
font-weight: bold;
display: inline-block;
}
}
&__question {
display: flex;
flex-direction: column;
align-items: center;
padding-top: 3rem;
a {
font-size: 1.25rem;
font-weight: bold;
border: 1px solid #ddd;
padding: 1rem 1.5rem;
width: 70%;
margin-bottom: 0.3rem;
text-align: left;
i {
color: #016ea9;
margin-right: -10px;
}
p {
display: inline-block;
}
}
a::after {
content: "\02228";
color: #ccc;
float: right;
}
a:hover > p {
text-decoration: underline;
}
.answer {
width: 70%;
text-align: left;
padding: 1rem 1rem 2rem;
display: none;
p {
font-weight: bold;
color: #333;
}
}
.answer.active {
display: block;
}
a.active::after {
transform: rotate(180deg);
}
}
}
const accordionMenu = document.querySelectorAll(".wrapper__question > a");
for (let i = 0; i < accordionMenu.length; i++) {
accordionMenu[i].addEventListener("click", function () {
this.classList.toggle("active");
this.nextElementSibling.classList.toggle("active");
});
}