こんにちは。KOUKIです。
本記事は、Udemyの「50 Projects In 50 Days – HTML, CSS & JavaScript」で学習したことを載せています。
<目次>
実装するもの
FAQアプリのToggleボタンの開閉処理を実装します。
demoは「こちら」で確認できます。
環境構築
簡単な環境構築をお願いします。
必要なファイルは、以下の通りです。
1 2 3 4 5 6 |
$ tree . ├── index.html ├── script.js └── style.css |
CSS版
開発
ページの作成
最初にページを作成しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" integrity="sha512-1PKOgIY59xJ8Co8+NE6FZ+LOAZKjy+KY8iq0G4B3CyeY6wYHN3yt9PW0XpSriVlkMXe40PTKnXrLnZ9+fkDaog==" crossorigin="anonymous" /> <link rel="stylesheet" href="style.css" /> <title>FAQ</title> </head> <body> <h1>Frequently Asked Questions</h1> <div class="faq-container"> <div class="faq active"> <h3 class="faq-title"> Why shouldn't we trust atoms? </h3> <p class="faq-text"> They make up everything </p> <button class="faq-toggle"> <i class="fas fa-chevron-down"></i> <i class="fas fa-times"></i> </button> </div> <div class="faq"> <h3 class="faq-title"> What do you call someone with no body and no nose? </h3> <p class="faq-text"> Nobody knows. </p> <button class="faq-toggle"> <i class="fas fa-chevron-down"></i> <i class="fas fa-times"></i> </button> </div> <div class="faq"> <h3 class="faq-title"> What's the object-oriented way to become wealthy? </h3> <p class="faq-text"> Inheritance. </p> <button class="faq-toggle"> <i class="fas fa-chevron-down"></i> <i class="fas fa-times"></i> </button> </div> <div class="faq"> <h3 class="faq-title"> How many tickles does it take to tickle an octopus? </h3> <p class="faq-text"> Ten-tickles! </p> <button class="faq-toggle"> <i class="fas fa-chevron-down"></i> <i class="fas fa-times"></i> </button> </div> <div class="faq"> <h3 class="faq-title"> What is: 1 + 1? </h3> <p class="faq-text"> Depends on who are you asking. </p> <button class="faq-toggle"> <i class="fas fa-chevron-down"></i> <i class="fas fa-times"></i> </button> </div> </div> <script src="script.js"></script> </body> </html> |
このHTMLをブラウザ上で表示すると以下のようになります。

スタイルの追加
次にスタイルを記述しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
@import url('https://fonts.googleapis.com/css?family=Muli&display=swap'); * { box-sizing: border-box; } body { font-family: 'Muli', sans-serif; background-color: #f0f0f0; } h1 { margin: 50px 0 30px; text-align: center; } .faq-container { max-width: 600px; margin: 0 auto; } .faq { background-color: transparent; border: 1px solid #9fa4a8; border-radius: 10px; margin: 20px 0; padding: 30px; position: relative; overflow: hidden; transition: 0.3s ease; } .faq.active { background-color: #fff; box-shadow: 0 3px 6px rgba(0, 0, 0, 0.1), 0 3px 6px rgba(0, 0, 0, 0.1); } .faq.active::before, .faq.active::after { content: '\f075'; font-family: 'Font Awesome 5 Free'; color: #2ecc71; font-size: 7rem; position: absolute; opacity: 0.2; top: 20px; left: 20px; z-index: 0; } .faq.active::before { color: #3498db; top: -10px; left: -30px; transform: rotateY(180deg); } .faq-title { margin: 0 35px 0 0; } .faq-text { display: none; margin: 30px 0 0; } .faq.active .faq-text { display: block; } .faq-toggle { background-color: transparent; border: 0; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 16px; padding: 0; position: absolute; top: 30px; right: 30px; height: 30px; width: 30px; } .faq-toggle:focus { outline: 0; } .faq-toggle .fa-times { display: none; } .faq.active .faq-toggle .fa-times { color: #fff; display: block; } .faq.active .faq-toggle .fa-chevron-down { display: none; } .faq.active .faq-toggle { background-color: #9fa4a8; } |
ここまで実装すると以下のようになります。

Toggleボタンは、「Font Awesome」を使っています。
また、背景のコメントバルーンは、ユニコード「\f075」で表現しています。これもFont Awesomeから提供されています。

JavaScriptの実装
Toggleボタンによるカードの開閉は、「active」クラスを「feq」クラスが付与されているHTML要素に追加することで表現します。
1 |
<div class="faq active"> <<< ここにactiveをつける |
要素を取得する
JavaScriptで制御すべき要素が1つあります。最初にこの要素を取得しましょう。
1 2 |
// 要素を取得する const toggles = document.querySelectorAll('.faq-toggle') |
ページ上の全てのtoggle要素を取得しました。この要素は、配列形式で格納されます。
クリックイベントの登録
続いて、クリックイベントを登録しましょう。対象は、全てのtoggle要素です。
1 2 3 4 5 6 7 |
// 取得したtoggle要素をループで回す toggles.forEach(toggle => { // クリックイベントを登録 toggle.addEventListener('click', () => { }) }) |
forEachは、配列内の要素をループして処理してくれる便利なメソッドで、パラメータのtoggleは、toggles(配列)に格納されている要素です。「toggle」という名前にしましたが、これは任意の名前です。しかし、toggles -> toggle(配列から取り出した要素)であることが明確になるので、こういった書き方の方が良いと思います。
他の言語でも似たような実装をしますね。
1 2 3 4 5 6 7 8 |
// python for toggle in toggle_list: print(task) // golang for _, toggle := range toggles { fmt.Println(toggle) } |
parentNodeで親要素にアクセス
HTML上では、取得したtoggle要素は次の場所にあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<body> <h1>Frequently Asked Questions</h1> <div class="faq-container"> <div class="faq"> <h3 class="faq-title">...</h3> <p class="faq-text">...</p> <button class="faq-toggle"> <<<< ここの要素を取得している <i class="fas fa-chevron-down"></i> <i class="fas fa-times"></i> </button> </div> .... </div> <script src="script.js"></script> </body> |
カードを開閉するためには、toggle要素の親である
にアクセスする必要があります。
claass="faq"><div
それを可能にするものが、「parentNode」プロパティです。このプロパティを経由して、activeクラスを付与します。
1 2 3 4 5 6 7 |
toggles.forEach(toggle => { toggle.addEventListener('click', () => { // 親要素へactiveクラスを付与する toggle.parentNode.classList.toggle('active') }) }) |
classListのtoggleは、activeクラスが付与されている場合は除去し、そうでない場合は付与します。かなり便利なメソッドです。
これで完成です。
おわりに
Toggleボタン系の処理も現場ではよく実装しますね。Bootstrapを使うのもありだと思いますが、結構簡単に実装できるので(CSSは難しいが)、パパッと作れると思います。
それでは、また!
JavaScriptまとめ
JavaScript ソースコード
1 2 3 4 5 6 7 8 9 10 11 |
// 要素を取得する const toggles = document.querySelectorAll('.faq-toggle') // 取得したtoggle要素をループで回す toggles.forEach(toggle => { // クリックイベントを登録 toggle.addEventListener('click', () => { // 親要素へactiveクラスを付与する toggle.parentNode.classList.toggle('active') }) }) |
コメントを残す
コメントを投稿するにはログインしてください。