記事内に商品プロモーションを含む場合があります

Blog WordPress

【コピペでOK!】シンプルなアコーディオンを実装する方法

2023年9月7日

【コピペでOK!】シンプルなアコーディオンを実装する方法
悩んでいる人
悩んでいる人
よくある質問とかであるボタンをクリックしたら開閉するやつを作りたい...できればコピペとかで簡単にできないかな...


こういったアコーディオンを実装したい方向けに書いています。

この記事を書いている私は、完全未経験(前職は美容師)からWebデザイナーに転職した僕が実際に現場でよくある要望事例をわかりやすく説明していきます。

ご参考になれば幸いです。

アコーディオン完成イメージ


さっそくですが、完成イメージはこんな感じです。

See the Pen Untitled by dot (@rikiiito) on CodePen.


今回は、コピペで簡単にできるJavascriptでシンプルなアコーディオンを実装する方法を解説していきます。

シンプルなアコーディオンを実装するコード


下記3つのファイルにコードをかいていきます。

  • HTML
  • CSS
  • JavaScript

順番に解説していきます。

HTMLのコード

<dl class="accordion js-accordion">
  <div class="accordion__item js-accordion-trigger">
    <dt class="accordion__title">タイトル</dt>
    <dd class="accordion__content">アコーディオンのコンテンツアコーディオンのコンテンツアコーディオンのコンテンツアコーディオンのコンテンツ</dd>
  </div>
  <div class="accordion__item js-accordion-trigger">
    <dt class="accordion__title">タイトル</dt>
    <dd class="accordion__content">アコーディオンのコンテンツアコーディオンのコンテンツアコーディオンのコンテンツアコーディオンのコンテンツ</dd>
  </div>
  <div class="accordion__item js-accordion-trigger">
    <dt class="accordion__title">タイトル</dt>
    <dd class="accordion__content">アコーディオンのコンテンツアコーディオンのコンテンツアコーディオンのコンテンツアコーディオンのコンテンツ</dd>
  </div>
</dl>

CSSのコード

/* 簡易リセットCSS */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* アコーディオン全体 */
.accordion {
  max-width: 800px;
  margin: 0 auto;
}

/* アコーディオン */
.accordion__item {
  border: 1px solid #ccc;
  margin-top: 10px;
  cursor: pointer;
}

/* アコーディオン タイトル */
.accordion__title {
  position: relative;
  padding: 15px 60px 15px 20px;
  font-weight: bold;
  cursor: pointer;
}

/* +アイコン */
.accordion__title::before,
.accordion__title::after {
  content: "";
  position: absolute;
  right: 20px;
  top: 0;
  bottom: 0;
  margin: auto 0;
  background-color: #9c9c9c;
  width: 20px;
  height: 4px;
  transition: all 0.3s;
}

.accordion__title::after {
  transform: rotate(90deg);
}

/* アコーディオンのコンテンツ */
.accordion__content {
  padding: 0 20px 15px 20px;
  display: none;
  cursor: pointer;
}

.accordion__content.is-open {
  display: block;
}

/* アコーディオン展開時の-アイコン */
.accordion__item.is-active .accordion__title::before {
  transform: rotate(180deg);
}

.accordion__item.is-active .accordion__title::after {
  transform: rotate(180deg);
  opacity: 0;
}

JavaScriptのコード

// 要素をスライドしながら非表示にする関数
const slideUp = (el, duration = 300) => {
  el.style.height = el.offsetHeight + "px";
  el.offsetHeight;
  el.style.transitionProperty = "height, margin, padding";
  el.style.transitionDuration = duration + "ms";
  el.style.transitionTimingFunction = "ease";
  el.style.overflow = "hidden";
  el.style.height = 0;
  el.style.paddingTop = 0;
  el.style.paddingBottom = 0;
  el.style.marginTop = 0;
  el.style.marginBottom = 0;
  setTimeout(() => {
    el.style.display = "none";
    el.style.removeProperty("height");
    el.style.removeProperty("padding-top");
    el.style.removeProperty("padding-bottom");
    el.style.removeProperty("margin-top");
    el.style.removeProperty("margin-bottom");
    el.style.removeProperty("overflow");
    el.style.removeProperty("transition-duration");
    el.style.removeProperty("transition-property");
    el.style.removeProperty("transition-timing-function");
    el.classList.remove("is-open");
  }, duration);
};

// 要素をスライドしながら表示する関数
const slideDown = (el, duration = 300) => {
  el.classList.add("is-open");
  el.style.removeProperty("display");
  let display = window.getComputedStyle(el).display;
  if (display === "none") {
    display = "block";
  }
  el.style.display = display;
  let height = el.offsetHeight;
  el.style.overflow = "hidden";
  el.style.height = 0;
  el.style.paddingTop = 0;
  el.style.paddingBottom = 0;
  el.style.marginTop = 0;
  el.style.marginBottom = 0;
  el.offsetHeight;
  el.style.transitionProperty = "height, margin, padding";
  el.style.transitionDuration = duration + "ms";
  el.style.transitionTimingFunction = "ease";
  el.style.height = height + "px";
  el.style.removeProperty("padding-top");
  el.style.removeProperty("padding-bottom");
  el.style.removeProperty("margin-top");
  el.style.removeProperty("margin-bottom");
  setTimeout(() => {
    el.style.removeProperty("height");
    el.style.removeProperty("overflow");
    el.style.removeProperty("transition-duration");
    el.style.removeProperty("transition-property");
    el.style.removeProperty("transition-timing-function");
  }, duration);
};

// 要素をスライドしながら交互に表示/非表示にする関数
const slideToggle = (el, duration = 300) => {
  if (window.getComputedStyle(el).display === "none") {
    return slideDown(el, duration);
  } else {
    return slideUp(el, duration);
  }
};

/* =================================================== */
// DOM操作
/* =================================================== */

// アコーディオンを全て取得
const accordions = document.querySelectorAll(".js-accordion");
// 取得したアコーディオンをArrayに変換(IE対策)
const accordionsArr = Array.prototype.slice.call(accordions);

accordionsArr.forEach((accordion) => {
  // Triggerを全て取得
  const accordionTriggers = accordion.querySelectorAll(".js-accordion-trigger");
  // TriggerをArrayに変換(IE対策)
  const accordionTriggersArr = Array.prototype.slice.call(accordionTriggers);

  accordionTriggersArr.forEach((trigger) => {
    // Triggerにクリックイベントを付与
    trigger.addEventListener("click", () => {
      // '.is-active'クラスを付与or削除
      trigger.classList.toggle("is-active");
      // 開閉させる要素を取得
      const content = trigger.querySelector(".accordion__content");
      // 要素を展開or閉じる
      slideToggle(content);
    });
  });
});

まとめ

今回は、コピペで簡単にできるシンプルなアコーディオンを実装する方法をご紹介してきました。

コピペで簡単に実装できるので、この記事を参考にしていただいて、CSSを自分好みなデザインに変更してもらえればと思います。

これからWebデザイナー・エンジニアになりたい方は僕が完全未経験の独学期間にはやく知りたかったおすすめの本をご紹介していますので、ご参考にしていただければと思います。

以上、「【コピペでOK!】シンプルなアコーディオンを実装する方法」でした。

  • この記事を書いた人
rdotblog_profile

dot

関西出身の29歳 R.BLOG(アールドットブログ)では、完全未経験から独学でWebデザイナーへ転職し、現役Webデザイナーとして日々学んだ(Webデザイン・プログラミング・Webマーケティング・SEOなど)タメになる情報を発信していきます。

-Blog, WordPress