Siatka i responsywność
Techniczny: DraftAkceptacja: DraftUkład zaczyna się od najwęższego ekranu. Szerokość okna zmienia go na czterech progach, a szerokość treści ograniczają dwa kontenery. Jedno i drugie jest tokenem, więc w kodzie nie pada ani liczba pikseli, ani zapytanie o media napisane z ręki.
Cztery progi
Dział zatytułowany „Cztery progi”| Token | Zmienna CSS | Wartość | Podgląd |
|---|---|---|---|
breakpoint.sm | --breakpoint-sm | 40rem | |
breakpoint.md | --breakpoint-md | 48rem | |
breakpoint.lg | --breakpoint-lg | 64rem | |
breakpoint.xl | --breakpoint-xl | 80rem |
Tyle ich jest. Build wygasza skalę domyślną Tailwinda, więc wariant spoza tej
czwórki, na przykład 2xl:, nie powstaje i klasa z nim nic nie zrobi. Nowy próg
zaczyna się od tokenu, nie od klasy w komponencie.
Progi są te same w pięciu markach i dwóch trybach. Zapytania o media nie da się
zakresować atrybutem na <html>, więc próg nadpisany dla jednej marki byłby
martwy. Build zatrzymuje się, gdy taka różnica się pojawi.
Jak zapisać przełamanie
Dział zatytułowany „Jak zapisać przełamanie”Zapis zależy od miejsca. Wartość pod spodem jest jedna.
<section className="grid grid-cols-1 gap-stack-lg md:grid-cols-2">…</section>.article-body { font-size: var(--font-body-m-size); @variant md { font-size: var(--font-body-l-size); }}/* @media nie rozwija var(). Ta reguła kompiluje się bez błędu, przechodzi każdą bramkę i nie dopasowuje się nigdy. */@media (min-width: var(--breakpoint-md)) { … }
/* Literał zadziała, ale jest drugą kopią progu: zmiana tokenu go nie ruszy. */@media (min-width: 48rem) { … }W bloku <style> komponentu Astro @variant nie zadziała, bo ten CSS nie widzi
motywu Tailwinda. Tam przełamanie zapisujemy klasą z wariantem w znaczniku,
razem z klasą bazową. Styl komponentu ma wyższą specyficzność i wygrałby
z samym wariantem.
Mobile-first
Dział zatytułowany „Mobile-first”Deklaracja bez wariantu opisuje najwęższy ekran. Próg tylko dodaje: md:
nadpisuje to, co już stoi, i nie występuje bez wersji bazowej. Dlatego
w systemie nie ma progów liczonych od góry (max-width).
Na progu md zmieniają się dziś dwie rzeczy:
- typografia — cztery największe poziomy (
display-l,display,heading-l,heading-m) rosną, pozostałe dziewięć jest identycznych na każdej szerokości (Typografia); - układ artykułu — kolumna poboczna schodzi spod treści i staje obok niej (Artykuł i treść źródłowa).
Odstępy nie zmieniają się na żadnym progu. page-gutter i section-gap mają
jedną wartość na każdej szerokości (Odstępy i rytm).
Kontenery treści
Dział zatytułowany „Kontenery treści”| Token | Zmienna CSS | Wartość | Podgląd | Przeznaczenie |
|---|---|---|---|---|
size.container-aside | --size-container-aside | 16rem | Kolumna poboczna obok treści: spis treści, panel kontekstu. | |
size.container-page | --size-container-page | 64rem | Górny limit kolumny treści. Powyżej rośnie margines, nie tekst. |
container-page ogranicza kolumnę treści i ma tę samą wartość co próg lg.
Szersze okno nie rozciąga akapitu na całą szerokość, tylko dokłada margines.
container-aside trzyma kolumnę poboczną. Obok treści staje dopiero od md,
niżej idzie pod nią.
<main className="mx-auto w-full max-w-(--size-container-page) px-page-gutter"> <div className="grid grid-cols-1 gap-stack-lg md:grid-cols-[minmax(0,1fr)_var(--size-container-aside)]"> <article className="flex flex-col gap-stack-md">…</article> <aside className="flex flex-col gap-stack-sm">…</aside> </div></main><main className="mx-auto max-w-[1024px] px-4"> <div className="grid grid-cols-[1fr_256px] gap-6">…</div></main>Cztery błędy w kontrprzykładzie. max-w-[1024px] i 256px wpisują szerokość
z ręki zamiast wziąć kontener; wartość arbitralna w nawiasie nie czyta żadnej
skali, więc zadziała i wyłapie ją review. px-4 i gap-6 sięgały po skalę
własną Tailwinda obok naszej — dziś nie kompilują się wcale, bo
dist/theme.css gasi domyślny motyw w tych przestrzeniach nazw. Kolumny stoją obok siebie od razu, bez wersji na wąski
ekran, więc na telefonie poboczny panel ściska treść. Ostatni błąd jest cichy:
1fr ma domyślne minimum auto, nie zero, więc długie słowo albo tabela
rozpycha kolumnę poza ekran. Dlatego w przykładzie wyżej stoi minmax(0, 1fr).
Kolumny deklarujemy przy elemencie, który ich potrzebuje. Wzór jest za każdym
razem ten sam: grid, przerwa z roli odstępu i liczba kolumn zaczynająca się
od jednej.
<ul className="grid grid-cols-1 gap-stack-md md:grid-cols-3">…</ul>Nazwanej siatki o stałej liczbie kolumn system dziś nie ma i żadna strona jej nie zakłada. Liczbę kolumn wybiera treść: elementy o tej samej wadze dzielą się równo, treść z kolumną poboczną nie.
Konteksty
Dział zatytułowany „Konteksty”| Klient | Przedsiębiorca | Pracodawca | Klient indywidualny |
|---|---|---|---|
| Co niesie kolumna poboczna | kontekst oferty przy treści: mapa potrzeb, wycena wstępna, powód propozycji | nawigację po porównaniu pakietów | nic; kalkulator prowadzi jednym torem |
| Czego pilnujemy przy zwężaniu | gęsta strona oferty nie może zgubić ceny i zastrzeżenia pod złożonym panelem | esencja wyciągu dla zarządu czyta się na telefonie w jednej kolumnie, bez poziomego przewijania tabeli | cena i warunek jej ważności zostają przy polu, którego dotyczą |
Kolejność w dokumencie jest kolejnością czytania. Kolumna, która na wąskim ekranie schodzi pod treść, trafia tam w tej kolejności, w której stoi w kodzie. Czytnik ekranu i klawiatura nie widzą kolejności ustawionej wizualnie (standard dostępności).
Granice
Dział zatytułowany „Granice”- Nowy próg i nowa szerokość kontenera powstają w warstwie semantycznej, nie jako literał w CSS ani wartość w nawiasie kwadratowym przy klasie.
- Progi nie zależą od marki ani od trybu.
- Próg nie naprawia treści. Tabela, która nie mieści się na telefonie, wymaga innej formy danych, a nie kolejnego przełamania.
Brief do wykonania
Dział zatytułowany „Brief do wykonania”@todo(layout): wykonać poniższy brief, przedstawić rezultat i dowody odbioru. Usunięcie znacznika nie jest wykonaniem zadania.
- Zakres: trzy rzeczy bez rozstrzygnięcia. (1) Szerokość czytania prozy na
stronie bez kolumny pobocznej: dziś akapit dochodzi tam do
container-page, bo własnej szerokości nie ma. (2) Szerokość formularza Analizy Potrzeb Klienta. (3) Czy system potrzebuje nazwanej siatki o stałej liczbie kolumn, czy wystarczygrid-cols-*przy elemencie. Rozstrzygnięcie to token w warstwie semantycznej plus wiersz w tabeli wyżej. - Źródła: platforma marki, realne strony: LP zawodu, karta decyzji, wyciąg dla zarządu, formularz Analizy Potrzeb Klienta. Wartość bierze się z pomiaru na tych stronach, nie z zalecenia ogólnego.
- Granica swobody: progi
sm/md/lg/xli dwa kontenery są ustalone i ich nie ruszasz. Nową szerokość przedstawiasz do decyzji razem ze stroną, na której ją zmierzono.
Weryfikacja
Dział zatytułowany „Weryfikacja”- W kodzie nie ma
@medianapisanego ręcznie ani szerokości w nawiasie kwadratowym. Sprawdzasz to wyszukaniem@mediaimax-w-[poza artefaktem budowania tokenów. - Ta sama strona czyta się przy każdej szerokości od 320 px w górę, bez poziomego przewijania i bez treści uciętej przy krawędzi (WCAG 2.2 AA, reflow).
- Przy powiększeniu tekstu do 200% układ przechodzi na jedną kolumnę zamiast ściskać obie.
- Kolejność treści czytana klawiszem Tab zgadza się z kolejnością na ekranie, także po zejściu kolumny pobocznej pod treść.
pnpm design:checkprzechodzi, łącznie z kontrolą literałów w zbudowanym styleguide; porównanie zrzutów:pnpm design:audit.
Tokeny i zależności,
Typografia,
Odstępy i rytm,
Artykuł i treść źródłowa,
Standard dostępności,
progi i kontenery w prymitywach — źródło w repo: packages/design/tokens/src/core.tokens.json,
mechanika progów w @theme — źródło w repo: packages/design/tokens/README.md.