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

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

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

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

Browser Support

  • Хром: 131.
  • Край: 131.
  • Firefox: 143.
  • Сафари: 18.4.

Source

Настройка 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 :

Начальный тег, имя которого может быть одним из следующих: "address", "article", "aside", "blockquote", "center", "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p", "search", "section", "summary", "ul"

Если в стеке открытых элементов есть элемент 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> для краткого содержания (с дочерним элементом summary по умолчанию) и один <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> доступен для поиска и автоматически раскрывается при прокрутке браузером до его скрытого содержимого в ответ на команды find-in-page, 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-оболочку. К div-оболочке применяются стили макета, такие как padding , а псевдоэлемент ::details-content анимирован.