<details> , <summary>
Нативный раскрывающийся блок с контентом без магии и JavaScript.
Время чтения: меньше 5 мин
- Кратко
- Пример
- Как понять
- Как пишется
- Подсказки
- На практике
- Лена Райан советует
- Татьяна Фокина советует
Обновлено 26 октября 2022
Кратко
Скопировать ссылку на секцию «Кратко» Скопировано
Блок с раскрывающимся контентом на чистом HTML.
Пример
Скопировать ссылку на секцию «Пример» Скопировано
Самый простой раскрывающийся блок выглядит вот так:
Как понять
Скопировать ссылку на секцию «Как понять» Скопировано
Иногда нужно скрывать какую-то информацию на странице в специальном блоке. Чтобы в любой момент можно было кликнуть на этот блок и развернуть информацию. И свернуть обратно таким же кликом. Такой блок ещё называют «аккордеоном».
Как пишется
Скопировать ссылку на секцию «Как пишется» Скопировано
Тег <details> — это интерактивный элемент, при нажатии на который открывается блок с информацией — текстом или картинками. Нередко такие элементы можно встретить на страницах с часто задаваемыми вопросами (FAQ), где в заголовке (или легенде) написан вопрос, а ответом является содержимое «аккордеона».
Тег <summary> — это заголовок «аккордеона», так называемая легенда. Он необязателен — без него в качестве легенды будет написан текст «Подробнее», «Details» или нечто подобное — в зависимости от выбранного языка и браузера.
Собирается «аккордеон» очень просто: в <details> вкладываем <summary> и теги с информацией, которая будет показываться при нажатии.
По умолчанию «аккордеон» закрыт, но если мы хотим, чтобы его содержание показывалось сразу при загрузке страницы или открывать его из JavaScript, нужно добавить к нему атрибут open .
Подсказки
Скопировать ссылку на секцию «Подсказки» Скопировано
Можно вкладывать <details> в <details> .
<details> — это интерактивный элемент, но вкладывать другие интерактивные элементы в него можно.
В HTML-стандарте написано, что <summary> должен быть первым ребёнком в <details> , но на деле всё прекрасно работает, даже если <summary> находится между тегами содержательной части «аккордеона».
Вёрстка не ломается, если вложить <summary> в <summary> — в таком случае будет только один элемент : : marker (треугольник перед легендой).
Если в «аккордеоне» будет несколько <summary> подряд, браузер будет реагировать только на первый, а остальные даже не отобразятся, хотя будут стоять в разметке.
Если указать просто <summary> без <details> , то он будет вести себя как обычный <div> — блочный элемент без интерактивности.
На практике
Скопировать ссылку на секцию «На практике» Скопировано
Лена Райан советует
Скопировать ссылку на секцию «Лена Райан советует» Скопировано
Если присутствует тег <summary> , то псевдоэлемент : : marker можно стилизовать — правда, он реагирует не на все свойства, но как минимум вы сможете поменять цвет и размер шрифта. Раньше для его стилизации нужно было использовать : : — webkit — details — marker .
Татьяна Фокина советует
Скопировать ссылку на секцию «Татьяна Фокина советует» Скопировано
Можно заменить иконку по умолчанию с помощью <img> . В этом случае оставьте значение атрибута alt пустым, так как это декоративное изображение.
У <summary> есть встроенная роль button . На практике скринридеры определяют роль тега по-разному. NVDA считает его кнопкой, Narrator — раскрывающим треугольником (disclosure triangle), десктопный VoiceOver — саммари (summary), а TalkBack в Firefox и мобильный VoiceOver в Safari вообще не определяют роль <summary> .
Можно использовать явную роль button для <summary> , но так лучше не делать:
- Это не та ситуация, где стоит явно задавать ARIA-роль и нарушать одно из правил использования WAI-ARIA.
- VoiceOver перестанет определять состояние <details> — развёрнут или свёрнут элемент.
- Не решит проблему с неопределяемой ролью <details> для TalkBack в Firefox и мобильного VoiceOver в Safari.
Если заменить на свою иконку с треугольником по умолчанию у <summary> , это может привести к проблемам с объявлением VoiceOver, NVDA и JAWS состояния, в котором сейчас находится элемент.
В Firefox есть баг, из-за которого VoiceOver читает название иконки по умолчанию и считает его частью имени элемента — краткого названия, которое скринридеры объявляют вместе с ролью.
VoiceOver в Safari и JAWS в Chrome, Edge или Firefox не считают <h1> – <h6> заголовками, если они вложены в <summary> .
Может показаться, что <details> и <summary> подходят для выпадающего меню. Они ведут себя похоже, но это не самое доступное решение. Вот несколько причин:
Создаем блоки раскрывающегося текста на HTML, CSS и JavaScript
В этой статье описывается, как без использования сторонних библиотек с помощью HTML, CSS и JavaScript создать раскрывающийся текст. Вот как этот элемент интерфейса выглядит в действии.
Подходы
Для создания подобных панелей расширения используется несколько подходов:
- На основе анимации и переходов, примененных к свойствам height или max-height контента.
- Использование transform: translateY для перемещения элементов на новую позицию, создания эффекта закрытия панели и повторной визуализации DOM.
- Применение сторонней библиотеки.
Какой из подходов лучше?
С точки зрения производительности использование transform более эффективно, чем анимация height и max-height. При применении CSS-свойства transform элементы растризуются и перемещаются графическим процессором. Это низко затратная и простая операция для графического процессора.
Для реализации данного подхода нужно выполнить следующие действия:
- Получить высоту контента, который будет располагаться на панели.
- Переместить контент выше на высоту содержимого, которое будет свернуто с помощью transform: translateY(Xpx). С помощью перехода реализовать эффект открытия и закрытия панели.
- С помощью JavaScript перехватить событие transitionend. После его наступления задаем display: none для контента и удаляем преобразование.
Но у данного метода есть множество недостатков. Например, при использовании transform: translateY необходимо учитывать z-index элемента.
Поэтому проще с помощью JavaScript обернуть все, что вы хотите переместить, в контейнер и переместить его. Вот пример использования данного подхода.
Применение переходов к max-height работает не так хорошо, как свойство transform. Так как браузер изменяет высоту сворачивающегося элемента на протяжении всего перехода. Эта операция потребляет много ресурсов памяти и графического процессора. Но зато данный подход проще в реализации.
Подход на основе элементов details и summary
В HTML существуют элементы details и summary, которые позволяют создать панель расширения:
Кроме этого элемент details поддерживает JavaScript-событие toggle. Поэтому можно изменять HTML в зависимости от того, скрыто или отображается содержимое панели.
Но элементы details и summary не анимируются и к ним нельзя применять переходы. Поэтому используем другие средства.
Шаблон разметки
Основная разметка будет выглядеть следующим образом:
У нас есть внешний контейнер, который оборачивает расширяемый блок. Первым элементом является кнопка. За ней идет блок содержимого, которое будет скрываться, и отображаться с помощью пользовательских свойств CSS, переходов и JavaScript.
Базовая логика
- После загрузки веб-страницы измеряем высоту содержимого.
- Устанавливаем высоту содержимого в контейнере в качестве значения пользовательского свойства CSS.
- Скрываем содержимое, добавив к нему атрибут aria-hidden: «true».
- Устанавливаем max-height в качестве значения пользовательского свойства.
- Нажатие кнопки изменяет значение свойства aria-hidden с true на false. А также max-height содержимого с 0 на высоту, заданную в пользовательском свойстве. Затем с помощью переходов реализуем визуальный эффект.
JavaScript-код
Как насчет нескольких блоков?
Если на странице есть несколько раскрывающихся блоков, то нужно будет перебрать их все. Но только в том случае, если они разного размера. Для этого используйте querySelectorAll, чтобы получить все контейнеры и повторно задать пользовательские переменные через forEach.
setTimeout
Метод setTimeout с продолжительностью 0 до вывода контейнера используется для первоначального вывода веб-страницы. Это позволяет получить высоту контента.
Когда страница готова
Кроме этого можно обернуть код блока в функцию, которая инициализируется при загрузке страницы. Например:
Мы добавим ее в ближайшее время.
Дополнительные атрибуты data для контейнера
Мы добавляем атрибут data тогда, нужно что-то нужно изменить, когда панель открывается / закрывается. Например, цвет какого-то элемента.
Значение по умолчанию для пользовательского свойства
По умолчанию для пользовательского свойства установлено значение 1000px. Оно указывается после запятой внутри значения: var(—containerHeight, 1000px). Вы можете установить другое значение.
Почему бы не использовать значение по умолчанию 10000000px?
Проблема заключается в том, что переход всегда будет выполняться от этой высоты. Если длительность перехода установлена в 1 сек., переход будет выполняться со скоростью 10000000 пикселей в секунду. Если контент имеет высоту всего 50px, то вы получите довольно быстрый эффект открытия / закрытия.
Тернарный оператор для переключателей
Тернарный оператор является укороченной формой if / else. В нем сначала указывается условие, которое нужно проверить. Затем ? отделяет код для выполнения, если true. После : идет код, который будет выполняться, если проверка ложна.
Что происходит при изменении размера окна браузера?
При изменении размера окна браузера высота контента тоже может измениться. В подобном случае придется повторно установить высоту контейнеров. Для этого можно использовать две функции: одну – для установки высоты, другую – для взаимодействия. А также добавить для окна браузера два прослушивателя: для перехвата события загрузки страницы и события изменения размера.
Повышаем доступность (Accessibility)
Чтобы повысить доступность создаваемой панели, используйте атрибуты aria-expanded, aria-controls и aria-labelledby. Это даст вспомогательным технологиям лучшее представление о том, когда панели будут открыты / раскрыты. Мы добавляем aria-expanded=»false» к кнопке и aria-controls=»IDofcontent», где IDofcontent — это идентификатора контейнера с контентом.
Затем мы используем другой тернарный оператор для переключения в JavaScript атрибута aria-expanded по клику.
Все вместе
Полная версия JavaScript-кода примера:
Вы также можете поэкспериментировать с кодом, размещенным на CodePen
Заключение
Возможно, это не самый эффективный метод реализации панелей расширения. Но для большинства ситуаций он подходит.
Вадим Дворников автор-переводчик статьи « Make Your Own Expanding And Contracting Content Panels »
Справка:Сворачивание
Сворачивание позволяет скрыть любой элемент на странице с помощью специальной кнопки «свернуть/развернуть». Это также можно использовать для крупных таблиц и текстов.
Данную функцию полезно использовать, когда страница содержит очень много информации, часть из которой востребована только в некоторых случаях. Иногда сворачивание полезно, чтобы скрыть спойлеры или крупные навигационные таблицы (например, см. эту статью)
Содержание
Сворачивание таблицы
Добавьте код « mw-collapsible » как класс, чтобы в таблице появилась ссылка «свернуть/развернуть».
Цифра Буква 1 A 2 Б 3 В Сворачивание текста
Аналогично можно этот класс использовать для сворачивания текста внутри статьи.
Этот текст можно свернуть.
Свёрнутая по умолчанию таблица
Чтобы таблица изначально была свёрнута, используйте двойной код: « mw-collapsed » и « mw-collapsible ». Пример:
Заголовок всегда будет виден Содержимое всегда будет скрыто Скрытие спойлеров в тексте
Скрыть текст внутри статьи можно, используя двойной код: указанный в предыдущем разделе с добавлением кода « mw-collapsible-content ».
Этот текст предшествует скрытому тексту.
Настройка текста «свернуть/развернуть»
Можно добавить свой текст вместо стандартного «свернуть/развернуть». Для этого используйте код « data-expandtext » и « data-collapsetext ».
Цифра Буква 1 A 2 Б Кнопка «свернуть/развернуть»
Как вы заметили, ссылка «свернуть/развернуть» увеличивает ширину колонки таблицы, где она находится. Этого можно избежать, если вынести переключатель за пределы таблицы, что удобно сделать с помощью кнопки.
Если присвоить переключателю значение » mw-customcollapsible-myTable «, то при использовании кода » mw-customtoggle-myTable » это можно осуществить следующим образом:
Аккордеон, faq, спойлер и другие раскрывающиеся виджеты
Поддерживается всеми современными браузерами и это семантически правильно оформленный код, при использовании которого будут плюсы:
- Людям с ограниченными возможностями проще будет пользоваться вашим сайтом! Их софт (скринридеры и подобное) прекрасно понимает html5 теги и будет правильно обрабатывать их и правильно информировать людей о содержимом.
- Улучшится связанность текста, и поисковики смогут более качественно индексировать сайт, так как будут лучше понимать, как связаны между собой видимый и скрытый текст.
- Будет доступно управление элементами с клавиатуры и других устройств.
- Уменьшается количество javascript кода, который нужно подгружать, что увеличивает скорость загрузки страницы, скорость обработки и корректность.
- Улучшаются показатели в Lighthouse, Google PageSpeed и других подобных инструментах.
- Работает при выключенном javascript.
- Старые браузеры не знают таких тегов и не будут скрывать информацию.
С одной стороны выглядит не очень красиво, с другой стороны нейтрально и легко может вписаться во многие дизайны. Кстати, дефолтный вид тега Details очень похож на спойлер от хабра, только нужно чуть перекрасить, сделать подчеркивание и получим семантически правильный, без javascript и дивов, хабровский спойлер.
К сожалению, у дефолтного маркера есть два недостатка:
- Старые браузеры его не видят.
- Вебкит баузеры не позволяют менять символ маркера.
Рассмотрим первый пример Details/Summary с измененным текстовым маркером:
Дефолтным маркерам делаем display:none и показываем альтернативный при помощи summary:before
summary:focus — обводка при помощи box-shadow, это нужно для клавиатуры, чтоб видно было активный элемент и можно было перемещаться клавишей таб и открывать и закрывать при помощи пробела.
Для тега summary я поставил display:inline-block — это чтоб он не растягивался на всю ширину и были кликабельными только слова, а не вся строка.
Текстовый маркер справа + простейшая анимация текста и маркера:
В новом примере я использую для маркера summary:after вместо summary:before, для того чтоб он отображался справа.
Анимация маркера при помощи transform: scale(1,-1);
Всем элементам, которые находится после summary, ставлю анимацию плавного появления при помощи animation: sweep .5s ease-in-out;
Svg маркер + анимация поворота:
Summary:before пришлось серьезно переделать:
- Поставить position: absolute; left: .3em; top: .4em; width: 1em; height: 1em;
- Текстовому маркеру надо обязательно поставить color: transparent; иначе он будет виден.
- Картинку вешаем при помощи background.
Ну и добавляем transform: rotateZ(90deg) для красивого поворота стрелки.
Если нам нужна svg иконка справа, то нужно поменять summary:before и вместо left поставить right.
Для summary поставить padding-right: 1.5em;
Давайте теперь сделаем один из наиболее распространенных примеров создания аккордиона, где будет иконка слева, фон, тени, эффекты:
Svg маркер справа + эффект зеркального поворота стрелки:
Теперь вы можете создавать красивые аккордионы, спойлеры и faq, без JavaScript, на чистом HTML5 и CSS.
Прежде чем убирать outline, 100 раз подумайте, чем вы можете его заменить, чтоб человек мог видеть фокус и мог перемещаться с клавиатуры или других устройств.
Если вам нужно, чтоб при открытии одного спойлера, закрывались остальные, то придется применить javascript, ниже привожу пример простого JS кода, который решит эту проблему.
С уважением, создатель конструктора лэндингов для фрилансеров CMS cPortfolio