Więcej opcji stylizacji <details>

Opublikowano: 6 listopada 2024 r.

Od Chrome 131 w wersji 131 dostępnych jest więcej opcji określania stylu struktury elementów <details> i <summary>. Możesz teraz używać tych elementów podczas tworzenia widżetów informacji lub akordeonów.

W szczególności zmiany wprowadzone w Chrome 131 umożliwiają używanie właściwości display w tych elementach i dodawanie pseudoelementu ::details-content do stylizacji części, która się rozwija i zwija.

Obsługa przeglądarek

  • Chrome: 131.
  • Edge: funkcja nie jest obsługiwana.
  • Firefox: nieobsługiwane.
  • Safari: nieobsługiwane.

Ustawienie display w elemencie <details>

Dawniej zmiana typu wyświetlania elementu <details> nie była możliwa. To ograniczenie zostało złagodzone, dzięki czemu możesz na przykład używać układów siatki lub elastycznych w elemencie <details>.

W tym 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 zawartość jest umieszczana obok elementu <summary>.

Prezentacja

Nagrywanie

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

Aby to osiągnąć, użyj układu flex w elemencie <details>, stosując ten kod CSS:

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

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

Uwaga dotycząca używania display: inline

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

Umieszczenie elementu <details> w akapitach powoduje, że parsujący HTML musi najpierw zamknąć otwarty akapit, zgodnie z definicją podaną w sekcji 13.2.6.4.7 standardu HTML:

tag początkowy z nazwą tagu: „address”, „article”, „aside”, „blockquote”, „center”, „details”, „dialog”, „dir”, „div”, „dl”, „fieldset”, „figcaption”, „figure”, „footer”, „header”, „hgroup", „main", "section", "navsummary", "main", "section", "navsummary",

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

W efekcie <details> przepływa w kierunku blokowania niezależnie od tego, czy ustawisz display: inline.

Na przykład te znaczniki

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

Po przeanalizowaniu wygląda tak:

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

Możesz to sprawdzić samodzielnie w tym filmie demonstracyjnym, sprawdzając zanalizowany znacznik za pomocą narzędzi deweloperskich w Chrome.

Pamiętaj, że dotyczy to tylko zagnieżdżania elementu <details> w elemencie <p>. Używanie funkcji display: inline w przypadku <details> w ramach <div> działa prawidłowo.

Pseudo ::details-content

W przeglądarkach element <details> jest zaimplementowany za pomocą modelu Shadow DOM. Zawiera 1 <slot> dla podsumowania (z domyślnym elementem podrzędnym) i <slot> dla całej pozostałej treści, czyli wszystkie elementy podrzędne elementu <details> oprócz 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 korzystania z większej liczby typów wyświetlania w przypadku <details> możesz teraz kierować reklamy na miejsce do wyświetlania treści za pomocą pseudoelementu ::details-content. Możesz użyć tego pseudoklasy do nadania stylu kontenerowi, który otacza zawartość elementu <details>.

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

Aby zastosować styl tylko wtedy, gdy element <details> jest otwarty, przed nim umieść selektor [open].

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

Stylizację pseudoelementu ::details-content zalecamy stosować tylko wtedy, gdy element <details> jest w stanie [open].

Prezentacja

Nagrywanie

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

W arkuszu stylów UA typ display elementu ::details-content ma wartość block, podczas gdy wcześniej była to wartość display: contents. W niektórych przypadkach ta zmiana może działać na Twoją niekorzyść, np. w przypadku ujawnionego materiału, który opiera się na height: 100%. Jeśli to stanowi dla Ciebie problem, możesz go rozwiązać, przywracając typ display do contents, tak jak w tym przykładzie: details[open]::details-content { display: contents; }.

Animowanie pseudo ::details-content

Zawartość elementu <details> można animować podczas rozwijania. W tym 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 przejścia właściwości width musisz też przenieść właściwość content-visibility. Dzieje się tak, ponieważ jego wartość zmienia się ze stanu „nieotwarty” na „otwarty” zdefiniowany w arkuszu stylów klienta użytkownika. Ta właściwość jest właściwością, którą można animować oddzielnie, dlatego do jej działania potrzebujesz klucza allow-discrete.

Po dodaniu do udostępnionego wcześniej dema wyłącznego menu w kształcie harmonijki wygląda ono tak:

Prezentacja

Nagrywanie

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

Element height może też być animowany. Aby animować do height: auto, musisz użyć interpolate-size lub calc-size(). Dodatkowo, aby zapobiec wybielaniu treści z pseudo ::details-content, zastosuj do nich atrybut 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 */
    }
}

Ten kod możesz zobaczyć w działaniu w następującym pokazie, który jest inspirowany przez accordion z Material UI. Zawartość każdego elementu <details> ładnie się animuje.

Prezentacja

Nagrywanie

Nagrywanie 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 użytkownicy nie widzą, jest animacja.

Wykrywanie cech

Aby włączyć obsługę funkcji wykrywania w CSS, użyj tego fragmentu kodu.::details-content

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

Możesz też użyć tej funkcji do wykrywania, czy przeglądarka używana przez odwiedzającego obsługuje dodatkowe wartości wyświetlania.

Ułatwienia dostępu

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

Jak do tej pory, przynajmniej w przypadku przeglądarek opartych na Chromium i zgodnie ze standardem HTML, element <details> można wyszukiwać i automatycznie rozwija się, gdy przeglądarka próbuje przewinąć do ukrytej zawartości w odpowiedzi na znajdowanie na stronie, przewijanie do fragmentu tekstu i nawigację po fragmencie elementu. To się nie zmienia.

Zanim jednak zaczniesz używać akordeonów na wyłączność, zastanów się, czy są one pomocne lub szkodliwe dla użytkowników. Chociaż użycie wyłącznego układu harmonijkowego zmniejsza ilość miejsca na treści, użytkownicy mogą potrzebować otworzenia wielu elementów, aby zapoznać się z wszystkimi informacjami. Może to irytować użytkowników, którzy chcą oglądać kilka produktów jednocześnie.

A co z określaniem stylu znacznika?

Obecnie styl markera listy nie jest interoperacyjny, ponieważ istnieją dwa różne podejścia: jedno stosowane przez Gecko i (obecnie) Chromium oraz drugie przez WebKit (które było wcześniej używane również w Chromium).

Gdy funkcja będzie interoperacyjna, chcemy zapewnić Ci większą kontrolę nad stylami znaczników.

Więcej wersji demonstracyjnych

Na koniec kilka dodatkowych prezentacji. Wszystkie one używają domeny ::details-content.

Akordeon UIKit

Prezentacja

Nagrywanie

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

To demo zostało stworzone na podstawie poziomych kart UIKit. Kod jest praktycznie taki sam jak w udostępnionym wcześniej interfejsie Material UI.

Częściowo otwarty widżet

Prezentacja

Nagrywanie

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

W tym filmie widać częściowo otwarty widżet, którego zawartość jest już widoczna na ekranie. Aby to osiągnąć, wartość content-visibility jest zawsze ustawiana na visible. Element height jest animowany za pomocą elementu calc-size(), ponieważ jest to związane z wykonywaniem obliczeń.

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

Ze względu na wygodę stylizacji zawartość jest ujęta w element DIV. Element DIV otrzymuje style układu, takie jak padding, a pseudoelement ::details-content jest animowany.