День 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— контент скрыт - При добавлении класса
activemax-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');
}
}
Логика работы:
- Проверяем, активен ли элемент:
item.classList.contains('active')contains()— метод, который проверяет, есть ли класс у элемента- Возвращает
trueилиfalse
- Закрываем все элементы (убираем класс active со всех)
- Если элемент был неактивен (
!isActiveозначает "не активен"), открываем его - Если элемент был активен, он останется закрытым (так как мы убрали 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)
Практическое задание
- Создайте структуру аккордеона
- Стилизуйте заголовки и контент
- Реализуйте анимацию открытия/закрытия
- Добавьте поворот иконки при открытии
- Сделайте так, чтобы при открытии одного элемента другие закрывались
- Добавьте возможность открывать несколько элементов одновременно (опционально)
- Улучшите анимацию, используя реальную высоту контента
Что дальше?
Отлично! Аккордеон готов. В следующем уроке мы создадим модальное окно — всплывающее окно, которое используется для форм, подтверждений и важной информации.