【PR】を含みます。

フロントエンド

【JavaScript】jQuery未使用でアコーディオン(開閉ボタン)を実装する方法

JavaScript jQuery未使用でアコーディオン(開閉ボタン)を実装する方法

jQueryを使わずにJavaScriptでアコーディオンメニューを実装する方法を解説します。

HTML・CSS・JavaScriptのコードをコピペするだけで使える、アニメーション付きのアコーディオンの作り方を紹介します。

jQueryが使用できない環境でも、アクセシビリティに配慮したアコーディオンメニューを実装できるよう、コードを公開しています。

スムーズな開閉アニメーションも実装済みです。

アコーディオンをjQueryで実装する方法は以下の記事で紹介しています。

あわせて読む
jQuery アコーディオン(開閉ボタン)を実装する方法

【jQuery】アコーディオン(開閉ボタン)を実装する方法

もくじ【サンプル】jQueryでアコーディオンメニューを実装【コピペOK】jQueryを使用したアコーディオンメニューの実装コード【サンプル】jQueryでアクセシビリティ対応済みのアコーディオンメニ ...

アコーディオンをHTMLのみで実装する方法は以下の記事で紹介しています。

あわせて読む
CSS不要 HTMLのみでアコーディオン(開閉ボタン)を実装する方法

【CSS不要】HTMLのみでアコーディオン(開閉ボタン)を実装する方法

もくじ【サンプル】HTMLのみでアコーディオンメニューを実装【実装コード】HTMLのみでアコーディオンメニューを実装detailsタグとsummaryタグにCSS当ててデザインを調整【サンプル】CSS ...

アコーディオンをHTMLとCSSのみで実装する方法は以下の記事で紹介しています。

あわせて読む
HTML・CSS アコーディオンメニューをHTMLとCSSのみで実装する方法

【HTML・CSS】アコーディオンメニューをHTMLとCSSのみで実装する方法

もくじ単体用アコーディオン(折りたたみメニュー)【サンプル】単体用アコーディオン【コピペOK】HTML・CSSのみで単体用アコーディオンを実装単体用アコーディオンを複数利用する方法2段のアコーディオン ...

【実装例】jQuery未使用のアコーディオンメニュー(開閉ボタン)のサンプル

Q. JavaScriptでアコーディオン(開閉ボタン)を実装する方法は?

A. 「【コピペOK】jQuery未使用のアコーディオンメニューの実装コード」より、HTML・CSS・JavaScriptをコピペすることでアコーディオン(開閉ボタン)を実装できます。

Q. はじめからアコーディオンを開いた状態にする方法は?

HTMLにis-activeを追加することで可能です。


class="accordion js-accordion"is-activeを追加

【コピペOK】jQuery未使用のアコーディオンメニューの実装コード

下記HTML・CSS・JavaScriptをコピペすることでアコーディオンを実装することができます。

Copyをクリックするとコピーできます。

HTML
Copy
<div class="accordion js-accordion">
  <div class="accordion-summary js-accordion-toggle">
    <p class="accordion-ttl">Q. テキスト</p>
    <div class="accordion-toggle-icon">
      <span class="accordion-toggle-line"></span>
      <span class="accordion-toggle-line"></span>
    </div>
  </div>
  <div class="accordion-panel js-accordion-panel">
    <div class="accordion-details">
      <div class="accordion-details-inner">
        <p class="accordion-txt">A. テキスト</p>
        <p class="accordion-txt">※テキスト</p>
      </div>
    </div>
  </div>
</div>
<div class="accordion js-accordion is-active">
  <div class="accordion-summary js-accordion-toggle">
    <p class="accordion-ttl">Q. テキスト</p>
    <div class="accordion-toggle-icon">
      <span class="accordion-toggle-line"></span>
      <span class="accordion-toggle-line"></span>
    </div>
  </div>
  <div class="accordion-panel js-accordion-panel">
    <div class="accordion-details">
      <div class="accordion-details-inner">
        <p class="accordion-txt">A. テキスト</p>
        <p class="accordion-txt">※テキスト</p>
      </div>
    </div>
  </div>
</div>
CSS
Copy
.accordion * {
  box-sizing: border-box;
}
.accordion {
  margin-bottom: 30px;
  background: #ffefef;
  border-radius: 5px;
}
.accordion-summary {
  display: block;
  position: relative;
  width: 100%;
  padding: 1em 3.2em 1em 2em;
  font: inherit;
  text-align: left;
  background: transparent;
  border: none;
  cursor: pointer;
}
.accordion-summary:active {
  background: transparent;
}
.accordion-ttl {
  margin: 0;
  font-size: 16px;
}
.accordion-toggle-icon {
  position: absolute;
  top: 50%;
  right: 1.5em;
  width: 1em;
  height: 1em;
  transform: translateY(-50%);
}
.accordion-toggle-line {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0.8em;
  height: 2px;
  background: #333;
}
.accordion-toggle-line:nth-child(1) {
  transform: translate(-50%, -50%);
}
.accordion-toggle-line:nth-child(2) {
  transform: translate(-50%, -50%) rotate(90deg);
  transition: 0.3s linear;
}
.accordion.is-active .accordion-toggle-line:nth-child(2) {
  opacity: 0;
}
.accordion-panel {
  display: none;
}
.accordion.is-active .accordion-panel {
  display: block;
}
.accordion-details {
  padding: 0 1.5em 1.5em;
}
.accordion-details-inner {
  padding: 1.5em;
  background: #fff;
  border-radius: 5px;
}
.accordion-txt {
  margin: 0;
  font-size: 16px;
}
JavaScript
Copy
const accordionToggle = document.querySelectorAll('.js-accordion-toggle');
accordionToggle.forEach(function (element) {
  element.addEventListener('click', function () {
    const accordion = element.closest('.js-accordion');
    if (!accordion) return;
    const accordionPanel = accordion.querySelector('.js-accordion-panel');
    if (!accordionPanel) return;
    slideToggle(accordionPanel, 500);
  });
});
function slideUp(element, duration = 400) {
  if (element.dataset.sliding === 'true') return;
  element.dataset.sliding = 'true';
  element.style.display = 'block';
  element.closest('.js-accordion').classList.remove('is-active');
  const height = element.offsetHeight;
  element.style.height = height + 'px';
  element.offsetHeight;
  element.style.overflow = 'hidden';
  element.style.transition = `height ${duration}ms ease`;
  requestAnimationFrame(() => {
    element.style.height = '0px';
  });
  setTimeout(() => {
    element.style.display = 'none';
    element.style.removeProperty('height');
    element.style.removeProperty('overflow');
    element.style.removeProperty('transition');
    element.dataset.sliding = 'false';
  }, duration);
}
function slideDown(element, duration = 400) {
  if (element.dataset.sliding === 'true') return;
  element.dataset.sliding = 'true';
  element.closest('.js-accordion').classList.add('is-active');
  element.style.removeProperty('display');
  let display = window.getComputedStyle(element).display;
  if (display === 'none') display = 'block';
  element.style.display = display;
  const height = element.scrollHeight;
  element.style.height = '0px';
  element.offsetHeight;
  element.style.overflow = 'hidden';
  element.style.transition = `height ${duration}ms ease`;
  requestAnimationFrame(() => {
    element.style.height = height + 'px';
  });
  setTimeout(() => {
    element.style.removeProperty('height');
    element.style.removeProperty('overflow');
    element.style.removeProperty('transition');
    element.dataset.sliding = 'false';
  }, duration);
}
function slideToggle(element, duration = 400) {
  const isActive = element.closest('.js-accordion').classList.contains('is-active');
  if (isActive) {
    slideUp(element, duration);
  } else {
    slideDown(element, duration);
  }
}

【実装例】アクセシビリティ対応済みのアコーディオンメニュー(開閉ボタン)のサンプル

class="accordion js-accordion"is-activeを追加とaria-expanded="false"aria-expanded="true"に変更、hidden="until-found"を削除することで可能です。

【コピペOK】アクセシビリティ対応済みのアコーディオンメニューの実装コード

下記HTML・CSS・JavaScriptをコピペすることでアコーディオンを実装することができます。

Copyをクリックするとコピーできます。

HTML
Copy
<div class="accordion js-accordion">
  <button id="accordion-summary-1" class="accordion-summary js-accordion-btn" aria-expanded="false" aria-controls="accordion-panel-1">
    <span class="accordion-ttl">Q. テキスト</span>
    <span class="accordion-toggle-icon" aria-hidden="true">
      <span class="accordion-toggle-line"></span>
      <span class="accordion-toggle-line"></span>
    </span>
  </button>
  <div id="accordion-panel-1" class="accordion-panel-other js-accordion-panel" role="region" aria-labelledby="accordion-summary-1" hidden="until-found">
    <div class="accordion-details">
      <div class="accordion-details-inner">
        <p class="accordion-txt">A. テキスト</p>
        <p class="accordion-txt">※テキスト</p>
      </div>
    </div>
  </div>
</div>
<div class="accordion js-accordion is-active">
  <button id="accordion-summary-2" class="accordion-summary js-accordion-btn" aria-expanded="true" aria-controls="accordion-panel-2">
    <span class="accordion-ttl">Q. テキスト</span>
    <span class="accordion-toggle-icon" aria-hidden="true">
      <span class="accordion-toggle-line"></span>
      <span class="accordion-toggle-line"></span>
    </span>
  </button>
  <div id="accordion-panel-2" class="accordion-panel-other js-accordion-panel" role="region" aria-labelledby="accordion-summary-2">
    <div class="accordion-details">
      <div class="accordion-details-inner">
        <p class="accordion-txt">A. テキスト</p>
        <p class="accordion-txt">※テキスト</p>
      </div>
    </div>
  </div>
</div>
CSS
Copy
.accordion * {
  box-sizing: border-box;
}
.accordion {
  margin-bottom: 30px;
  background: #ffefef;
  border-radius: 5px;
}
.accordion-summary {
  display: block;
  position: relative;
  width: 100%;
  padding: 1em 3.2em 1em 2em;
  font: inherit;
  text-align: left;
  background: transparent;
  border: none;
  cursor: pointer;
}
.accordion-summary:active {
  background: transparent;
}
.accordion-ttl {
  margin: 0;
  font-size: 16px;
}
.accordion-toggle-icon {
  position: absolute;
  top: 50%;
  right: 1.5em;
  width: 1em;
  height: 1em;
  transform: translateY(-50%);
}
.accordion-toggle-line {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0.8em;
  height: 2px;
  background: #333;
}
.accordion-toggle-line:nth-child(1) {
  transform: translate(-50%, -50%);
}
.accordion-toggle-line:nth-child(2) {
  transform: translate(-50%, -50%) rotate(90deg);
  transition: 0.3s linear;
}
.accordion.is-active .accordion-toggle-line:nth-child(2) {
  opacity: 0;
}
.accordion-details {
  padding: 0 1.5em 1.5em;
}
.accordion-details-inner {
  padding: 1.5em;
  background: #fff;
  border-radius: 5px;
}
.accordion-txt {
  margin: 0;
  font-size: 16px;
}
JavaScript
Copy
const accordionBtn = document.querySelectorAll('.js-accordion-btn');
accordionBtn.forEach(function (element) {
  element.addEventListener('click', function () {
    const accordion = element.closest('.js-accordion');
    if (!accordion) return;
    const accordionPanel = accordion.querySelector('.js-accordion-panel');
    if (!accordionPanel) return;
    toggleAccordionPanel(accordionPanel, 500);
  });
});
function openAccordionPanel(element, duration = 400) {
  if (element.dataset.sliding === 'true') return;
  element.dataset.sliding = 'true';
  const accordion = element.closest('.js-accordion');
  accordion.classList.add('is-active');
  element.removeAttribute("hidden");
  const height = element.scrollHeight;
  element.style.height = '0px';
  element.offsetHeight;
  element.style.overflow = 'hidden';
  element.style.transition = `height ${duration}ms ease`;
  const accordionBtn = accordion.querySelector('.js-accordion-btn');
  accordionBtn.setAttribute('aria-expanded', 'true');
  requestAnimationFrame(() => {
    element.style.height = height + 'px';
  });
  setTimeout(() => {
    element.style.removeProperty('height');
    element.style.removeProperty('overflow');
    element.style.removeProperty('transition');
    element.dataset.sliding = 'false';
  }, duration);
}
function closeAccordionPanel(element, duration = 400) {
  if (element.dataset.sliding === 'true') return;
  element.dataset.sliding = 'true';
  const accordion = element.closest('.js-accordion');
  accordion.classList.remove('is-active');
  const height = element.offsetHeight;
  element.style.height = height + 'px';
  element.offsetHeight;
  element.style.overflow = 'hidden';
  element.style.transition = `height ${duration}ms ease`;
  const accordionBtn = accordion.querySelector('.js-accordion-btn');
  accordionBtn.setAttribute('aria-expanded', 'false');
  requestAnimationFrame(() => {
    element.style.height = '0px';
  });
  setTimeout(() => {
    element.style.removeProperty('height');
    element.style.removeProperty('overflow');
    element.style.removeProperty('transition');
    element.dataset.sliding = 'false';
    element.setAttribute('hidden', 'until-found');
  }, duration);
}
function toggleAccordionPanel(element, duration = 400) {
  const isHidden = element.hasAttribute('hidden');
  if (isHidden) {
    openAccordionPanel(element, duration);
  } else {
    closeAccordionPanel(element, duration);
  }
}

Q & A

まとめ

  • jQueryなしでアコーディオンを実装する方法を解説しました。
  • アクセシビリティ対応のポイントも紹介しました。
  • コピペで使えるHTML・CSS・JavaScriptのサンプル付きです。

アコーディオンをjQueryで実装する方法は以下の記事で紹介しています。

あわせて読む
jQuery アコーディオン(開閉ボタン)を実装する方法

【jQuery】アコーディオン(開閉ボタン)を実装する方法

もくじ【サンプル】jQueryでアコーディオンメニューを実装【コピペOK】jQueryを使用したアコーディオンメニューの実装コード【サンプル】jQueryでアクセシビリティ対応済みのアコーディオンメニ ...

アコーディオンをHTMLのみで実装する方法は以下の記事で紹介しています。

あわせて読む
CSS不要 HTMLのみでアコーディオン(開閉ボタン)を実装する方法

【CSS不要】HTMLのみでアコーディオン(開閉ボタン)を実装する方法

もくじ【サンプル】HTMLのみでアコーディオンメニューを実装【実装コード】HTMLのみでアコーディオンメニューを実装detailsタグとsummaryタグにCSS当ててデザインを調整【サンプル】CSS ...

アコーディオンをHTMLとCSSのみで実装する方法は以下の記事で紹介しています。

あわせて読む
HTML・CSS アコーディオンメニューをHTMLとCSSのみで実装する方法

【HTML・CSS】アコーディオンメニューをHTMLとCSSのみで実装する方法

もくじ単体用アコーディオン(折りたたみメニュー)【サンプル】単体用アコーディオン【コピペOK】HTML・CSSのみで単体用アコーディオンを実装単体用アコーディオンを複数利用する方法2段のアコーディオン ...

-フロントエンド
-