Дополнительные возможности оформления <details>

Опубликовано: 6 ноября 2024 г.

Начиная с Chrome 131, у вас появилось больше возможностей для стилизации структуры элементов <details> и <summary> . Теперь вы можете использовать эти элементы при создании виджетов раскрытия или аккордеона.

В частности, изменения, внесенные в Chrome 131, позволяют использовать свойство display для этих элементов и добавлять псевдоэлемент ::details-content для стилизации части, которая расширяется и сворачивается.

Поддержка браузера

  • Хром: 131.
  • Край: 131.
  • Firefox: не поддерживается.
  • Сафари: не поддерживается.

Настройка display элемента <details>

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

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

Демо

Запись

Запись https://codepen.io/web-dot-dev/pen/VwoBQjY в Chrome 131

Это достигается за счет использования гибкого макета элемента <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] .

Демо

Запись

Запись https://codepen.io/web-dot-dev/pen/oNKMEYv в Chrome 131

В таблице стилей 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 чтобы оно работало.

Если добавить к эксклюзивной демонстрации аккордеона, представленной ранее, результат будет таким:

Демо

Запись

Запись https://codepen.io/web-dot-dev/pen/XWvBZNo в Chrome 131

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> прекрасно анимируется.

Демо

Запись

Запись https://codepen.io/web-dot-dev/pen/ExqpQZM в Chrome 131

В браузерах без поддержки ::details-content компонент по-прежнему работает нормально. Единственное, чего посетители не видят, — это анимацию.

Обнаружение функций

Чтобы обеспечить поддержку псевдо-контента ::details-content в CSS, используйте следующий фрагмент.

@supports selector(::details-content) {
  
}

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

Соображения доступности

Введение псевдоэлемента ::details-content и возможность изменения типа отображения не влияют на доступность элемента <details> .

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

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

А как насчет стилизации маркера?

В настоящее время стиль маркера списка несовместим, поскольку существует два разных подхода: один используется Gecko и (текущий) Chromium, а другой — WebKit (который ранее использовался совместно с Chromium).

Как только эта функция станет интероперабельной, наша цель — предоставить вам лучший контроль над стилем маркера.

Больше демонстраций

В заключение, вот еще несколько демо-версий, которые вы можете проверить. Все они используют ::details-content .

UIKit Аккордеон

Демо

Запись

Запись https://codepen.io/web-dot-dev/pen/rNXrJyQ в Chrome 131

Эта демонстрация построена на основе UIKit Accordion . Код практически такой же, как и аккордеон Material UI, который был опубликован ранее.

Частично открытый виджет раскрытия

Демо

Запись

Запись https://codepen.io/web-dot-dev/pen/PoMBQmW в Chrome 131

В этой демонстрации представлен частично открытый виджет раскрытия, содержимое которого уже видно на экране. Чтобы добиться этого, для 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 анимируется.