HTML5 details и summary: аккордеон без JavaScript — практическое руководство

HTML5 details и summary: аккордеон без JavaScript — практическое руководство

HTML5 details и summary: аккордеон без JavaScript — практическое руководство

HTML5 <details> и <summary>: аккордеон без JavaScript — практическое руководство

Запрос «HTML5 details summary аккордеон без JavaScript» популярен у начинающих и практикующих верстальщиков, потому что эти элементы позволяют быстро сделать раскрывающиеся блоки (FAQ, спойлеры, разделы документации) без JS и с отличной поддержкой доступности. Ниже — пошаговое руководство, кодовые примеры и лучшие практики стилизации и UX.

Что такое <details> и <summary>

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

<details>
  <summary>Что такое HTML5 Details?</summary>
  <p>Это нативный способ делать сворачиваемые блоки без JavaScript.</p>
</details>

Чтобы показать блок раскрытым по умолчанию, используйте булев атрибут open:

<details open>
  <summary>Открыто при загрузке</summary>
  <p>Контент виден сразу.</p>
</details>

Пример: FAQ‑аккордеон без JS

Соберём секцию часто задаваемых вопросов на HTML5 details/summary и аккуратно её стилизуем. Добавим читаемый маркер, плавное раскрытие и фокус для клавиатуры.

<section class="faq">
  <h2>FAQ: Аккордеон на HTML5</h2>

  <details class="faq-item" open>
    <summary>Как работает элемент <code>details</code>?</summary>
    <div class="content">
      <div class="content-inner">
        <p>По клику на <summary> браузер сам скрывает/показывает контент и обновляет состояние для доступности.</p>
      </div>
    </div>
  </details>

  <details class="faq-item">
    <summary>Можно ли стилизовать маркер?</summary>
    <div class="content">
      <div class="content-inner">
        <p>Да. Скрываем стандартный маркер и рисуем свой через псевдоэлемент.</p>
      </div>
    </div>
  </details>

  <details class="faq-item">
    <summary>Будет ли это решение доступным?</summary>
    <div class="content">
      <div class="content-inner">
        <p>Да, элементы поддерживают клавиатуру и скринридеры из коробки.</p>
      </div>
    </div>
  </details>
</section>
.faq { max-width: 720px; margin: 2rem auto; padding: 0 1rem; }
.faq-item { border: 1px solid #e5e7eb; border-radius: 12px; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.04); }
.faq-item + .faq-item { margin-top: 12px; }

/* Сводим маркер к нулю и делаем кликабельную шапку */
.faq-item summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: .75rem; padding: 1rem 1.25rem; font-weight: 600; }
.faq-item summary::-webkit-details-marker { display: none; }

/* Кастомный индикатор раскрытия */
.faq-item summary::before { content: '▸'; display: inline-block; transition: transform .2s ease; color: #6b7280; }
.faq-item[open] summary::before { transform: rotate(90deg); }

/* Фокус и hover состояния */
.faq-item summary:hover { background: #f9fafb; }
.faq-item summary:focus-visible { outline: 3px solid #93c5fd; outline-offset: 2px; border-radius: 10px; }

/* Плавное раскрытие контента (CSS Grid trick) */
.faq-item .content { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .25s ease; }
.faq-item[open] .content { grid-template-rows: 1fr; }
.faq-item .content-inner { overflow: hidden; }
.faq-item .content-inner { padding: 0 1.25rem 1rem; color: #374151; }

Трюк с grid-template-rows даёт плавное открытие/закрытие без JS. Внутренний контейнер .content-inner не даёт контенту «выпрыгнуть» во время анимации.

Доступность (a11y) и UX‑советы

  • <summary> должен быть кратким и информативным — это интерактивный заголовок секции.
  • Не вкладывайте в <summary> другие кнопки/ссылки: кликабельная область должна быть единой и предсказуемой.
  • Не дублируйте aria-атрибуты (aria-expanded и т. п.) — браузер делает это сам.
  • Заголовки h1–h6 нельзя помещать внутрь <summary> (они не относятся к «phrasing content»). Используйте жирный текст или подходящий стиль CSS, если нужен «вид» заголовка.
  • Клавиатура: проверьте Tab/Enter/Space. Фокус-стиль делайте заметным (пример выше).
  • Продвинутая стилизация: тени, разделители, состояния

    /* Разделитель между вопросом и ответом */
    .faq-item[open] summary { border-bottom: 1px solid #f3f4f6; }
    
    /* Состояние «открыт»: меняем цвет заголовка */
    .faq-item[open] summary { color: #111827; }
    
    /* Тёмная тема (пример) */
    @media (prefers-color-scheme: dark) {
      .faq-item { background: #111827; border-color: #1f2937; box-shadow: none; }
      .faq-item summary { color: #e5e7eb; }
      .faq-item .content-inner { color: #d1d5db; }
    }
    

    Частые ошибки и как их избежать

  • Использование div+JS вместо нативных <details>: вы теряете доступность и усложняете код без причины.
  • Забытый <summary>: без него блок не сворачивается и теряется смысл элемента.
  • Иконка-маркер без индикатора состояния: обязательно показывайте «раскрыто/свернуто».
  • Слишком длинный <summary>: сократите формулировки — это улучшит кликабельность и мобильный UX.
  • SEO: индексируется ли скрытый контент?

    Да. По актуальным рекомендациям Google контент в раскрывающихся блоках (аккордеонах, вкладках) учитывается при мобильной индексации наравне с видимым, если он предназначен для удобства пользователя. Поэтому <details> подходит для FAQ, схем и длинных инструкций. Главное — не прятать «спам» и оставаться полезными.

    Наследуемые и вложенные блоки

    <details> можно вкладывать друг в друга, но делайте это умеренно, чтобы не запутать пользователей. Пример вложенного спойлера:

    <details>
      <summary>Продвинутый раздел</summary>
      <p>Общее описание.</p>
      <details>
        <summary>Подраздел</summary>
        <p>Детали для любопытных.</p>
      </details>
    </details>
    

    Режим «только один пункт открыт» (необязательно)

    Нативно <details> не умеет ограничивать одновременное раскрытие элементов. Если вам принципиально нужно поведение «аккордеон с одним открытым пунктом», добавьте небольшой JS (прогрессивное улучшение).

    document.addEventListener('click', function(e) {
      const summary = e.target.closest('summary');
      if (!summary) return;
      const current = summary.parentElement;
      const container = current.closest('.faq');
      if (!container) return;
      container.querySelectorAll('details[open]').forEach(d => {
        if (d !== current) d.removeAttribute('open');
      });
    });
    

    Это улучшение не ломает базовую доступность: если JS отключён, элементы продолжают работать независимо друг от друга.

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

  • Для важных блоков оставляйте первый пункт открытым по умолчанию атрибутом open — так повысите вовлечённость.
  • Тестируйте на мобильных: размер кликабельной области у <summary> должен быть не меньше 44×44 px по рекомендациям WCAG/Apple/Google.
  • Подбирайте контраст для текста и иконок; добавляйте состояние :focus-visible и :hover.
  • Следите, чтобы анимации были быстрыми (200–300 мс) и не мешали читабельности контента.
  • Где потренироваться и закрепить навыки

    Хотите уверенно верстать такие блоки, собирать полноценные страницы и проекты? Посмотрите практический курс по вёрстке:
    Прокачать вёрстку на курсе «Вёрстка сайта с нуля 2.0» ↗ — много практики, разбор типовых паттернов и проверка домашних работ.

    Итог

    Элементы <details> и <summary> — простой, доступный и SEO‑дружественный способ сделать аккордеон без JavaScript. Используйте их для FAQ, спойлеров и документации, стилизуйте маркер, добавляйте аккуратную анимацию и помните о доступности. Такой подход снижает сложность кода и улучшает производительность интерфейса.

    Источник

    НЕТ КОММЕНТАРИЕВ

    Оставить комментарий