Więcej opcji stylizacji <details>

Opublikowano: 6 listopada 2024 r.

Od Chrome 131 masz więcej opcji stylizowania struktury elementów <details><summary>. Możesz teraz używać tych elementów podczas tworzenia widżetów ujawniania informacji lub widżetów akordeonowych.

W szczególności zmiany wprowadzone w Chrome 131 umożliwiają używanie właściwości display w tych elementach i dodają pseudoelement ::details-content, który pozwala określać styl części, która się rozwija i zwija.

Browser Support

  • Chrome: 131.
  • Edge: 131.
  • Firefox: 143.
  • Safari: 18.4.

Source

Ustawienie display w elemencie <details>

W przeszłości nie można było zmienić typu wyświetlania elementu <details>. To ograniczenie zostało obecnie złagodzone, dzięki czemu możesz na przykład używać układów siatki lub flex w elemencie <details>.

W poniższym przykładzie wyłączny akordeon składa się z kilku elementów <details> umieszczonych obok siebie. Po rozwinięciu jednego z elementów <details> jego treść jest umieszczana obok elementu <summary>.

Prezentacja

Nagrywanie

Nagranie https://codepen.io/web-dot-dev/pen/VwoBQjY w Chrome 131

Można to osiągnąć, stosując układ elastyczny w elemencie <details> za pomocą tego kodu CSS:

details {
  display: flex;
  flex-direction: row;
}

Dozwolone są też inne wartości wyświetlane, np. grid.

Uwaga dotycząca korzystania z display: inline

Wartość display, która może mieć nieoczekiwany wynik, to inline. Nie dlatego, że nie działa, ale z powodu ograniczeń parsera HTML.

Umieszczenie elementu <details> w akapicie wymusza na parserze HTML zamknięcie otwartego akapitu, zgodnie z definicją w sekcji 13.2.6.4.7 standardu HTML:

Tag otwierający, którego nazwa to: „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”.

Jeśli stos otwartych elementów zawiera element p w zakresie przycisku, zamknij element p. Wstaw element HTML dla tokena.

W efekcie przepływ <details> odbywa się w kierunku bloku, niezależnie od ustawienia display: inline.

Na przykład ten kod:

<p>Hello <details>…</details> world</p>

Po przetworzeniu wygląda tak:

<p>Hello </p><details>…</details> world<p></p>

Możesz to sprawdzić w tym demo, analizując przeanalizowany kod za pomocą Narzędzi deweloperskich w Chrome.

Pamiętaj, że dotyczy to tylko zagnieżdżania elementu <details> w elemencie <p>. Użycie display: inline na <details> wewnątrz <div> działa prawidłowo.

Pseudoklasa ::details-content

W przeglądarkach element <details> jest implementowany za pomocą Shadow DOM. Zawiera jeden element <slot> dla podsumowania (z domyślnym elementem podrzędnym podsumowania) i jeden element <slot> dla pozostałych treści, czyli wszystkich elementów podrzędnych elementu <details> z wyjątkiem elementu <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>

Oprócz używania większej liczby typów wyświetlania w <details> można teraz kierować na miejsce na treść za pomocą pseudoelementu ::details-content. Za pomocą tego pseudoselektora możesz określić styl kontenera, który otacza zawartość elementu <details>.

details::details-content {
  border: 5px dashed hotpink;
}

Aby zastosować ustawiony styl tylko wtedy, gdy element <details> jest otwarty, dodaj do niego selektor [open].

[open]::details-content {
  border: 5px dashed hotpink;
}

Zalecamy stosowanie stylów do pseudoklasy ::details-content tylko wtedy, gdy element <details> jest w stanie [open].

Prezentacja

Nagrywanie

Nagranie https://codepen.io/web-dot-dev/pen/oNKMEYv w Chrome 131

Typ display atrybutu ::details-content ma w arkuszu stylów UA wartość block, a wcześniej miał wartość display: contents. W niektórych przypadkach ta zmiana może być niekorzystna, np. w przypadku ujawnionych treści opartych na height: 100%. Jeśli to dla Ciebie problem, możesz go obejść, ustawiając typ display z powrotem na contents, np. details[open]::details-content { display: contents; }.

Animowanie ::details-content pseudo

Możesz animować treść elementu <details> podczas jej rozwijania. W poniższym przykładzie szerokość zmienia się z 0px na 300px.

::details-content {
  transition: width 0.5s ease, content-visibility 0.5s ease allow-discrete;
  width: 0;
}

[open]::details-content {
  width: 300px;
}

Oprócz przeniesienia width musisz też przenieść właściwość content-visibility. Dzieje się tak, ponieważ jego wartość zmienia się w zależności od tego, czy element jest otwarty, czy nie, zgodnie z arkuszem stylów User-Agent. Ponieważ ta właściwość jest właściwością, którą można animować dyskretnie, aby działała, musisz użyć słowa kluczowego allow-discrete.

Po dodaniu do udostępnionej wcześniej wersji demonstracyjnej akordeonu wynik będzie wyglądać tak:

Prezentacja

Nagrywanie

Nagranie https://codepen.io/web-dot-dev/pen/XWvBZNo w Chrome 131

Symbol height może być też animowany. Aby animować do height: auto, musisz użyć interpolate-size lub calc-size(). Aby zapobiec wyciekaniu treści z elementu pseudoklasy ::details-content, zastosuj do niej właściwość 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 */
    }
}

Kod w działaniu możesz zobaczyć w tym demo, które zostało zainspirowane akordeonem Material UI. Zawartość każdego elementu <details> jest płynnie animowana.

Prezentacja

Nagrywanie

Nagranie https://codepen.io/web-dot-dev/pen/ExqpQZM w Chrome 131

W przeglądarkach, które nie obsługują ::details-content, komponent nadal działa prawidłowo. Jedyną rzeczą, której nie zobaczą odwiedzający, jest animacja.

Wykrywanie cech

Aby wykryć obsługę pseudoklasy ::details-content w CSS, użyj tego fragmentu kodu.

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

Możesz też użyć tego wykrywania jako testu, aby sprawdzić, czy przeglądarka używana przez odwiedzającego obsługuje dodatkowe wartości wyświetlania.

Względy dotyczące ułatwień dostępu

Wprowadzenie pseudoelementu ::details-content i możliwość zmiany typu wyświetlania nie wpływa na dostępność elementu <details>.

Podobnie jak wcześniej, przynajmniej w przeglądarkach opartych na Chromium i zgodnie ze standardem HTML element <details> można wyszukiwać i automatycznie rozwija się, gdy przeglądarka próbuje przewinąć do jego ukrytej zawartości w odpowiedzi na wyszukiwanie na stronie, ScrollToTextFragment i nawigację po fragmencie elementu. To się nie zmienia.

Zanim jednak użyjesz wyłącznych akordeonów, zastanów się, czy będą one przydatne dla użytkowników. Używanie ekskluzywnego akordeonu zmniejsza ilość miejsca zajmowanego przez treści, ale użytkownicy mogą musieć otworzyć wiele elementów, aby zapoznać się ze wszystkimi informacjami. Może to frustrować użytkowników, którzy chcą wyświetlić kilka produktów jednocześnie.

A co ze stylem znacznika?

Obecnie stylizacja znacznika listy nie jest interoperacyjna, ponieważ istnieją 2 różne podejścia: jedno stosowane przez Gecko i (obecnie) Chromium, a drugie przez WebKit (które było wcześniej udostępniane Chromium).

Gdy ta funkcja będzie działać w sposób interoperacyjny, chcemy dać Ci większą kontrolę nad stylem znacznika.

Więcej wersji demonstracyjnych

Na zakończenie przedstawiamy kilka dodatkowych prezentacji, które możesz obejrzeć. Wszystkie korzystają z ::details-content.

Komponent akordeonu w UIKit

Prezentacja

Nagrywanie

Nagranie https://codepen.io/web-dot-dev/pen/rNXrJyQ w Chrome 131

Ta wersja demonstracyjna jest oparta na akordeonie UIKit. Kod jest praktycznie taki sam jak akordeon Material UI, który został udostępniony wcześniej.

Częściowo otwarty widżet z informacjami

Prezentacja

Nagrywanie

Nagranie https://codepen.io/web-dot-dev/pen/PoMBQmW w Chrome 131

Prezentacja przedstawia częściowo otwarty widżet ujawniania, którego zawartość jest już widoczna na ekranie. Aby to osiągnąć, wartość content-visibility jest zawsze ustawiona na visible. height jest animowany za pomocą calc-size(), ponieważ obejmuje obliczenia.

::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 */
}

Aby ułatwić stylizację, treść jest zawarta w divie opakowującym. Div opakowujący otrzymuje style układu, takie jak padding, a pseudo-element ::details-content jest animowany.