⚙️
Front-end patterns
  • Введение
  • Шаблоны
    • Эффекты CSS
      • Overlay
      • Анимация display:none
      • Текст
        • Фон текста градиент с анимацией
      • Элементы формы
        • Вертикальное выравнивание placeholder по вертикали
      • Ссылки
        • Градиент как основной цвет
        • Линия под ссылкой ездит слева направо при наведении
      • Скрывать блок .clipped
    • Модальное окно
      • Dialog
    • Элементы формы
      • Select
      • Radio
      • CheckBox
      • Ввод текста (input)
        • Телефон (tel)
        • Почта (email)
      • Кнопка
    • Вкладки/Списки
      • Вкладки или Табы (tabs)
      • Аккордеон (Accordion)
    • Навигация
      • Основная и дополнительная навигация на сайте
        • Анимирование основной навигации
      • Пропустить навигацию
      • Хлебные крошки (Breadcrumbs)
      • Кнопка основной навигации (Бургер)
    • Структуры
      • Контейнер
      • Столбцы
      • Прогресс
      • Горизонтальная прокрутка карточек
      • Цитата
    • Тэги (семантика)
      • Текст
      • Логика
    • Увеличить скорость загрузки страницы
    • Шрифты
  • JS
    • Прокрутка страницы
    • Анимация элементов
  • A11Y
    • Фокус с клавиатуры
    • No sort
  • WordPress
    • Решения и подсказки
    • Плагины
    • Натягиваем сайт
      • Пустая тема
      • Делаем главную (пустую) страницу
      • Подключаем стили и js
      • Заменяем содержимое файлов (header, footer, page)
    • Свой плагин
      • Шаблон
      • Административная часть
      • Пользовательская часть
      • Локализация плагина
  • Ghost
    • Создание своей темы
      • Фалы шаблона
        • Partials
          • footer.hbs
          • header.hbs
          • post_card.hbs
        • index.hbs
        • default.hbs
        • post.hbs
      • Переменные
      • Циклы, условия и функции
  • Visual Studio
  • Gulp
    • Deploy on GitHub
    • Плагин
    • Моя сборка
      • Изображения
  • Регулярные выражения
  • Алгоритмы
    • Поиск
    • Сортировка
    • Поиск в ширину (глубину)
    • Типы данных
  • Конструкторы сайтов
Powered by GitBook
On this page
  • Основные данные
  • Терминология
  • Лучшая практика
  • Интерактивный дизайн
  • Управление клавиатурой
  • Screenreader
  • Код
  • CSS
  • JavaScript
  • Код (с возможность анимации)
  • ARIA

Was this helpful?

  1. Шаблоны
  2. Вкладки/Списки

Аккордеон (Accordion)

Серия разворачивающихся / сворачивающихся панелей контента.

PreviousВкладки или Табы (tabs)NextНавигация

Last updated 9 months ago

Was this helpful?

Основные данные

Основной ресурс откуда взята информация -

Каждая панель аккордеона отделена интерактивным заголовком панели, которую в любой момент можно открыть.

Часто используется в боковых панелях и меню навигации для постепенного раскрытия ссылок и фильтров.

Терминология

  • accordion: шаблон в целом, состоящий из следующих частей

  • panel: каждая панель в аккордеоне - это виджет раскрытия деталей

  • header: заголовок, который отображает интерактивную сводку содержимого панели

  • heading: заголовок, который находится внутри элемента и отражает суть панели

  • auto-collapse: свойство аккордеона, при котором автоматически сворачиваются открытые панели при открытии новой панели

Лучшая практика

Каждый заголовок (header) находится в естественном индексе табуляции. Этот естественный tabindex нельзя удалять или изменять.

По умолчанию все панели могут быть в открытом, развернутом состоянии.

При желании аккордеон может быть ограничен отображением только одной панели содержимого за раз (т.е. открытие панели закроет любую другую открытую панель). Это называется автоматически сворачивающимся аккордеоном.

Интерактивный дизайн

Управление клавиатурой

Нажатие клавиши TABдолжно перемещать фокус клавиатуры с одного заголовка на другой. Он также будет перемещать фокус через любые интерактивные элементы внутри открытых панелей.

Точно так же нажатие клавиш SHIFT-TAB перемещает фокус назад по заголовкам и содержимому интерактивной панели.

Нажатие клавиши ПРОБЕЛили ВВОДв заголовке с фокусом клавиатуры должно открывать панель. Для автоматического сворачивания аккордеонов любая другая открытая панель должна закрываться.

Screenreader

Виртуальный курсор должен иметь возможность перемещаться от одного заголовка к другому. ‌

С виртуальным курсором на заголовке, он должен иметь возможность открывать панель с помощью имитации события щелчка. Для аккордеонов с автоматическим сворачиванием любая другая открытая панель должна закрываться, но об этом не следует объявлять.

Код

В шаблоне «аккордеон» активно используется тег "details" HTML. Старые браузеры, включая IE11 и Edge, изначально не поддерживают тег сведений, поэтому требуют полифилла.

При использовании details нет возможности анимировать открытие

HTML-элемент <details> используется для раскрытия скрытой (дополнительной) информации.

Виджет раскрытия обычно представлен на экране с использованием небольшого треугольника, который поворачивается, чтобы показать состояние открытия / закрытия, с меткой рядом с треугольником. Если первый дочерний элемент элемента <details> является <summary>, содержимое элемента <summary> используется в качестве метки для виджета раскрытия.

<ul class="accordion" role="list" aria-roledescription="accordion">
    <li>
        <details class="accordion__details" open>
            <summary><h4>Buying</h4></summary>
            <ul>
                <li><a href="http://www.ebay.com">Purchases</a></li>
                <li><a href="http://www.ebay.com">Bids/Offers</a></li>
                <li><a href="http://www.ebay.com">Didn't Win</a></li>
            </ul>
        </details>
    </li>
    <li>
        <details class="accordion__details">
            <summary><h4>Selling</h4></summary>
            <ul>
                <li><a href="http://www.ebay.com">Sold</a></li>
                <li><a href="http://www.ebay.com">Bids/Offers</a></li>
                <li><a href="http://www.ebay.com">Didn't Swell</a></li>
            </ul>
        </details>
    </li>
</ul>

Обратите внимание, что в некоторых браузерах роль неявного списка удаляется, когда применяется CSS list-style-type: none, поэтому мы применили role = list в нашей разметке, чтобы гарантировать явную роль.

CSS

Для смены стандартного треугольника раскрытия:

summary { list-style-image: url(right-arrow.svg); }
summary::-webkit-details-marker { background: url(right-arrow.svg); color: transparent; }

Анимация раскрытия:

details[open] summary ~ * {
  animation: sweep .5s ease-in-out;
}

@keyframes sweep {
  0%    {opacity: 0; margin-left: -10px}
  100%  {opacity: 1; margin-left: 0px}
}

JavaScript

Код для загрузки полифила только для ие:

<script type="text/javascript">
    if(/MSIE \d|Trident.*rv:/.test(navigator.userAgent))
        document.write('<script src="somescript.js"><\/script>');
</script>

Основной код указан выше и служит для того, что бы закрывать открытую вкладку при выборе новой.

Код (с возможность анимации)

<ul class="services__list" role="list" aria-roledescription="accordion">
   <li class="services__details">
      <button class="btn services__summary" aria-expanded="false">
          <h3 class="services__header">Заголовок</h3>
          <span class="services__icon"></span>
      </button>
      <div class="services__content" aria-hidden="true">
         <p class="services__text">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Praesentium, quod.</p>
      </div>
   </li>  
   <li class="services__details">
      <button class="btn services__summary" aria-expanded="false">
          <h3 class="services__header">Заголовок</h3>
          <span class="services__icon"></span>
      </button>
      <div class="services__content" aria-hidden="true">
         <p class="services__text">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Praesentium, quod.</p>
      </div>
   </li>         
 </ul>
 &__content {
         opacity: 0;
         max-height: 0;
         will-change: max-height;
         overflow: hidden;
         transition: opacity, max-height  0.3s ease-out;
         box-sizing: content-box;
      }

      &__content[aria-hidden="false"]{
         opacity: 1;
         padding: 10px 10px;
      }
/**
 * Аккордеон с анимацией (через button)
 * el - класс аккордеона
 * closeAll - определят, требуется ли закрывать остальные вкладки при открытии
 */
class AccordionBtn {
   constructor(el, closeAll = false) {
      this.accrdion = document.querySelector(el);
      this.closeAll = closeAll;
      if (!this.accrdion) {
         console.error(`Не найден аккордеон - ${el}!`);
         return;
      }
      this.init();
   }

   init() {
      this.accItmesBtns = this.accrdion.querySelectorAll("button[aria-expanded]");
      if (!this.accItmesBtns) console.error("Не найдены кнопки содержащие аттрибут aria-expanded");

      this.accItmesBtns.forEach((itemBtn) => {
         itemBtn.addEventListener("click", (e) => {
            const btn = e.currentTarget;
            const openBtn = btn.getAttribute("aria-expanded") === "true" ? true : false;

            if (this.closeAll) {
               this.showOne(btn);
            }
            const context = btn.nextElementSibling;
            if (!context || !context.hasAttribute("aria-hidden")) console.error("Не найден блок с контентом содержащий аттрибут aria-hidden");
            const openContext = context.getAttribute("aria-hidden") === "true" ? true : false;
            const heightContext = context.style.maxHeight === "" || context.style.maxHeight === "0px" ? context.scrollHeight : 0;

            btn.setAttribute("aria-expanded", !openBtn);
            context.setAttribute("aria-hidden", !openContext);
            context.style.maxHeight = heightContext + "px";
         });
      });
   }

   showOne(btn) {
      this.accItmesBtns.forEach((itemBtn) => {
         if (itemBtn !== btn) {
            itemBtn.setAttribute("aria-expanded", "false");
            if (itemBtn.nextElementSibling.hasAttribute("aria-hidden")) {
               itemBtn.nextElementSibling.setAttribute("aria-hidden", "true");
               itemBtn.nextElementSibling.style.maxHeight = "0px";
            }
         }
      });
   }
}

ARIA

  • aria-roledescription: определяет удобочитаемое, локализованное для автора описание роли элемента. В данном случае «аккордеон».

Хорошая статья с примерами настройки и применения <details>:

Очень много примеров <details> использования с кодом:

Тэг details требует для браузеров которые не поддерживают его нативно.

https://habr.com/ru/post/477520/
https://freefrontend.com/html-details-summary-css/
polyfill
https://ebay.gitbook.io/mindpatterns/disclosure/accordion