Перейти к содержанию

Details и summary

Виджет раскрытия - это элемент управления пользовательским интерфейсом, который скрывает и показывает содержимое. Если вы читаете эту статью на web.dev, а область просмотра имеет ширину менее 106 em, то щелчок на надписи "На этой странице" над этим абзацем откроет оглавление этого раздела. Если вы не видите его, сжимайте браузер, чтобы увидеть навигацию по оглавлению на этой странице в виде виджета раскрытия.

Аккордеон графический интерфейс пользователя представляет собой серию вертикально расположенных виджетов раскрытия информации. Часто используемым вариантом интерфейса "аккордеон" является страница часто задаваемых вопросов (FAQ) на многих сайтах. FAQ в виде аккордеона содержит список видимых вопросов; щелчок на вопросе раскрывает, или "раскрывает", ответ на него.

jQuery включает в себя паттерн пользовательского интерфейса "аккордеон", по крайней мере, с 2009 года. Оригинальное решение аккордеона без JavaScript включало в себя создание для каждого вопроса FAQ <label>, за которым следовал флажок, которым он был помечен, а затем отображение ответа <div>, когда флажок был отмечен. CSS выглядел примерно так:

1
2
3
4
5
6
7
#FAQ [type='checkbox'] + div.answer {
    /* all the answer styles */
    display: none;
}
#FAQ [type='checkbox']:checked + div.answer {
    display: block;
}

Зачем нужна история? Виджеты раскрытия информации, такие как аккордеоны, не требующие использования JavaScript или взлома элементов управления формой, появились сравнительно недавно: элементы <details> и <summary> стали полностью поддерживаться во всех современных браузерах только с января 2020 года. Теперь вы можете создавать работающие, хотя и не слишком привлекательные виджеты раскрытия информации, используя только семантический HTML. Элементы <details> и <summary> - это все, что вам нужно: они представляют собой встроенный способ обработки расширяющегося и сворачивающегося содержимого. Когда пользователь щелкает или касается элемента <summary>, или отпускает клавишу Enter, когда элемент <summary> находится в фокусе, содержимое родительского элемента <details> переключается на видимое!

Как и в случае с семантическим контентом, можно постепенно расширять стандартные возможности и внешний вид. В данном случае было добавлено немного CSS, но не более того:

Обратите внимание, что в этих кодепенах нет JavaScript.

Переключение видимости: атрибут open

Элемент <details> является контейнером виджета раскрытия информации. Элемент <summary> является сводкой или легендой для своего родителя <details>. Сводка всегда отображается, выполняя роль кнопки, переключающей отображение остального содержимого родительского элемента. Взаимодействие с <summary> переключает отображение саморазмеченных сводок, переключая атрибут open элемента <details>.

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

Поскольку атрибут open добавляется и удаляется автоматически при взаимодействии пользователя с элементом управления, он может быть использован в CSS для придания элементу различных стилей в зависимости от его состояния.

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

Скрытое содержимое в свернутом состоянии доступно для поиска в некоторых браузерах, но не в других, несмотря на то что свернутое содержимое не является частью DOM. При поиске в браузерах Edge или Chrome детали, содержащие поисковый запрос, раскрываются и отображают его. В Firefox и Safari такое поведение не воспроизводится.

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

Переключение маркера сводки

В двух предыдущих Codepens вы заметили стрелку, указывающую на inline-start сторону сводки. Виджет раскрытия информации обычно представляется на экране в виде небольшого треугольника, который вращается (или крутится), показывая состояние открытости/закрытости, а рядом с треугольником располагается метка. Содержимое элемента <summary> содержит метку виджета раскрытия информации. Вращающаяся стрелка в верхней части каждого раздела - это ::marker, установленный на элементе <summary>. Как и элементы списка, элемент <summary> поддерживает сокращенное свойство list-style и его расширенные свойства, включая list-style-type. Треугольник раскрытия можно стилизовать с помощью CSS, в том числе изменить используемый маркер с треугольника на любой другой тип пули, включая изображение с помощью list-style-image.

Для применения других стилей используйте селектор, подобный details summary::marker. Псевдоэлемент ::marker принимает только ограниченное количество стилей. Удаление ::marker и замена его более простым по стилю ::before является обычной практикой, при этом стили CSS незначительно изменяют стиль генерируемого содержимого в зависимости от наличия (или отсутствия) атрибута open. Вы можете убрать значок виджета раскрытия, задав list-style: none, или установить для content маркера значение none, но всегда включайте визуальные индикаторы, информирующие зрячих пользователей о том, что краткое содержание является кнопкой-тумблером, которая при активации показывает и скрывает содержимое.

1
2
3
4
5
6
details summary::before {
    /* all the styles */
}
details[open] summary::before {
    /* changes applied when open only */
}

В этом примере удаляется маркер по умолчанию и добавляется сгенерированное содержимое для создания знака + при закрытых деталях и знака - при открытых деталях.

Если вы хотите, чтобы блок подробностей открывался по умолчанию, включите атрибут open в открывающий тег <details>. Для улучшения внешнего вида можно также добавить пробел между каждым диалогом и изменить вращение маркера, созданного с помощью сгенерированного содержимого:

Как обрабатываются ошибки

Если вы не включите <summary>, браузер создаст его за вас: с маркером и словом "подробности". Это резюме является частью shadow root, и поэтому к нему не будут применены авторские CSS-стили резюме. К сожалению, Safari не включает подробности в порядок фокусировки клавиатуры.

Если вы включите <summary>, но он не будет первым элементом в <details>, браузер все равно отобразит резюме, как и должно быть. Браузер также не откажет, если включить в резюме ссылку, ярлык или другой интерактивный элемент, однако браузеры по-разному обрабатывают интерактивное содержимое внутри интерактивного содержимого. Например, если включить в сводку ссылку, то некоторые браузеры добавят и сводку, и ссылку в порядок табуляции по умолчанию, но другие браузеры по умолчанию не будут фокусироваться на ссылке. Если щелкнуть на <label>, вложенной в <summary>, то в некоторых браузерах фокус будет передан связанному с ней элементу управления формой; в других браузерах фокус будет передан элементу управления формой и переключит <details> на открытый или закрытый экран.

Интерфейс HTMLDetailsElement.

Как и все HTML-элементы, HTMLDetailsElement наследует все свойства, методы и события от HTMLElement, а также добавляет свойство экземпляра open и событие toggle. Свойство HTMLDetailsElement.open представляет собой булево значение, отражающее HTML-атрибут open и указывающее, должно ли содержимое элемента (не считая <summary>) быть показано пользователю. Событие toggle срабатывает при переключении элемента <details> на открытый или закрытый. Прослушать это событие можно с помощью addEventListener().

Если вы хотите написать скрипт, который будет закрывать открытые детали, когда пользователь откроет любую другую деталь, удалите атрибут open с помощью removeAttribute("open"):

Это единственный пример, в котором используется JavaScript. Скорее всего, вам не нужен JavaScript, за исключением этой функции закрытия других открытых виджетов раскрытия.

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

Источник: Details and summary

Комментарии