Wzorzec 13
Rozwijanie bez skryptu
Rozwijana sekcja na divach potrzebuje stanu, aria-expanded i obsługi klawiatury, które element details ma wbudowane od zawsze. Brakowało tylko animacji: pseudoelement ::details-content razem z interpolate-size: allow-keywords pozwala płynnie przejść do block-size: auto, a atrybut name zamyka sąsiednie sekcje bez jednej linii JavaScript. To domyślny wybór, gdy stan rozwinięcia obchodzi tylko użytkownika. Gdy musi go znać aplikacja, wróć do wzorca Akordeon bez mierzenia, którego animacja działa dziś w każdej przeglądarce.
Akordeon z trzech elementów details
Rozwijaj sekcje klikiem albo Enterem. Animację robi tranzycja block-size na ::details-content, a wspólny atrybut name zamyka poprzednią sekcję przy otwarciu następnej. Stan trzyma przeglądarka.
Skąd przeglądarka zna wysokość rozwiniętej treści?
Nie musi jej znać z góry. interpolate-size: allow-keywords pozwala tranzycji dojechać do block-size: auto, więc pomiar robi silnik layoutu w trakcie animacji, nie skrypt przed nią.
Dlaczego details zamiast diva z onClick?
Bo stan otwarcia, obsługa klawiatury i semantyka są wbudowane. Do tego atrybut name zamyka sąsiednie sekcje, a wyszukiwanie na stronie znajduje treść w zwiniętych panelach.
Co się dzieje bez wsparcia ::details-content?
Sekcja otwiera się natychmiast, bez animacji. Semantyka, klawiatura i ekskluzywne grupowanie działają dalej, bo pochodzą z HTML, nie z CSS.
Wzorzec akordeonu z grid-template-rows steruje stanem w React. Ta wersja oddaje stan przeglądarce: mniej kodu, ta sama płynność i semantyka za darmo.
Reguły
- Rozwijaną sekcję buduje details z summary, nie div z onClick i ręcznie dopisywanym aria.
- Animację daje transition na block-size pseudoelementu ::details-content przy interpolate-size: allow-keywords.
- Atrybut name grupuje sekcje w ekskluzywny akordeon, stan trzyma przeglądarka.
- Zwinięta treść jest w DOM, więc wyszukiwanie na stronie ją znajduje, a brak wsparcia i reduced motion degradują do natychmiastowego otwarcia.
- Gdy stan rozwinięcia musi znać aplikacja, właściwym wzorcem jest akordeon z grid-template-rows.
Wzorzec w kodzie
<details name="faq">
<summary>Jak działa rezerwacja miejsca?</summary>
<p>Kontener istnieje od pierwszego renderu...</p>
</details>
<details name="faq">
<summary>Czym różni się dvh od vh?</summary>
<p>dvh mierzy viewport taki, jaki jest...</p>
</details>.faq {
interpolate-size: allow-keywords;
}
details::details-content {
block-size: 0;
overflow: clip;
transition:
block-size 0.3s ease,
content-visibility 0.3s allow-discrete;
}
details[open]::details-content {
block-size: auto;
}Prompt dla Claude
Wklej do Claude Code w swoim projekcie. Prompt niesie komplet reguł tej lekcji i ogólne zasady Liquid Design, więc implementacja trafia w metodologię bez tłumaczenia jej od zera.
Zaimplementuj w moim projekcie wzorzec „Rozwijanie bez skryptu" z metodologii Liquid Design. Element details z ::details-content i interpolate-size animuje rozwijanie w czystym CSS, a atrybut name składa sekcje w ekskluzywny akordeon. Wymagania: - Rozwijaną sekcję buduje details z summary, nie div z onClick i ręcznie dopisywanym aria. - Animację daje transition na block-size pseudoelementu ::details-content przy interpolate-size: allow-keywords. - Atrybut name grupuje sekcje w ekskluzywny akordeon, stan trzyma przeglądarka. - Zwinięta treść jest w DOM, więc wyszukiwanie na stronie ją znajduje, a brak wsparcia i reduced motion degradują do natychmiastowego otwarcia. - Gdy stan rozwinięcia musi znać aplikacja, właściwym wzorcem jest akordeon z grid-template-rows. Ogólne reguły Liquid Design, których implementacja nie może złamać: - HTML jest semantyczny: button, a, nav, form, label, dialog, details, ul, dl i nagłówki h1-h6 zamiast div z onClick i ARIA dopisywanym ręcznie. div i span służą wyłącznie do layoutu, nigdy do interakcji ani struktury treści. - Layout jest umową: treść, która dociera później, ma miejsce zarezerwowane od pierwszego renderu. Nic nie skacze. - Stany ładowania, pustki, błędu i treści dzielą jeden layout. - Typografia pochodzi z nazwanej, płynnej skali opartej o clamp(), nie z gołych rozmiarów. - Animacje dotyczą wyłącznie transform i opacity, a prefers-reduced-motion redukuje je do natychmiastowej zmiany stanu. - Breakpoint jest ostatecznością: najpierw container queries i repeat(auto-fit, minmax(...)). Sposób pracy — zanim napiszesz pierwszą linię kodu: - Sprawdź w plikach projektu, jak stylowane są komponenty (Tailwind, CSS Modules, vanilla-extract, styled-components, Sass, czysty CSS...) i pisz wyłącznie w tej konwencji. Niczego nie zakładaj z góry i nie dodawaj nowych zależności. - Wymagania powyżej opisują właściwości CSS i atrybuty HTML, nie klasy narzędziowe. Przełóż je na system stylowania zastany w projekcie. - Sprawdź framework komponentów, wersję i konwencje nazewnictwa, zamiast zakładać konkretny stack. - Używaj istniejących tokenów projektu (kolory, typografia, odstępy). Jeśli czegoś brakuje, zaproponuj minimalne uzupełnienie w duchu istniejącego kodu, nie osobny system. - Nie używaj klas, tokenów ani API, których nie znalazłeś w tym projekcie. Pełny opis z żywym demo i kodem: https://liquid-design.website/wzorce/rozwijanie-natywne