質問するログイン新規登録
SCSS

SCSSは、SassのCSSメタ言語です。Webページのスタイルを指定するCSSを効率的に記述することができます。ネストと呼ばれる入れ子構造で記述するため、CSSの全体の記述量を減らせる点が特徴です。さらに変数も利用できるため、変更や修正の際に少ない作業量で対応することもできます。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

780閲覧

アコーディオンメニューでアイコンの↑を上向きや下向きに動かす際、矢印の棒部分と矢印の先端部分が一瞬離れて回転してしまう。

spn

総合スコア42

SCSS

SCSSは、SassのCSSメタ言語です。Webページのスタイルを指定するCSSを効率的に記述することができます。ネストと呼ばれる入れ子構造で記述するため、CSSの全体の記述量を減らせる点が特徴です。さらに変数も利用できるため、変更や修正の際に少ない作業量で対応することもできます。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2023/07/12 12:56

0

0

実現したいこと

2点あります。
1.アコーディオンメニューでアイコンの↑を上向きや下向きに動かす際、矢印の棒部分と矢印の先端部分が一瞬離れて回転してしまう。
2.タイトル部分を押すとアコーディオンのコンテンツ部分が出てこない。
(ボタン内のその他の部分を押すと出てくる。)

初歩的な問題で恐縮ですが、ご教示いただけますと幸いです。
宜しくお願い致します。

該当のソースコード

HTML

1 <dl class="accordion js-accordion"> 2 <div class="accordion__item js-accordion-trigger"> 3 <dt class="accordion__title"> 4 <span>question 5 <br>質問が入ります。</span> 6 <span class="arrow"></span><!-- /.arrow --> 7 </dt> 8 <dd class="accordion__content"> 9実現したいこと 102点あります。 111.アコーディオンメニューでアイコンの↑を上向きや下向きに動かす際、矢印の棒部分と矢印の先端部分が一瞬離れて回転してしまう。 122.タイトル部分を押すとアコーディオンのコンテンツ部分が出てこない。 13(ボタン内のその他の部分を押すと出てくる。) 14 </dd> 15 </div> 16 </dl>

javasprict

1/* =================================================== */ 2// slideUp, slideDown, slideToggle関数を定義 3/* =================================================== */ 4 5// 要素をスライドしながら非表示にする関数(jQueryのslideUpと同じ) 6const slideUp = (el, duration = 300) => { 7 el.style.height = el.offsetHeight + "px"; 8 el.offsetHeight; 9 el.style.transitionProperty = "height, margin, padding"; 10 el.style.transitionDuration = duration + "ms"; 11 el.style.transitionTimingFunction = "ease"; 12 el.style.overflow = "hidden"; 13 el.style.height = 0; 14 el.style.paddingTop = 0; 15 el.style.paddingBottom = 0; 16 el.style.marginTop = 0; 17 el.style.marginBottom = 0; 18 setTimeout(() => { 19 el.style.display = "none"; 20 el.style.removeProperty("height"); 21 el.style.removeProperty("padding-top"); 22 el.style.removeProperty("padding-bottom"); 23 el.style.removeProperty("margin-top"); 24 el.style.removeProperty("margin-bottom"); 25 el.style.removeProperty("overflow"); 26 el.style.removeProperty("transition-duration"); 27 el.style.removeProperty("transition-property"); 28 el.style.removeProperty("transition-timing-function"); 29 el.classList.remove("is-open"); 30 }, duration); 31}; 32 33 34// 要素をスライドしながら表示する関数(jQueryのslideDownと同じ) 35const slideDown = (el, duration = 300) => { 36 el.classList.add("is-open"); 37 el.style.removeProperty("display"); 38 let display = window.getComputedStyle(el).display; 39 if (display === "none") { 40 display = "block"; 41 } 42 el.style.display = display; 43 let height = el.offsetHeight; 44 el.style.overflow = "hidden"; 45 el.style.height = 0; 46 el.style.paddingTop = 0; 47 el.style.paddingBottom = 0; 48 el.style.marginTop = 0; 49 el.style.marginBottom = 0; 50 el.offsetHeight; 51 el.style.transitionProperty = "height, margin, padding"; 52 el.style.transitionDuration = duration + "ms"; 53 el.style.transitionTimingFunction = "ease"; 54 el.style.height = height + "px"; 55 el.style.removeProperty("padding-top"); 56 el.style.removeProperty("padding-bottom"); 57 el.style.removeProperty("margin-top"); 58 el.style.removeProperty("margin-bottom"); 59 setTimeout(() => { 60 el.style.removeProperty("height"); 61 el.style.removeProperty("overflow"); 62 el.style.removeProperty("transition-duration"); 63 el.style.removeProperty("transition-property"); 64 el.style.removeProperty("transition-timing-function"); 65 }, duration); 66}; 67 68// 要素をスライドしながら交互に表示/非表示にする関数(jQueryのslideToggleと同じ) 69const slideToggle = (el, duration = 300) => { 70 if (window.getComputedStyle(el).display === "none") { 71 return slideDown(el, duration); 72 } else { 73 return slideUp(el, duration); 74 } 75}; 76 77/* =================================================== */ 78// DOM操作 79/* =================================================== */ 80 81// アコーディオンを全て取得 82const accordions = document.querySelectorAll(".js-accordion"); 83// 取得したアコーディオンをArrayに変換(IE対策) 84const accordionsArr = Array.prototype.slice.call(accordions); 85 86accordionsArr.forEach((accordion) => { 87 // Triggerを全て取得 88 const accordionTriggers = accordion.querySelectorAll(".js-accordion-trigger"); 89 // TriggerをArrayに変換(IE対策) 90 const accordionTriggersArr = Array.prototype.slice.call(accordionTriggers); 91 92 accordionTriggersArr.forEach((trigger) => { 93 // Triggerにクリックイベントを付与 94 trigger.addEventListener("click", (e) => { 95 accordionTriggersArr.forEach((trigger) => { 96 // クリックしたアコーディオン以外を全て閉じる 97 if (trigger !== e.target.parentElement) { 98 trigger.classList.remove("is-active"); 99 const openedContent = trigger.querySelector(".accordion__content"); 100 slideUp(openedContent); 101 } 102 }); 103 104 // '.is-active'クラスを付与or削除 105 trigger.classList.toggle("is-active"); 106 // 開閉させる要素を取得 107 const content = trigger.querySelector(".accordion__content"); 108 // 要素を展開or閉じる 109 slideToggle(content); 110 }); 111 }); 112});

SCSS

1//アコーディオン 2/* 簡易リセットCSS */ 3* { 4 margin: 0; 5 padding: 0; 6 box-sizing: border-box; 7} 8 9/* アコーディオン全体 */ 10.accordion { 11 margin: 0 auto; 12} 13 14/* アコーディオン */ 15.accordion__item { 16 17 border: 2px solid $color-blue; 18 border-radius: 10px; 19 background: $color-white; 20 margin-top: 10px; 21 cursor: pointer; 22 23} 24 25/* アコーディオンのタイトル */ 26.accordion__title { 27 position: relative; 28 font-size: clamp(16px, 3vw, 20px); 29 font-family: "Noto Serif JP", serif; 30 color: $color-blue; 31 padding: 35px 60px 35px 20px; 32 font-weight: bold; 33 cursor: pointer; 34 35 36} 37 38//もっと読む 39.accordion__title__single { 40 padding: 23px 60px 23px 20px; 41} 42 43/* 矢印(↑)アイコン */ 44.arrow { 45 position: absolute; 46 right: 0; 47 display: inline-block; 48 padding: 0 0 0 16px; 49 color: $color-blue; 50 vertical-align: middle; 51 text-decoration: none; 52} 53 54.accordion__title .arrow::before, 55.accordion__title .arrow::after { 56 position: absolute; 57 margin: auto; 58 content: ""; 59 vertical-align: middle; 60 transition: all 0.3s; 61} 62 63.arrow::before { 64 top: 0; 65 bottom: 0; 66 right: 37px; 67 width: 2px; 68 height: 30px; 69 background: $color-blue; 70 71} 72 73.arrow::after { 74 top: 0; 75 bottom: -20px; 76 right: 33px; 77 width: 10px; 78 height: 10px; 79 border-top: 2px solid $color-blue; 80 border-right: 2px solid $color-blue; 81 -webkit-transform: rotate(135deg); 82 transform: rotate(135deg); 83} 84 85.accordion__content.is-open { 86 display: block; 87} 88 89/* アコーディオン展開時の(↑)アイコン */ 90.accordion__item.is-active .accordion__title .arrow::before { 91 transform: rotate(180deg); 92} 93 94.accordion__item.is-active .accordion__title .arrow::after { 95 transform: rotate(310deg); 96 top: -20px; 97 bottom: 0; 98} 99 100/* アコーディオンのコンテンツ */ 101.accordion__content { 102 font-size: clamp(14px, 3vw, 18px); 103 font-family: "Noto Sands JP"; 104 padding: 0 2em 2em 2em; 105 display: none; 106 cursor: pointer; 107 text-align: left; 108 line-height: 1.7; 109 110 .accordion__list { 111 margin: 20px 0; 112 } 113}

試したこと

ネットで調べたがわかりませんでした。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

  1. 矢印のパーツを回転させるのではなくて、矢印ごと回転させてはどうでしょうか。
  2. Event.target は実際にクリックされた要素を参照しているので、triggerの子孫要素ではありますが、子要素とは限らないです。つまり、trigger !== e.target.parentElementが成り立たないことがあります。Event.currentTargetを試してみてはどうでしょうか。

投稿2023/07/13 01:40

Lhankor_Mhy

総合スコア37528

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

spn

2023/07/13 04:50

ご回答ありがとうございます。 1の矢印の回転は /* アコーディオン展開時の(↑)アイコン */ .accordion__item.is-active .accordion__title .arrow { transform: rotate(180deg); right: 77px; } でお陰様で無事解決しました。ありがとうございます。 2がjavasprict初学者で、私の理解力がなく苦戦しております。 trigger !== Event.currentTarget.parentElementにしても効かなかったです。 詳しく教えていただけませんか。
spn

2023/07/13 05:43

// クリックしたアコーディオン以外を全て閉じる if (trigger !== e.target.closest('.js-accordion-trigger')) { trigger.classList.remove("is-active"); const openedContent = trigger.querySelector(".accordion__content"); slideUp(openedContent); }にして解決しました!ありがとうございました!
Lhankor_Mhy

2023/07/13 05:43

Event ではなくて、ご提示のコードの場合は e ですね。
Lhankor_Mhy

2023/07/13 05:46

あら、かぶった。 ご解決されて何よりです。
hatena19

2023/07/13 06:17

解決済みですが、それで本当に解決ですか? // クリックしたアコーディオン以外を全て閉じる というコメントがありますが、これは実現できていないのでは?
Lhankor_Mhy

2023/07/13 06:27

できるのでは……?
Lhankor_Mhy

2023/07/13 06:31

ああ、回答を見て理解しました。そのようにお読みになったんですね。 当方では .js-accordion*x>.js-accordion-trigger*y と読んでました。
guest

0

解決ずみですが、下記の点は未解決では。

// クリックしたアコーディオン以外を全て閉じる

やりたいことは、複数のアコーディオンがあって、クリックした以外の開いているアコーディオンは閉じるということですよね。

HTMLが
js-accordion → js-accordion-trigger → accordion__title, accordion__content
という親子関係になってますが、js-accordionの配列(accordionsArr)をforEachループして、その中でjs-accordion-triggerの配列を取得してますが、カレントのjs-accordionの中にはjs-accordion-triggerは一つしかないので、accordionTriggersArr.forEachによる判定は無意味です。

js-accordion と js-accordion-trigger の二重ループにせずに、js-accordion-trigger のループで自分以外を閉じるようにすればいいでしょう。

JavaScript

1/* =================================================== */ 2// DOM操作 3/* =================================================== */ 4 5// アコーディオン Triggerを全て取得 6const accordionTriggers = document.querySelectorAll( 7 ".js-accordion .js-accordion-trigger" 8); 9// 取得したアコーディオン TriggerをArrayに変換(IE対策) 10const accordionTriggersArr = Array.prototype.slice.call(accordionTriggers); 11 12accordionTriggersArr.forEach((trigger, index) => { 13 // Triggerにクリックイベントを付与 14 trigger.addEventListener("click", (e) => { 15 currentIndex = index; //クリックされたボタンのインデックス 16 accordionTriggersArr.forEach((trigger, index) => { 17 // クリックしたアコーディオン以外を全て閉じる 18 if (currentIndex !== index) { 19 trigger.classList.remove("is-active"); 20 const openedContent = trigger.querySelector(".accordion__content"); 21 slideUp(openedContent); 22 } 23 }); 24 25 // '.is-active'クラスを付与or削除 26 trigger.classList.toggle("is-active"); 27 // 開閉させる要素を取得 28 const content = trigger.querySelector(".accordion__content"); 29 // 要素を展開or閉じる 30 slideToggle(content); 31 }); 32});

CodePenサンプル

投稿2023/07/13 06:21

編集2023/07/13 06:33
hatena19

総合スコア34367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問