Опубликовано: 6 ноября 2024 г.
Начиная с Chrome 131, у вас появилось больше возможностей для стилизации структуры элементов <details>
и <summary>
. Теперь вы можете использовать эти элементы при создании виджетов раскрытия или аккордеона.
В частности, изменения, представленные в Chrome 131, позволяют использовать свойство display
для этих элементов и добавлять псевдоэлемент ::details-content
для стилизации части, которая расширяется и сворачивается.
Поддержка браузера
Настройка display
элемента <details>
Исторически было невозможно изменить тип отображения элемента <details>
. Это ограничение теперь смягчено, что позволяет вам, например, использовать сетку или гибкий макет для элемента <details>
.
В следующем примере эксклюзивный аккордеон состоит из нескольких элементов <details>
, расположенных рядом. При раскрытии одного из элементов <details>
его содержимое размещается рядом с <summary>
.
Демо
Запись
Это достигается за счет использования гибкого макета элемента <details>
с использованием следующего CSS:
details {
display: flex;
flex-direction: row;
}
Также разрешены другие отображаемые значения, такие как grid
.
Примечание по использованию display: inline
display
значение, которое может иметь неожиданный результат, является inline
. Не потому, что это не работает, а из-за ограничений парсера HTML.
При размещении элемента <details>
внутри абзаца он заставляет анализатор HTML сначала закрыть открытый абзац, как определено в разделе 13.2.6.4.7 стандарта HTML :
Начальный тег, имя которого является одним из следующих: «адрес», «статья», «в стороне», «блоковая цитата», «центр», «подробности», «диалог», «дир», «дел», «дл», «fieldset», «figcaption», «figure», «footer», «header», «hgroup», «main», «menu», «nav», «ol», «p», «search», «section» ", "резюме", "ул"
Если в стеке открытых элементов есть элемент ap в области действия кнопки, закройте элемент ap. Вставьте элемент HTML для токена.
В результате <details>
перемещается в направлении блока, независимо от того, установили ли вы display: inline
.
Например, следующая разметка
<p>Hello <details>…</details> world</p>
Получается после разбора:
<p>Hello </p><details>…</details> world<p></p>
Вы можете убедиться в этом сами, проверив разобранную разметку с помощью Chrome DevTools.
Обратите внимание, что это применимо только к вложению <details>
внутри <p>
. Использование display: inline
в <details>
внутри <div>
работает нормально.
Псевдо ::details-content
В браузерах элемент <details>
реализован с помощью Shadow DOM . Он содержит один <slot>
для сводки (с дочерним элементом сводки по умолчанию) и <slot>
для всего остального содержимого, то есть всех дочерних элементов элемента <details>
, кроме элемента <summary>
.
<details>
↳ #shadow-root (user-agent)
<slot id="details-summary">
<summary>Details</summary>
<!-- The summary goes here -->
</slot>
<slot id="details-content">
<!-- All content goes here -->
</slot>
</details>
Помимо использования большего количества типов отображения в <details>
, слот контента теперь можно настроить с помощью псевдоэлемента ::details-content
. Вы можете использовать этот псевдоним для стилизации контейнера, который обертывает содержимое элемента <details>
.
details::details-content {
border: 5px dashed hotpink;
}
Чтобы применить заданный стиль только тогда, когда элемент <details>
находится в открытом состоянии, добавьте к нему селектор [open]
.
[open]::details-content {
border: 5px dashed hotpink;
}
Рекомендуется применять стиль к псевдо-контенту ::details-content
только тогда, когда элемент <details>
находится в состоянии [open]
.
Демо
Запись
В таблице стилей UA для типа display
::details-content
установлено значение block
, тогда как раньше это было display: contents
. В некоторых случаях это изменение может сработать против вас, например, если раскрываемый контент зависит от height: 100%
. Если для вас это проблема, вы можете обойти ее, вернув тип display
contents
, например: details[open]::details-content { display: contents; }
.
Анимация псевдо- ::details-content
Вы можете анимировать содержимое элемента <details>
по мере его расширения. В следующем примере ширина анимируется от 0px
до 300px
.
::details-content {
transition: width 0.5s ease, content-visibility 0.5s ease allow-discrete;
width: 0;
}
[open]::details-content {
width: 300px;
}
Помимо изменения width
, необходимо также изменить свойство content-visibility
. Это связано с тем, что его значение меняется между неоткрытым и открытым состоянием, как определено в таблице стилей User-Agent. Поскольку это свойство является дискретно анимируемым, вам нужно ключевое allow-discrete
чтобы оно работало.
Если добавить к эксклюзивной демонстрации аккордеона, представленной ранее, результат будет таким:
Демо
Запись
height
также можно анимировать. Чтобы анимировать по height: auto
, вам нужно использовать interpolate-size
или calc-size()
. Кроме того, чтобы предотвратить утечку содержимого из псевдо-контента ::details-content
, примените к нему overflow: clip
.
::details-content {
transition: height 0.5s ease, content-visibility 0.5s ease allow-discrete;
height: 0;
overflow: clip;
}
/* Browser supports interpolate-size */
@supports (interpolate-size: allow-keywords) {
:root {
interpolate-size: allow-keywords;
}
[open]::details-content {
height: auto;
}
}
/* Fallback for browsers with no interpolate-size support */
@supports not (interpolate-size: allow-keywords) {
[open]::details-content {
height: 150px;
overflow-y: scroll; /* In case the contents should be taller than 150px */
}
}
Вы можете увидеть код в действии в следующей демонстрации, вдохновленной аккордеоном Material UI . Содержимое каждого элемента <details>
красиво анимируется.
Демо
Запись
В браузерах без поддержки ::details-content
компонент по-прежнему работает нормально. Единственное, чего посетители не видят, — это анимацию.
Обнаружение функций
Чтобы обеспечить поддержку псевдо-контента ::details-content
в CSS, используйте следующий фрагмент.
@supports selector(::details-content) {
…
}
Вы также можете использовать это обнаружение в качестве контрольной проверки, чтобы выяснить, поддерживает ли браузер, который использует ваш посетитель, дополнительные отображаемые значения или нет.
Соображения доступности
Введение псевдоэлемента ::details-content
и возможность изменения типа отображения не влияют на доступность элемента <details>
.
Как и раньше, по крайней мере, в браузерах на базе Chromium и в соответствии со стандартом HTML , элемент <details>
доступен для поиска и автоматически расширяется, когда браузер пытается прокрутить его до скрытого содержимого в ответ на поиск на странице, ScrollToTextFragment и навигацию по фрагменту элемента. . Это не меняется.
Однако, прежде чем использовать эксклюзивные аккордеоны, подумайте, будет ли это полезно или вредно для пользователей. Хотя использование эксклюзивного аккордеона уменьшает объем визуального пространства, занимаемого контентом, пользователям, возможно, придется открывать множество элементов, чтобы получить всю информацию. Это может расстроить пользователей, которые хотят просматривать несколько элементов одновременно.
А как насчет стилизации маркера?
В настоящее время стиль маркера списка несовместим, поскольку существует два разных подхода: один используется Gecko и (текущий) Chromium, а другой — WebKit (который ранее использовался совместно с Chromium).
Как только эта функция станет интероперабельной, наша цель — предоставить вам лучший контроль над стилем маркера.
Больше демонстраций
В заключение, вот еще несколько демо-версий, которые вы можете проверить. Все они используют ::details-content
.
UIKit Аккордеон
Демо
Запись
Эта демонстрация построена на основе UIKit Accordion . Код практически такой же, как и аккордеон Material UI, который был опубликован ранее.
Частично открытый виджет раскрытия
Демо
Запись
В этой демонстрации представлен частично открытый виджет раскрытия, содержимое которого уже видно на экране. Чтобы добиться этого, для content-visibility
всегда установлено значение visible
. height
анимируется с помощью calc-size()
поскольку здесь требуется вычисление.
::details-content {
content-visibility: visible; /* Make it always visible */
transition: height 0.5s ease;
height: 150px;
overflow: clip;
}
[open]::details-content {
height: calc-size(auto, size + 0.5rem); /* calc-size because we need to add a length */
}
Для удобства стилизации содержимое заключено в обертку div. В элементе-обертке применяются стили макета, такие как padding
, а псевдо-элемент ::details-content
анимируется.