Урок 21

День 21 | Верстаем аккордеон (Accordion) на чистом JS

45 мин

Что такое аккордеон?

Аккордеон — это компонент, который показывает контент в компактном виде. Обычно виден только заголовок, а содержимое скрыто. При клике на заголовок содержимое раскрывается.

Где используются аккордеоны?

  • FAQ (часто задаваемые вопросы) — самый популярный случай
  • Меню с подпунктами
  • Описания товаров (характеристики, детали)
  • Любой контент, который нужно скрыть, чтобы не перегружать страницу

Преимущества аккордеона:

  • Экономит место на странице
  • Позволяет организовать много информации
  • Пользователь видит только то, что его интересует

HTML структура аккордеона

<div class="accordion">
  <div class="accordion-item">
    <button class="accordion-header">
      <span>Вопрос 1</span>
      <span class="accordion-icon">+</span>
    </button>
    <div class="accordion-content">
      <p>Ответ на первый вопрос. Здесь может быть длинный текст с подробным объяснением.</p>
    </div>
  </div>
  
  <div class="accordion-item">
    <button class="accordion-header">
      <span>Вопрос 2</span>
      <span class="accordion-icon">+</span>
    </button>
    <div class="accordion-content">
      <p>Ответ на второй вопрос.</p>
    </div>
  </div>
  
  <div class="accordion-item">
    <button class="accordion-header">
      <span>Вопрос 3</span>
      <span class="accordion-icon">+</span>
    </button>
    <div class="accordion-content">
      <p>Ответ на третий вопрос.</p>
    </div>
  </div>
</div>

Разберём структуру:

  • accordion-item — один элемент аккордеона (вопрос-ответ)
  • accordion-header — заголовок (кнопка, на которую кликают)
  • accordion-icon — иконка (обычно + или стрелка, которая поворачивается)
  • accordion-content — содержимое (скрыто по умолчанию)
  • class="active" — класс для открытого элемента

Почему <button> для заголовка? Кнопка семантически правильна для интерактивного элемента. Кроме того, кнопки доступны с клавиатуры (можно открыть аккордеон нажатием Enter или Пробела).

Разбор CSS для аккордеона

Анимация высоты

Самая сложная часть аккордеона — анимация высоты. Проблема в том, что нельзя анимировать height: auto. Решение — использовать max-height:

.accordion-content {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
}

.accordion-item.active .accordion-content {
  max-height: 500px;
}

Как это работает:

  • По умолчанию max-height: 0 — контент скрыт
  • При добавлении класса active max-height: 500px — контент виден
  • transition делает изменение плавным
  • overflow: hidden — скрывает контент, который не помещается

Проблема с max-height: Нужно указать значение больше, чем может быть контента. Если контент больше 500px, он обрежется. Обычно ставят большое значение (например, 1000px) или используют JavaScript для вычисления реальной высоты.

Поворот иконки

.accordion-icon {
  font-size: 24px;
  transition: transform 0.3s;
}

.accordion-item.active .accordion-icon {
  transform: rotate(45deg);
}

Иконка "+" поворачивается на 45 градусов при открытии, превращаясь в "×".

Разбор JavaScript кода

Метод toggleItem()

toggleItem(item) {
  const isActive = item.classList.contains('active');
  
  // Закрываем все элементы
  this.items.forEach(i => i.classList.remove('active'));
  
  // Если элемент был неактивен, открываем его
  if (!isActive) {
    item.classList.add('active');
  }
}

Логика работы:

  1. Проверяем, активен ли элемент: item.classList.contains('active')
    • contains() — метод, который проверяет, есть ли класс у элемента
    • Возвращает true или false
  2. Закрываем все элементы (убираем класс active со всех)
  3. Если элемент был неактивен (!isActive означает "не активен"), открываем его
  4. Если элемент был активен, он останется закрытым (так как мы убрали active со всех)

Что такое ! (восклицательный знак)? Это оператор "НЕ" (логическое отрицание). !isActive означает "не активен" (если isActive = false, то !isActive = true).

Улучшенная версия с плавной анимацией

Для более точной анимации можно использовать JavaScript для вычисления реальной высоты:

toggleItem(item) {
  const isActive = item.classList.contains('active');
  const content = item.querySelector('.accordion-content');
  
  // Закрываем все элементы
  this.items.forEach(i => {
    if (i !== item) {
      i.classList.remove('active');
      const otherContent = i.querySelector('.accordion-content');
      otherContent.style.maxHeight = null;
    }
  });
  
  // Переключаем текущий элемент
  if (isActive) {
    item.classList.remove('active');
    content.style.maxHeight = null;
  } else {
    item.classList.add('active');
    // Устанавливаем реальную высоту
    content.style.maxHeight = content.scrollHeight + "px";
  }
}

Что нового:

  • content.scrollHeight — реальная высота контента (включая скрытую часть)
  • content.style.maxHeight = content.scrollHeight + "px" — устанавливаем точную высоту
  • style.maxHeight = null — сбрасываем inline стиль (возвращаем к CSS)

Практическое задание

  1. Создайте структуру аккордеона
  2. Стилизуйте заголовки и контент
  3. Реализуйте анимацию открытия/закрытия
  4. Добавьте поворот иконки при открытии
  5. Сделайте так, чтобы при открытии одного элемента другие закрывались
  6. Добавьте возможность открывать несколько элементов одновременно (опционально)
  7. Улучшите анимацию, используя реальную высоту контента

Что дальше?

Отлично! Аккордеон готов. В следующем уроке мы создадим модальное окно — всплывающее окно, которое используется для форм, подтверждений и важной информации.

Мы используем файлы cookie для улучшения работы сайта и персонализации контента. Продолжая использовать сайт, вы соглашаетесь с использованием cookies в соответствии с нашей Политикой конфиденциальности.