Zasady projektowania dla inżynierów oprogramowania
Podstawy projektowania dla inżynierów oprogramowania: typografia, kolor, odstępy, animacja, wzorce interfejsów AI, tokeny projektowe oraz 48 aktualnych studiów przypadku produktów.
Zaktualizowano 18 maja 2026
Aktualizacja z 18 maja 2026: Odświeżono indeks studiów projektowych, aby odpowiadał aktualnemu korpusowi 48 analiz, oraz rozszerzono wzorce interfejsów AI o dowody dotyczące przepływów agentowych: punkty kontrolne, stany zatwierdzenia, wiarygodność źródeł i widoczną weryfikację.
Aktualizacja z maja 2026: Dodano uwagę o roboczym szkicu WCAG 3.0 z marca 2026 roku oraz o stanowisku W3C, zgodnie z którym WCAG 2.2 i 3.0 będą współistnieć. WCAG 2.2 pozostaje standardem, w który należy celować przy bieżących pracach nad dostępnością.
Aktualizacja z lutego 2026: Dodano dwie nowe sekcje — wzorce interakcji (8 paradygmatów wynikających z analizy Framer, Flighty, Halide, Warp, Bear, Craft i Superhuman) oraz wzorce interfejsów AI (projektowanie z cytowaniami na pierwszym planie, fazy streamingu, przejrzystość błędów na przykładzie Perplexity). Zaktualizowano wzorce webowe na 2026 rok, uwzględniając pozycjonowanie kotwic, animacje sterowane przewijaniem i @starting-style. Zaktualizowano dostępność, aby odzwierciedlić standaryzację ISO dla WCAG 2.2. Głębokie analizy 48 wyjątkowych produktów znajdują się w sekcji studia projektowe.
Przez lata, budując oprogramowanie, zgłębiałem projektowanie, przyswajając zasady od legend takich jak Dieter Rams i analizując interfejsy produktów takich jak Linear, Stripe i Raycast. Ten przewodnik destyluje tę wiedzę w kompleksowe kompendium, którego brakowało mi, gdy zacząłem zwracać uwagę na to, jak moje oprogramowanie wygląda i jakie sprawia wrażenie.
Projektowanie nie jest dekoracją. Jest komunikacją. Każdy piksel komunikuje funkcję, hierarchię i znaczenie. Różnica między oprogramowaniem, które sprawia wrażenie amatorskiego, a oprogramowaniem, które sprawia wrażenie profesjonalnego, polega na zrozumieniu tych zasad i konsekwentnym ich stosowaniu.
Ten przewodnik zakłada, że potrafi Pan/Pani już pisać kod. Uczy patrzeć — rozumieć, dlaczego niektóre interfejsy wydają się bezwysiłkowe, a inne chaotyczne, i co ważniejsze, jak tworzyć te pierwsze.
Spis treści
Część 1: Podstawy
Część 2: Interakcja i AI
Część 3: Filozofia projektowania
Część 4: Implementacja
Część 5: Materiały referencyjne
Psychologia Gestalt
„Całość jest czymś innym niż suma jej części.” — Kurt Koffka
Psychologia Gestalt, rozwinięta w Niemczech w latach 20. XX wieku, wyjaśnia, w jaki sposób ludzie postrzegają informacje wizualne. Mózg nie widzi pojedynczych pikseli — organizuje elementy w znaczące wzorce. Opanowanie tych zasad pozwala kontrolować sposób, w jaki użytkownicy postrzegają interfejsy.
Bliskość
Elementy znajdujące się blisko siebie są postrzegane jako grupa.
To najpotężniejsza zasada Gestalt w projektowaniu UI. Przestrzeń komunikuje relacje lepiej niż jakakolwiek inna właściwość wizualna.
WRONG (equal spacing = no grouping):
┌─────────────────┐
│ Label │
│ │
│ Input Field │
│ │
│ Label │
│ │
│ Input Field │
└─────────────────┘
RIGHT (unequal spacing = clear groups):
┌─────────────────┐
│ Label │
│ Input Field │ ← Tight (4px) - related
│ │
│ │ ← Wide (24px) - separating groups
│ Label │
│ Input Field │ ← Tight (4px) - related
└─────────────────┘
Implementacja CSS:
.form-group {
margin-bottom: 24px; /* Between groups: wide */
}
.form-group label {
margin-bottom: 4px; /* Label to input: tight */
display: block;
}
Implementacja SwiftUI:
VStack(alignment: .leading, spacing: 4) { // Tight within group
Text("Email")
.font(.caption)
.foregroundStyle(.secondary)
TextField("you@example.com", text: $email)
.textFieldStyle(.roundedBorder)
}
.padding(.bottom, 24) // Wide between groups
Podobieństwo
Elementy o wspólnych cechach wizualnych wydają się powiązane.
Gdy elementy wyglądają tak samo, użytkownicy zakładają, że działają tak samo. Dlatego systemy projektowe stosują spójne style przycisków, kart i typografii.
Example Navigation:
┌───────────────────────────────────┐
│ [Dashboard] [Projects] [Settings] │ ← Same style = same function
│ │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │Card │ │Card │ │Card │ │ ← Same style = same content type
│ └─────┘ └─────┘ └─────┘ │
│ │
│ [+ New Project] │ ← Different style = different function
└───────────────────────────────────┘
Figura i tło
Treść powinna wyraźnie oddzielać się od tła.
Mózg musi odróżnić „figurę” (obiekt, na którym się skupia) od „tła” (podłoża). Słabe relacje figura–tło wywołują chaos wizualny.
Techniki: - Kontrast (jasna figura na ciemnym tle i odwrotnie) - Cienie (unoszenie figury nad tło) - Obramowania (wyznaczanie krawędzi figury) - Rozmycie (rozmycie tła, wyostrzenie figury)
/* Strong figure-ground relationship */
.card {
background: var(--color-surface); /* Figure */
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1); /* Elevation */
}
.modal-overlay {
background: rgba(0, 0, 0, 0.5); /* Dim ground */
backdrop-filter: blur(4px); /* Blur ground */
}
Wspólny region
Elementy zawarte w granicach jednego obszaru są postrzegane jako grupa.
Umieszczenie elementów w wizualnym kontenerze (karcie, ramce, obszarze z obramowaniem) sygnalizuje, że należą do siebie.
Ciągłość
Oko podąża za ścieżkami, liniami i krzywymi.
Wyrównanie i przepływ wizualny kierują uwagę przez interfejs.
CONTINUITY IN ALIGNMENT:
┌────────────────────────────────┐
│ Logo [Nav] [Nav] [Nav] │ ← Aligned on horizontal axis
├────────────────────────────────┤
│ │
│ Headline │
│ ───────────────────────────── │ ← Eye follows left edge
│ Paragraph text continues │
│ along the same left edge │
│ │
│ [Primary Action] │ ← Still on the left edge
└────────────────────────────────┘
Domknięcie
Mózg uzupełnia niekompletne kształty.
Użytkownicy nie potrzebują narysowanego każdego piksela — mentalnie dopełniają znane kształty. Pozwala to tworzyć bardziej minimalistyczne i eleganckie projekty.
/* Horizontal scroll with partial card (closure) */
.card-carousel {
display: flex;
gap: 16px;
overflow-x: auto;
padding-right: 48px; /* Show partial card = scroll hint */
}
.card-carousel .card {
flex: 0 0 280px; /* Fixed width, partial visible */
}
Gestalt — szybkie odniesienie
| Zasada | Reguła | Główne zastosowanie |
|---|---|---|
| Bliskość | Powiązane = blisko, niepowiązane = daleko | Pola formularzy, sekcje treści |
| Podobieństwo | Ten sam wygląd = ta sama funkcja | Przyciski, karty, nawigacja |
| Figura i tło | Wyraźne rozdzielenie warstw | Karty, modale, nakładki |
| Wspólny region | Granice grupują treść | Sekcje ustawień, karty użytkowników |
| Ciągłość | Podążanie za liniami i wyrównaniem | Osie czasu, przepływ czytania |
| Domknięcie | Mózg uzupełnia kształty | Ikony, wskazówki przewijania, szkielety |
Typografia
„Typografia to sztuka nadawania ludzkiemu językowi trwałej formy wizualnej.” — Robert Bringhurst
Typografia stanowi fundament projektowania interfejsów. Tekst komunikuje funkcjonalność, hierarchię i tożsamość marki. Słaba typografia utrudnia korzystanie z interfejsów; świetna typografia jest niewidoczna — po prostu działa.
Skala typograficzna
Spójna skala tworzy wizualną harmonię. Warto stosować proporcję matematyczną.
Skala 1,25 (zalecana dla UI):
:root {
/* Base: 16px (1rem) */
--text-xs: 0.64rem; /* 10.24px - use sparingly */
--text-sm: 0.8rem; /* 12.8px - captions, labels */
--text-base: 1rem; /* 16px - body text */
--text-lg: 1.25rem; /* 20px - lead text */
--text-xl: 1.563rem; /* 25px - h4 */
--text-2xl: 1.953rem; /* 31.25px - h3 */
--text-3xl: 2.441rem; /* 39px - h2 */
--text-4xl: 3.052rem; /* 48.8px - h1 */
}
Interlinia (leading)
Interlinia ma ogromny wpływ na czytelność. Różne rodzaje treści wymagają różnej interlinii.
| Typ treści | Interlinia | Dlaczego |
|---|---|---|
| Nagłówki | 1,1–1,2 | Zwięzłe, pogrubione, krótkie |
| Tekst UI | 1,3–1,4 | Etykiety, przyciski |
| Tekst główny | 1,5–1,7 | Czytelne akapity |
| Teksty długie | 1,7–2,0 | Artykuły, dokumentacja |
Długość wiersza (miara)
Optymalna długość wiersza zapobiega zmęczeniu oczu i poprawia zrozumienie tekstu.
- Optimum: 45–75 znaków na wiersz
- Cel: 50–65 znaków
- Absolutne maksimum: 85 znaków
p {
max-width: 65ch; /* ch unit = width of '0' character */
}
.article-body {
max-width: 70ch;
margin: 0 auto;
}
Dobór kroju pisma
Najpierw czcionki systemowe. Ładują się natychmiast, pasują do platformy i są zoptymalizowane pod kątem ekranów.
:root {
--font-sans: system-ui, -apple-system, BlinkMacSystemFont,
'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
--font-mono: ui-monospace, 'SF Mono', 'Cascadia Code',
'JetBrains Mono', Consolas, monospace;
}
Czcionki niestandardowe sprawdzają się w przypadku: - Wyróżnienia marki (strony marketingowe) - Charakteru edytorskiego / wydawniczego - Konkretnej intencji projektowej nieosiągalnej za pomocą czcionek systemowych
Grubość kroju w hierarchii
Grubość kroju pozwala budować hierarchię, nie tylko sam rozmiar.
h1 { font-weight: 700; } /* Bold */
h2 { font-weight: 600; } /* Semibold */
h3 { font-weight: 600; } /* Semibold */
.lead { font-weight: 500; } /* Medium */
p { font-weight: 400; } /* Regular */
.meta { font-weight: 400; color: var(--text-muted); }
Typografia — szybkie odniesienie
| Właściwość | Tekst główny | Nagłówki | Etykiety UI |
|---|---|---|---|
| Rozmiar | 16–18px | 24–48px | 12–14px |
| Grubość | 400 | 600–700 | 500 |
| Interlinia | 1,5–1,7 | 1,1–1,2 | 1,3–1,4 |
| Długość wiersza | 45–75ch | nie dotyczy | nie dotyczy |
| Wyrównanie | Do lewej | Wyśrodkowanie OK | Do lewej |
Teoria koloru
„Kolor jest siłą, która bezpośrednio wpływa na duszę.” — Wassily Kandinsky
Kolor komunikuje szybciej niż słowa. Buduje nastrój, kieruje uwagę, sygnalizuje znaczenie i wzmacnia rozpoznawalność marki.
Reguła 60-30-10
Najbardziej niezawodny rozkład kolorów w zrównoważonych interfejsach.
┌──────────────────────────────────────────┐
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ 60% - Dominant (Background)
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░│ 30% - Secondary (Cards, sections)
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░│
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓██████▓▓▓▓▓▓▓▓▓▓░░░░░░░░│ 10% - Accent (Buttons, links)
└──────────────────────────────────────────┘
Tworzenie palety kolorów
Każdy interfejs potrzebuje następujących kolorów semantycznych:
:root {
/* Brand */
--color-primary: hsl(220, 80%, 50%);
--color-primary-hover: hsl(220, 80%, 45%);
/* Semantic */
--color-success: hsl(142, 76%, 36%); /* Green - positive */
--color-warning: hsl(38, 92%, 50%); /* Amber - caution */
--color-error: hsl(0, 84%, 60%); /* Red - danger */
/* Neutrals */
--color-background: hsl(0, 0%, 100%);
--color-surface: hsl(220, 14%, 96%);
--color-border: hsl(220, 13%, 91%);
/* Text */
--color-text: hsl(220, 13%, 13%);
--color-text-secondary: hsl(220, 9%, 46%);
--color-text-muted: hsl(220, 9%, 64%);
}
Psychologia koloru
| Kolor | Psychologia | Zastosowanie w UI |
|---|---|---|
| Niebieski | Zaufanie, stabilność, spokój | Finanse, technologia, rozwiązania korporacyjne |
| Zielony | Wzrost, natura, sukces | Zdrowie, ekologia, stany pozytywne |
| Czerwony | Energia, pilność, zagrożenie | Alerty, sprzedaż, błędy |
| Pomarańczowy | Ciepło, entuzjazm | CTA, marki o swobodnym charakterze |
| Żółty | Optymizm, ostrożność | Ostrzeżenia, wyróżnienia |
| Fioletowy | Luksus, kreatywność | Produkty premium |
| ### Projektowanie z pierwszeństwem trybu ciemnego (Vercel) | ||
| Vercel projektuje najpierw z myślą o trybie ciemnym, a następnie wyprowadza z niego tryb jasny. Dzięki temu powstają lepsze ciemne interfejsy, ponieważ tryb ciemny staje się głównym założeniem, a nie dodatkiem na później. |
/* Design dark first, derive light */
:root {
/* Dark mode defaults */
--color-background: hsl(0, 0%, 0%);
--color-surface: hsl(0, 0%, 7%);
--color-border: hsl(0, 0%, 15%);
--color-text: hsl(0, 0%, 93%);
--color-text-secondary: hsl(0, 0%, 63%);
}
@media (prefers-color-scheme: light) {
:root {
--color-background: hsl(0, 0%, 100%);
--color-surface: hsl(0, 0%, 97%);
--color-border: hsl(0, 0%, 89%);
--color-text: hsl(0, 0%, 9%);
--color-text-secondary: hsl(0, 0%, 40%);
}
}
Kiedy stosować: Narzędzia programistyczne, aplikacje multimedialne, pulpity nawigacyjne — konteksty, w których użytkownicy spędzają długie sesje, a tryb ciemny zmniejsza zmęczenie oczu.
Kontrast dostępności
| Poziom | Zwykły tekst | Duży tekst | Komponenty UI |
|---|---|---|---|
| AA | 4.5:1 | 3:1 | 3:1 |
| AAA | 7:1 | 4.5:1 | Nie dotyczy |
| WCAG 2.2 stał się standardem ISO (ISO/IEC 40500:2025) w październiku 2025 roku, dodając kryteria dotyczące widoczności fokusu, redundantnego wprowadzania danych i dostępnego uwierzytelniania. Najważniejsze dodatki: wskaźniki fokusu nie mogą być całkowicie zasłonięte przez inne treści (2.4.11), a uwierzytelnianie nie może opierać się wyłącznie na testach funkcji poznawczych (3.3.8). W3C opublikowało zaktualizowany WCAG 2.2 w grudniu 2024 roku; oczekuje się, że zostanie wydany jako ISO/IEC 40500:2026 pod koniec 2026 roku. |
WCAG 3.0 nadal jest wersją roboczą. Najnowsza rewizja została opublikowana w marcu 2026 roku i nie zastępuje WCAG 2.2; W3C podaje, że oba standardy będą współistnieć. Accessibility Guidelines Working Group planuje opublikować przewidywany harmonogram WCAG 3 w 2026 roku, ale WCAG 2.2 pozostaje standardem, do którego należy dążyć w bieżących pracach.
Narzędzia: WebAIM Contrast Checker, selektor kolorów Chrome DevTools
Hierarchia wizualna
„Design jest cichym ambasadorem marki.” — Paul Rand
Hierarchia wizualna kontroluje, co użytkownicy widzą jako pierwsze, drugie i trzecie. Bez wyraźnej hierarchii użytkownicy muszą wkładać wysiłek w znalezienie informacji. Dzięki niej interfejsy wydają się intuicyjne.
Sześć narzędzi hierarchii
1. Rozmiar — Większe elementy jako pierwsze przyciągają uwagę
.hero-title { font-size: 3rem; } /* Dominant */
.section-title { font-size: 1.5rem; } /* Secondary */
.body-text { font-size: 1rem; } /* Baseline */
2. Grubość — Pogrubienie wysuwa się na pierwszy plan, lekki krój się cofa
h1 { font-weight: 700; }
.lead { font-weight: 500; }
p { font-weight: 400; }
3. Kolor i kontrast — Wysoki kontrast = przyciągnięcie uwagi
.title { color: var(--color-text); } /* Near black */
.meta { color: var(--color-text-muted); } /* Gray */
4. Pozycja — Kluczowe pozycje mają znaczenie
F-PATTERN (content pages): Z-PATTERN (landing pages):
████████████████████████ 1 ──────────────────► 2
████████ ↘
████ ↘
██ ↘
3 ──────────────────► 4
5. Pusta przestrzeń — Izolacja nadaje znaczenie
.hero { padding: 120px 48px; } /* Generous space */
.data-table { padding: 12px; } /* Dense content */
6. Głębia i wyniesienie — Elementy wysunięte na pierwszy plan domagają się uwagi
:root {
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
}
.card { box-shadow: var(--shadow-sm); }
.card:hover { box-shadow: var(--shadow-md); }
.modal { box-shadow: var(--shadow-lg); }
Zastosowane wzorce
Obecność współpracowników (Figma): Kursory wielu użytkowników z etykietami nazw, podświetleniami zaznaczeń i obrysami komponentów tworzą żywy dokument. Kolor każdego współpracownika jest odrębny, ale ma tę samą wagę wizualną - żaden kursor nie jest „głośniejszy” od innego.
Dyskretne wskaźniki statusu (Vercel): Status wdrożenia wykorzystuje subtelne, stałe wskaźniki zamiast natarczywych alertów. Cienki kolorowy pasek u góry komunikuje stan (trwa budowanie, wdrożono, niepowodzenie) bez przerywania pracy.
Analogie projektowe ze świata rzeczywistego (Flighty): Wizualizacje postępu lotu nawiązują do fizycznych przyrządów lotniczych - krzywe wysokości, wskaźniki prędkości i mapy bramek wykorzystują znane metafory wizualne zamiast abstrakcyjnych pasków postępu.
Test mrużenia oczu
Warto zmrużyć oczy, patrząc na projekt. Czy hierarchia nadal jest widoczna? Jeśli tak, jest silna.
Odstępy i rytm
„Biała przestrzeń jest jak powietrze: jest niezbędna, aby projekt mógł oddychać.” — Wojciech Zieliński
Odstępy są niewidoczną strukturą designu. Spójne odstępy tworzą wizualny rytm — poczucie, że elementy należą do siebie w ramach spójnego systemu.
Siatka 8 px
Siatka 8 px jest standardem branżowym, ponieważ: - Dzieli się równomiernie (8, 16, 24, 32, 40, 48…) - Działa z typowymi gęstościami ekranów (1x, 1.5x, 2x, 3x) - Tworzy spójny rytm bez obliczeń
:root {
--space-1: 4px; /* Tight: icon gaps */
--space-2: 8px; /* Compact: inline elements */
--space-3: 12px; /* Snug: form fields */
--space-4: 16px; /* Default: most gaps */
--space-6: 24px; /* Spacious: card padding */
--space-8: 32px; /* Section gaps */
--space-12: 48px; /* Major sections */
--space-16: 64px; /* Page sections */
--space-20: 80px; /* Hero spacing */
}
Odstępy wewnętrzne i zewnętrzne
Wewnętrzne (padding): Przestrzeń wewnątrz elementu Zewnętrzne (margin): Przestrzeń między elementami
Zasada: Odstępy wewnętrzne zwykle powinny być większe niż odstępy zewnętrzne w powiązanych grupach.
.card {
padding: 24px; /* Internal: spacious */
margin-bottom: 16px; /* External: less than padding */
}
Wzorce odstępów w komponentach
Karty:
.card { padding: 24px; border-radius: 12px; }
.card-header { margin-bottom: 16px; }
.card-title { margin-bottom: 4px; } /* Tight to subtitle */
Przyciski:
.btn { padding: 12px 24px; border-radius: 8px; }
.btn--sm { padding: 8px 16px; }
.btn--lg { padding: 16px 32px; }
.btn-group { display: flex; gap: 12px; }
Formularze:
.form-row { margin-bottom: 24px; }
.form-label { margin-bottom: 4px; }
.form-help { margin-top: 4px; }
.form-actions { margin-top: 32px; display: flex; gap: 12px; }
Szybkie zestawienie odstępów
| Kontekst | Zalecany odstęp |
|---|---|
| Ikona do tekstu | 4-8px |
| Etykieta do pola | 4px |
| Między grupami formularza | 24px |
| Padding karty | 20-24px |
| Odstęp między kartami | 16-24px |
| Padding sekcji (mobile) | 48-64px |
| Padding sekcji (desktop) | 80-96px |
| Padding przycisku (poziomo/pionowo) | 24px / 12px |
| — |
Zasady animacji
„Animation is not the art of drawings that move but the art of movements that are drawn.” — Norman McLaren
Animacja ożywia interfejsy. Dobrze wykonana kieruje uwagę, komunikuje stan i tworzy emocjonalną więź. Źle wykonana — frustruje i rozprasza.
Zasada nadrzędna
Animacja powinna wydawać się nieunikniona, nie dekoracyjna.
Dobra animacja: 1. Komunikuje coś, czego statyczny projekt nie jest w stanie przekazać 2. Zmniejsza obciążenie poznawcze, pokazując relacje między elementami 3. Wydaje się naturalna i oczekiwana 4. Znika ze świadomej percepcji
Zła animacja: 1. Istnieje tylko dlatego, że „fajnie wygląda” 2. Spowalnia użytkownika 3. Przyciąga uwagę na siebie 4. Wywołuje niepokój lub niecierpliwość
Kluczowe zasady dla UI
1. Antycypacja — przygotowanie użytkownika na to, co nadchodzi.
.button {
transition: transform 0.1s ease-out;
}
.button:active {
transform: scale(0.97); /* Slight press before action */
}
2. Kontynuacja ruchu — ruch powinien zakończyć się naturalnie, z efektem sprężystego wygaszania.
.panel {
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
withAnimation(.spring(response: 0.4, dampingFraction: 0.7)) {
isOpen = true
}
3. Ease-In, Ease-Out — nic w naturze nie porusza się ze stałą prędkością.
| Krzywa | Zastosowanie | Charakter |
|---|---|---|
ease-out |
Elementy wchodzące | Szybki start, łagodne zatrzymanie |
ease-in |
Elementy wychodzące | Łagodny start, szybkie wyjście |
ease-in-out |
Zmiany stanu | Płynność przez cały czas trwania |
linear |
Wskaźniki ładowania | Ciągły, mechaniczny ruch |
4. Inscenizacja — kierowanie uwagi na to, co istotne. W danym momencie powinien poruszać się tylko jeden element, chyba że ruch jest choreografowany jako grupa.
5. Kaskadowe pojawianie się — elementy powinny pojawiać się sekwencyjnie, nie wszystkie naraz.
.list-item {
animation: fadeSlideIn 0.3s ease-out both;
}
.list-item:nth-child(1) { animation-delay: 0ms; }
.list-item:nth-child(2) { animation-delay: 50ms; }
.list-item:nth-child(3) { animation-delay: 100ms; }
.list-item:nth-child(4) { animation-delay: 150ms; }
@keyframes fadeSlideIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
Wytyczne dotyczące czasu trwania
| Czas trwania | Zastosowanie | Odczucie |
|---|---|---|
| 50–100ms | Mikrointerakcje (najechanie, naciśnięcie) | Natychmiastowa reakcja |
| 150–200ms | Proste zmiany stanu (przełącznik, zaznaczenie) | Żwawe |
| 250–350ms | Średnie przejścia (wysunięcie panelu, obrót karty) | Płynne |
| 400–500ms | Duże ruchy (przejścia między stronami, modale) | Celowe, świadome |
Wydajność — złota zasada
Animuj wyłącznie transform i opacity — są GPU i nie wyzwalają przeliczania układu.
/* BAD: Animating layout */
.panel { transition: left 0.3s, width 0.3s; }
/* GOOD: Using transform */
.panel { transition: transform 0.3s; }
Kiedy NIE animować
-
Użytkownik włączył
prefers-reduced-motioncss @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } } -
Animacja nie wnosi informacji — zbędne kółka ładowania, podskakujące elementy
- Użytkownik się spieszy — stany błędów, walidacja formularzy, wyniki wyszukiwania
- Animacja spowalniałaby powtarzane czynności — skróty klawiaturowe powinny pomijać animacje
- Dane są już załadowane — Bear wykorzystuje wstępne ładowanie treści, eliminując stany ładowania i sprawiając, że aplikacja działa natychmiastowo. Jeśli można wstępnie załadować dane, warto pominąć szkielety i wskaźniki ładowania.
// Bear's approach: preload so no loading state is needed
struct NoteListView: View {
@Query var notes: [Note] // SwiftData loads from disk instantly
// No loading state, no skeleton, no spinner — data is always there
var body: some View {
List(notes) { note in
NoteRow(note: note)
}
}
}
Szybka ściągawka z animacji
:root {
/* Durations */
--duration-instant: 0.1s;
--duration-fast: 0.15s;
--duration-normal: 0.25s;
--duration-slow: 0.4s;
/* Easings */
--ease-out: cubic-bezier(0.0, 0.0, 0.58, 1.0);
--ease-in: cubic-bezier(0.42, 0.0, 1.0, 1.0);
--ease-in-out: cubic-bezier(0.42, 0.0, 0.58, 1.0);
--ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
}
Wzorce interakcji
„The best interface is no interface.” — Golden Krishna
Wzorce interakcji definiują, w jaki sposób użytkownicy manipulują produktem, nawigują po nim i go rozumieją. Przedstawione tu wzorce zostały wyodrębnione na podstawie analizy produktów oferujących wyjątkowe interakcje.
Bezpośrednia manipulacja (Framer)
Abstrakcyjne koncepcje warto uczynić namacalnymi. Framer przekształca CSS — abstrakcyjne wartości liczbowe — w przeciągane uchwyty. Użytkownicy widzą, jak układ adaptuje się w czasie rzeczywistym.
/* Breakpoint handle styling */
.breakpoint-handle {
position: absolute;
top: 0;
bottom: 0;
width: 4px;
background: var(--accent);
cursor: col-resize;
opacity: 0.6;
transition: opacity 0.15s ease;
}
.breakpoint-handle:hover,
.breakpoint-handle:active {
opacity: 1;
width: 6px;
}
Kiedy stosować: wszędzie tam, gdzie wynik jest wizualny — przeciąganie w celu zmiany rozmiaru, selektory kolorów, przewijanie osi czasu.
Interfejsy kontekstowe (Flighty, Figma)
Wyświetlanie wyłącznie tego, co jest istotne w danym momencie. Flighty wykorzystuje 15 odrębnych stanów do śledzenia lotów. Panel właściwości w Figma całkowicie się zmienia w zależności od tego, co zostało zaznaczone.
| Faza (Flighty) | Co widzi użytkownik |
|---|---|
| 24 godz. przed | Kod potwierdzenia, informacje o terminalu |
| Na lotnisku | Numer bramki, godzina boardingu |
| W trakcie lotu | Pozostały czas, postęp, szacowany czas przylotu |
| Lądowanie | Bramki przesiadkowe, trasa dojścia |
enum ContextState: CaseIterable {
case farOut, dayBefore, headToAirport, atAirport
case atGate, boarding, inFlight, landed, connection
static func current(for flight: Flight, context: UserContext) -> ContextState {
// Factor in: time, location, flight status
// Return the single most relevant state
}
}
Antywzorzec: wyświetlanie wszystkich kontrolek i wyszarzanie nieistotnych. Tworzy to szum wizualny.
Inteligentna aktywacja (Halide)
Narzędzia powinny rozpoznawać kontekst i aktywować się samodzielnie. Lupa ostrości w Halide pojawia się przy przeciąganiu fokusu i znika po zwolnieniu. Nie potrzeba żadnych przycisków przełączania.
struct IntelligentlyActivated<Content: View>: ViewModifier {
let isInteracting: Bool
@State private var isVisible = false
func body(content: Content) -> some View {
content
.opacity(isVisible ? 1 : 0)
.scaleEffect(isVisible ? 1 : 0.95)
.animation(.easeInOut(duration: 0.2), value: isVisible)
.onChange(of: isInteracting) { _, newValue in
if newValue {
withAnimation { isVisible = true }
} else {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
if !isInteracting { isVisible = false }
}
}
}
}
}
Projektowanie dwutrybowe (Halide, Warp)
Zmiana trybu powinna transformować UI, nie tylko przełączać elementy. Tryby Auto i Manual w Halide to zupełnie różne interfejsy. Warp łączy CLI i GUI za pomocą czterech metod wprowadzania danych (wpisywanie, paleta poleceń, AI, mysz), nie zmuszając użytkowników do jednego paradygmatu.
Treść ustrukturyzowana (Warp, Bear, Craft)
Nadawanie struktury tradycyjnie nieustrukturyzowanym treściom. Warp zamienia wyjście terminala w dyskretne bloki, które można kopiować, udostępniać lub ponownie uruchamiać. Bear pozwala organizować notatki w trakcie pisania (#tag/subtag). W Craft każdy blok może stać się stroną — struktura wyłania się z użytkowania, nie z predefiniowanej hierarchii.
Stopniowe szkolenie (Superhuman)
Uczenie użytkowników szybszych metod poprzez powtarzalną ekspozycję. Paleta Cmd+K w Superhuman zawsze wyświetla skróty klawiaturowe obok wyników. Każde użycie to mikrolekcja.
/* Always show shortcut alongside command name */
.command-result {
display: flex;
justify-content: space-between;
padding: 8px 12px;
}
.command-shortcut {
font-family: var(--font-mono);
font-size: 12px;
color: var(--text-muted);
background: var(--bg-subtle);
padding: 2px 6px;
border-radius: 4px;
}
Antywzorzec: modalne okna z samouczkiem wyjaśniające funkcje. Wyjaśnienia się zapomina — praktyka zostaje w pamięci.
Wzorce interfejsów AI
„Najlepsze interfejsy AI uwidaczniają sposób działania maszyny i pozwalają zweryfikować jej wyniki”.
Interfejsy AI mierzą się ze szczególnymi wyzwaniami: użytkownicy nie mogą przewidzieć wyników ani ocenić ich poprawności na pierwszy rzut oka, a często nie są też w stanie stwierdzić, czy system działa prawidłowo, czy uległ awarii.
Główny problem
| Tradycyjne oprogramowanie | Oprogramowanie AI |
|---|---|
| Wynik jest przewidywalny | Wynik jest zmienny |
| Błędy są oczywiste | Błędy wyglądają wiarygodnie |
| Użytkownicy weryfikują wyniki przez testowanie | Użytkownicy weryfikują wyniki przez sprawdzanie źródeł |
| Ładowanie = oczekiwanie | Ładowanie = wykonywanie pracy (należy ją pokazać) |
| Domyślne zaufanie | Na zaufanie trzeba zapracować |
Projektowanie z cytowaniami na pierwszym planie (Perplexity)
Każde stwierdzenie dotyczące faktów musi zawierać odsyłacz do źródła. Perplexity osadza cytowania [1] bezpośrednio przy każdym stwierdzeniu, oferując podgląd po najechaniu kursorem oraz stale dostępny panel źródeł.
.citation-marker {
position: relative;
color: var(--accent);
cursor: pointer;
font-size: 0.8em;
vertical-align: super;
}
.citation-preview {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
width: 280px;
padding: 12px;
background: var(--bg-elevated);
border: 1px solid var(--border);
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
Antywzorzec: interfejsy AI, które generują stwierdzenia bez możliwych do prześledzenia źródeł. Jeśli model nie potrafi podać źródła, interfejs powinien to oznaczyć.
Wskaźniki etapów przesyłania strumieniowego (Perplexity)
Należy pokazywać użytkownikom, co robi AI, a nie tylko informować, że pracuje. Ogólne wskaźniki ładowania warto zastąpić wskaźnikami etapów: „Wyszukiwanie…” → „Czytanie 4 źródeł…” → „Pisanie odpowiedzi…”
.phase-indicator {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
background: color-mix(in srgb, var(--phase-color) 10%, transparent);
border-radius: 16px;
font-size: 13px;
color: var(--phase-color);
transition: all 0.3s ease;
}
.loading-dots span {
width: 4px;
height: 4px;
background: currentColor;
border-radius: 50%;
animation: pulse 1.4s ease-in-out infinite;
}
Przejrzyste informowanie o błędach
Gdy AI zawodzi lub nie ma pewności, należy to wyraźnie pokazać — zamiast maskować problem tekstem brzmiącym przekonująco.
| Sytuacja | Zły wzorzec | Dobry wzorzec |
|---|---|---|
| Niski poziom pewności | Przedstawienie informacji z pełnym przekonaniem | „Nie mam pewności, ale…” z mniej wyrazistym stylem |
| Nie znaleziono źródeł | Zmyślenie treści | „Nie udało mi się znaleźć źródeł potwierdzających to stwierdzenie” |
| Sprzeczne źródła | Dyskretny wybór jednego z nich | Pokazanie obu z wyróżnieniem sprzeczności |
| Nieaktualne informacje | Przedstawienie ich jako aktualnych | „Stan na [data]…” ze wskaźnikiem aktualności |
Kluczowy wniosek: użytkownicy wybaczają AI, które uczciwie informuje o niepewności. Nie wybaczają AI, które z przekonaniem podaje błędne informacje.
Dowody przebiegu pracy agentowej
Agenty AI wymagają stanów interfejsu, które potwierdzają wykonanie pracy, a nie tylko opisują podejmowane działania. Dobry agentowy przepływ pracy czytelnie przedstawia postępy za pomocą punktów kontrolnych: zaakceptowany plan, zgromadzone źródła, zastosowane zmiany, przeprowadzone testy, oczekujący przegląd oraz zablokowane lub gotowe wydanie.
| Stan agenta | Wzorzec interfejsu | Dlaczego ma to znaczenie |
|---|---|---|
| Planowanie | Jasno określony cel i kryteria akceptacji | Zapobiega optymalizowaniu przez agenta aktywności zamiast rezultatów |
| Analiza | Lista źródeł z poziomem pewności i aktualnością | Pozwala użytkownikom odróżnić zweryfikowane fakty od roboczych założeń |
| Wykonanie | Podsumowanie zmienionych plików powiązane z punktami kontrolnymi | Umożliwia przegląd zmian bez konieczności czytania całego zapisu rozmowy |
| Weryfikacja | Dowody z testów, tras, zrzutów ekranu lub działania systemu | Oddziela dowody od sztucznie kreowanej pewności |
| Wydanie | Stan zatwierdzenia, wdrożenia lub przeglądu natywnego | Zapobiega ukrywaniu niedokończonej pracy za pomyślnymi wynikami testów lokalnych podczas publikacji |
Antywzorzec: jeden stan „Gotowe” dla wieloetapowej pracy agenta. Złożona praca wymaga widocznego łańcucha odpowiedzialności: co zmieniono, jakie są na to dowody, z czego świadomie zrezygnowano i co nadal wymaga oceny człowieka.
Dieter Rams: dziesięć zasad
„Mniej, ale lepiej”. — Dieter Rams
Dieter Rams to najbardziej wpływowy projektant przemysłowy XX wieku. Jako główny projektant Braun w latach 1961–1995 tworzył produkty, które mimo upływu dekad pozostają ponadczasowe. Jego prace bezpośrednio zainspirowały język projektowania Apple.
Dziesięć zasad dobrego projektowania
1. Dobry design jest innowacyjny Nie należy kopiować. Rozwijającą się technologię trzeba łączyć z innowacyjnym designem.
2. Dobry design czyni produkt użytecznym Każdy element musi mieć określone zastosowanie. Forma podąża za funkcją.
3. Dobry design jest estetyczny Piękno nie jest powierzchowne — jest niezbędne. Produkty używane każdego dnia wpływają na nasze samopoczucie.
4. Dobry design czyni produkt zrozumiałym Użytkownicy nie powinni potrzebować instrukcji. Interfejs powinien objaśniać się sam.
5. Dobry design jest dyskretny Design powinien wspierać, a nie przytłaczać. Najważniejsze są treści użytkownika, nie UI.
/* Obtrusive: UI competes with content */
.editor {
background: linear-gradient(135deg, purple, blue);
border: 3px dashed gold;
}
/* Unobtrusive: UI recedes, content shines */
.editor {
background: var(--color-background);
border: 1px solid var(--color-border);
}
6. Dobry design jest uczciwy Nie należy stosować dark patterns ani obiecywać zbyt wiele. O ograniczeniach trzeba informować przejrzyście.
7. Dobry design jest trwały Należy unikać trendów, które szybko się zestarzeją. Klasyka zamiast chwilowej mody.
TRENDY (will date): TIMELESS:
- Extreme glassmorphism - Clean typography
- Neon colors, glitch effects - Subtle elevation
- Aggressive gradients - Neutral palette with considered accent
8. Dobry design jest dopracowany w każdym szczególe Nic nie może być przypadkowe. Stany ładowania, braku zawartości i błędów — wszystko musi zostać zaprojektowane.
9. Dobry design jest przyjazny dla środowiska Wydajność ma znaczenie dla środowiska. Należy szanować uwagę użytkownika i tworzyć wydajny kod.
10. Dobry design to możliwie najmniej designu Należy usunąć wszystko, co nie jest konieczne. Najlepszy design jest niewidoczny.
Wzorce webowe 2026
Natywne CSS zastępuje obecnie JavaScript w coraz większej liczbie problemów związanych z układem i interakcjami. Lata 2025–2026 przyniosły pozycjonowanie względem kotwic, animacje sterowane przewijaniem oraz @starting-style w przeglądarkach produkcyjnych, a w połowie 2026 roku dodano automatyczne dopasowywanie rozmiaru kontrolek formularzy, dekoracje odstępów i automatyczne dopasowywanie tekstu.
W tym przypadku stan obsługi jest ważniejszy niż nowość. Funkcja dostępna w jednym silniku stanowi progresywne ulepszenie; na funkcji o statusie Baseline Newly available można już bezpiecznie polegać. Poniższa tabela rozróżnia te dwie kategorie według stanu na sierpień 2026 roku.
| Funkcja | Chrome | Firefox | Safari | Stan |
|---|---|---|---|---|
field-sizing |
123 | 152 | 26.2 | Baseline Newly available |
shape-outside: rect() / xywh() |
149 | 149 | 17.2 | Baseline Newly available |
background-clip: border-area |
150 | — | 18.2 | Dwa silniki |
Dekoracje odstępów (column-rule w układzie grid/flex) |
149 | — | — | Tylko Chrome |
text-fit |
150 | — | — | Tylko Chrome |
focusgroup |
150 | — | — | Tylko Chrome |
Źródła: Nowości na platformie webowej w czerwcu i lipcu, web.dev.
Zapytania kontenerowe
Rozmiar komponentów należy określać na podstawie ich kontenera, a nie obszaru wyświetlania.
.card-grid {
container-type: inline-size;
container-name: card-grid;
}
.card {
display: grid;
gap: 16px;
padding: 20px;
}
@container card-grid (min-width: 400px) {
.card {
grid-template-columns: auto 1fr;
}
}
@container card-grid (min-width: 600px) {
.card {
padding: 32px;
gap: 24px;
}
}
Selektor :has()
Wybieranie elementu nadrzędnego na podstawie jego elementów potomnych — wcześniej niemożliwe bez JavaScript.
/* Card with image gets different padding */
.card:has(img) {
padding: 0;
}
.card:has(img) .card-content {
padding: 20px;
}
/* Form group with error */
.form-group:has(.input:invalid) .form-label {
color: var(--color-error);
}
/* Highlight navigation when on that page */
.nav-item:has(a[aria-current="page"]) {
background: var(--color-surface);
}
Zagnieżdżanie w CSS
Natywne zagnieżdżanie bez preprocesorów.
.card {
background: var(--color-surface);
border-radius: 12px;
padding: 24px;
& .card-title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 8px;
}
& .card-body {
color: var(--color-text-secondary);
line-height: 1.6;
}
&:hover {
box-shadow: var(--shadow-md);
}
@media (min-width: 768px) {
padding: 32px;
}
}
Dekoracje odstępów
Odstępy w układach grid i flex mogą mieć własne linie, dzięki czemu separatory nie wymagają już pseudoelementów, obramowania każdego elementu potomnego ani osobnego kontenera dla każdej kolumny. Funkcja jest dostępna wyłącznie w Chrome 149 i nowszych wersjach, dlatego stanowi progresywne ulepszenie, a nie podstawę układu.
.pricing-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 32px;
/* Vertical rules between columns, horizontal between rows */
column-rule: 1px solid var(--color-border);
row-rule: 1px solid var(--color-border);
}
W starym podejściu do każdego elementu poza pierwszym dodawano border-left, co przestawało działać, gdy tylko siatka zawijała się do drugiego wiersza. Dekoracje odstępów rysowane są w samym odstępie, więc pozostają prawidłowe również po zawinięciu układu.
Ponieważ funkcję obsługuje tylko jeden silnik, reguły te należy traktować jako dekorację, nigdy zaś jako element rozdzielający znaczeniowo treść. Układ, który bez nich staje się niejednoznaczny, nie spełnia swojej funkcji w przeglądarkach Firefox i Safari.
Kontrolki formularzy dopasowujące rozmiar do zawartości
field-sizing: content pozwala polom tekstowym, obszarom tekstowym i listom wyboru rozszerzać się oraz zwężać wraz z wpisywaną zawartością, zastępując JavaScript obliczające wysokość przewijania, które jest ponownie implementowane niemal w każdej bazie kodu.
.comment-box {
field-sizing: content;
min-height: 3lh; /* floor: three lines */
max-height: 12lh; /* ceiling: then scroll */
}
.tag-input {
field-sizing: content;
min-width: 8ch;
}
Zawsze należy łączyć tę właściwość z ograniczeniami min-/max-. Bez dolnej granicy puste pole kurczy się niemal do zera, a bez górnej granicy wklejenie długiego tekstu wypycha przycisk wysyłania poza ekran.
W czerwcu 2026 roku funkcja uzyskała status Baseline Newly available, dlatego można bezpiecznie używać jej jako podstawowego mechanizmu, a nie tylko ulepszenia.
Tekst dopasowany do swojego pola
text-fit skaluje rozmiar czcionki tak, aby tekst wypełniał szerokość kontenera. Przydaje się w przypadku wyeksponowanych nagłówków i dużych liczb w panelach, które wcześniej wymagały skryptu wykonującego pomiary.
.stat-value {
text-fit: consistent; /* one size for the whole box */
}
Funkcja jest dostępna wyłącznie w Chrome 150. Najpierw należy określić zwykłą wartość font-size, aby inne silniki otrzymały świadomie dobrany rozmiar zamiast wartości domyślnej:
.stat-value {
font-size: clamp(2rem, 8vw, 6rem); /* the real answer everywhere */
text-fit: consistent; /* refinement where supported */
}
clamp() rozwiązuje już większość problemów, w których rozważa się użycie tej funkcji, a ponadto jest powszechnie obsługiwane. Po text-fit warto sięgnąć, gdy długość treści jest na tyle zmienna, że nie sprawdza się żadne pojedyncze ograniczenie.
Gradientowe obramowania bez obejścia
background-clip: border-area maluje tło w obszarze obramowania, dzięki czemu gradientowe obramowanie wymaga dwóch wierszy reguł zamiast zagnieżdżonego elementu lub sztuczki z mask-composite.
.featured-card {
border: 2px solid transparent;
border-radius: 12px;
background:
linear-gradient(var(--color-surface), var(--color-surface)) padding-box,
linear-gradient(135deg, #6366f1, #ec4899) border-area;
}
Funkcja jest dostępna w Chrome 150 i Safari 18.2; Firefox jeszcze jej nie obsługuje. Najpierw należy zadeklarować jednolity border-color, aby rozwiązaniem zastępczym było rzeczywiste obramowanie, a nie przezroczyste.
Nawigacja klawiszami strzałek bez procedury obsługi keydown
Atrybut focusgroup informuje przeglądarkę, że zestaw kontrolek tworzy jedną jednostkę nawigacji klawiaturą: klawisz Tab przenosi fokus do grupy tylko raz, klawisze strzałek przemieszczają go w jej obrębie, a kolejne naciśnięcie klawisza Tab opuszcza grupę. Takiego zachowania wymagają paski narzędzi, paski kart, kontrolki segmentowe i grupy przycisków działające jak przyciski opcji. Jest to również element, który najczęściej implementuje się błędnie w komponentach tworzonych od podstaw.
<div role="toolbar" focusgroup="wrap">
<button>Bold</button>
<button>Italic</button>
<button>Underline</button>
</div>
wrap sprawia, że po naciśnięciu klawisza strzałki na ostatnim elemencie fokus wraca do pierwszego. Domyślne zachowanie zatrzymuje nawigację na końcach grupy.
Funkcja jest dostępna wyłącznie w Chrome 150, dlatego do czasu upowszechnienia obsługi należy zachować istniejącą procedurę obsługi keydown. Warto jednak znać ten atrybut już teraz, ponieważ precyzyjnie nazywa dostępne zachowanie: pasek narzędzi powinien stanowić jeden punkt zatrzymania klawisza Tab, a nie pięć. To oczekiwanie jest starsze od samego atrybutu o dziesięciolecia. ARIA Authoring Practices opisuje ten wzorzec niezależnie od sposobu jego implementacji.
Integracja z HTMX
Interaktywność sterowana przez serwer bez rozbudowanych frameworków JavaScript.
<!-- Load content on click -->
<button hx-get="/api/more-items"
hx-target="#item-list"
hx-swap="beforeend"
hx-indicator="#loading">
Load More
</button>
<!-- Form with inline validation -->
<form hx-post="/api/contact"
hx-target="#form-response"
hx-swap="outerHTML">
<input type="email" name="email"
hx-post="/api/validate-email"
hx-trigger="blur"
hx-target="next .error" />
<span class="error"></span>
</form>
Pozycjonowanie względem kotwic
Natywne pozycjonowanie CSS jednego elementu względem drugiego — bez potrzeby używania JavaScript. Przydatne w podpowiedziach, wyskakujących elementach i menu rozwijanych podążających za wywołującymi je kontrolkami.
/* Anchor an element to another */
.trigger {
anchor-name: --my-trigger;
}
.tooltip {
position: fixed;
position-anchor: --my-trigger;
top: anchor(bottom);
left: anchor(center);
translate: -50% 8px;
}
Animacje sterowane przewijaniem
Postęp animacji można powiązać z pozycją przewijania. Pozwala to tworzyć wskaźniki postępu czytania, efekty paralaksy i sekwencje odsłaniania bez JavaScript.
/* Reading progress bar */
.progress-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 3px;
background: var(--color-primary);
transform-origin: left;
animation: progress linear;
animation-timeline: scroll();
}
@keyframes progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
@starting-style
Określanie początkowych stylów elementów dodawanych do DOM — umożliwia tworzenie animacji wejścia wyłącznie za pomocą CSS, bez JavaScript.
.card {
opacity: 1;
transform: translateY(0);
transition: opacity 0.3s ease, transform 0.3s ease;
@starting-style {
opacity: 0;
transform: translateY(10px);
}
}
System tokens projektowych
Kompletny system tokens zapewniający spójność w całej aplikacji.
:root {
/* Colors */
--color-text: #1a1a1a;
--color-text-secondary: #666666;
--color-text-muted: #999999;
--color-background: #ffffff;
--color-surface: #f8f9fa;
--color-surface-elevated: #ffffff;
--color-border: #e5e7eb;
--color-primary: #3b82f6;
--color-primary-hover: #2563eb;
--color-success: #10b981;
--color-warning: #f59e0b;
--color-error: #ef4444;
/* Typography */
--font-sans: system-ui, -apple-system, sans-serif;
--font-mono: "SF Mono", Consolas, monospace;
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 2rem;
--leading-tight: 1.25;
--leading-normal: 1.5;
--leading-relaxed: 1.75;
/* Spacing (8px base) */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-12: 3rem; /* 48px */
--space-16: 4rem; /* 64px */
/* Borders */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-full: 9999px;
/* Shadows */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
/* Transitions */
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--duration-fast: 100ms;
--duration-normal: 200ms;
}
Dobrze zaprojektowany tryb ciemny
Nie wystarczy odwrócić kolorów — interfejs należy przeprojektować z myślą o ciemnym otoczeniu.
@media (prefers-color-scheme: dark) {
:root {
/* Neutrals */
--color-background: hsl(220, 13%, 10%);
--color-surface: hsl(220, 13%, 15%);
--color-surface-elevated: hsl(220, 13%, 18%);
--color-border: hsl(220, 13%, 23%);
/* Text (inverted) */
--color-text: hsl(220, 9%, 93%);
--color-text-secondary: hsl(220, 9%, 70%);
--color-text-muted: hsl(220, 9%, 55%);
/* Adjust saturation for dark mode */
--color-primary: hsl(220, 80%, 60%);
--color-success: hsl(142, 70%, 45%);
--color-error: hsl(0, 80%, 65%);
/* Shadows in dark mode need adjustment */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
}
}
Zasady projektowania trybu ciemnego: - Zmniejszyć nasycenie kolorów na dużych powierzchniach - Zwiększyć jasność kolorów akcentujących - Wzmocnić cienie (wymagają większego kontrastu) - Projektować tryb ciemny świadomie, a nie traktować go jako dodatku na późniejszym etapie
Procesy ekstrakcji z Figma
Przekształcanie plików projektowych w kod produkcyjny wymaga systematycznej ekstrakcji tokenów projektowych (design tokens) — kolorów, typografii, odstępów i efektów definiujących język wizualny projektu.
Eksport zmiennych z Figma
Natywna funkcja Variables w Figma zapewnia najprostszy sposób ekstrakcji:
Etapy eksportu:
1. Otworzyć plik Figma → panel Local Variables
2. Kliknąć menu kolekcji → „Export to JSON”
3. Zapisać jako figma-variables.json
Struktura tokenów JSON:
{
"colors": {
"primitive": {
"blue-500": { "value": "#3b82f6", "type": "color" },
"blue-600": { "value": "#2563eb", "type": "color" }
},
"semantic": {
"primary": { "value": "{colors.primitive.blue-500}", "type": "color" },
"primary-hover": { "value": "{colors.primitive.blue-600}", "type": "color" }
}
},
"spacing": {
"1": { "value": "4px", "type": "spacing" },
"2": { "value": "8px", "type": "spacing" },
"4": { "value": "16px", "type": "spacing" }
}
}
Transformacja tokenów do CSS
Niestandardowe właściwości CSS:
:root {
/* Primitive colors (direct values) */
--color-blue-50: #eff6ff;
--color-blue-100: #dbeafe;
--color-blue-500: #3b82f6;
--color-blue-600: #2563eb;
--color-blue-900: #1e3a8a;
/* Semantic colors (reference primitives) */
--color-primary: var(--color-blue-500);
--color-primary-hover: var(--color-blue-600);
--color-background: var(--color-white);
--color-surface: var(--color-gray-50);
/* Spacing (8px grid) */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
/* Typography */
--font-size-sm: 0.875rem;
--font-size-base: 1rem;
--font-size-lg: 1.125rem;
--line-height-tight: 1.25;
--line-height-normal: 1.5;
/* Effects */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
}
Tokeny trybu ciemnego:
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--color-gray-900);
--color-surface: var(--color-gray-800);
--color-text: var(--color-gray-100);
--color-text-secondary: var(--color-gray-400);
/* Adjusted shadows for dark mode */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
}
}
Transformacja tokenów do SwiftUI
Rozszerzenie kolorów:
import SwiftUI
extension Color {
// MARK: - Primitive Colors
static let blue50 = Color(hex: "eff6ff")
static let blue500 = Color(hex: "3b82f6")
static let blue600 = Color(hex: "2563eb")
// MARK: - Semantic Colors
static let brandPrimary = Color.blue500
static let brandPrimaryHover = Color.blue600
// MARK: - Surface Colors
static let surfaceBackground = Color(light: .white, dark: Color(hex: "0f172a"))
static let surfaceElevated = Color(light: Color(hex: "f8fafc"), dark: Color(hex: "1e293b"))
}
extension Color {
init(hex: String) {
// Standard hex parsing implementation
}
init(light: Color, dark: Color) {
self.init(UIColor { traits in
traits.userInterfaceStyle == .dark ? UIColor(dark) : UIColor(light)
})
}
}
Stałe odstępów:
enum Spacing {
static let xs: CGFloat = 4 // --space-1
static let sm: CGFloat = 8 // --space-2
static let md: CGFloat = 16 // --space-4
static let lg: CGFloat = 24 // --space-6
static let xl: CGFloat = 32 // --space-8
}
// Usage
VStack(spacing: Spacing.md) {
// ...
}
.padding(Spacing.lg)
Lista kontrolna przekazania projektu przez projektanta
Co projektanci powinni wyeksportować:
| Typ zasobu | Format | Uwagi |
|---|---|---|
| Kolory | Zmienne JSON | Uwzględnić tryb jasny i ciemny |
| Typografia | Eksport stylów | Krój pisma, rozmiar, grubość, wysokość wiersza |
| Odstępy | Zmienne JSON | Udokumentowana jednostka bazowa |
| Ikony | SVG | Konturowe, jednokolorowe |
| Obrazy | PNG @2x/@3x lub WebP | Z kompresją |
| Komponenty | Łącza Figma | Do wykorzystania podczas implementacji |
Kryteria kontroli jakości:
- [ ] Wszystkie kolory zdefiniowano jako zmienne (bez zakodowanych na stałe wartości szesnastkowych)
- [ ] Typografia korzysta ze zdefiniowanych stylów tekstu
- [ ] Odstępy są zgodne z systemem siatki (baza 8px)
- [ ] Dostarczono warianty trybu ciemnego
- [ ] Udokumentowano stany interaktywne (hover, active, disabled)
- [ ] Oznaczono responsywne punkty przerwania
- [ ] Wskazano wymagania dostępności (współczynniki kontrastu)
Materiały przekazywane programiście:
- Pliki tokenów (JSON/CSS/Swift zależnie od platformy)
- Specyfikacje komponentów z wymiarami
- Wyeksportowane zasoby w wymaganych formatach
- Dokumentacja interakcji (stany, animacje)
- Adnotacje dotyczące dostępności
Tabele podręczne
Zasady Gestalt
| Zasada | Reguła | Zastosowanie |
|---|---|---|
| Bliskość | Powiązane elementy = mała odległość | Formularze, sekcje |
| Podobieństwo | Taki sam wygląd = taka sama funkcja | Przyciski, karty |
| Figura–tło | Wyraźne rozdzielenie warstw | Okna modalne, karty |
| Ciągłość | Podążanie wzdłuż linii | Osie czasu, wyrównanie |
| Domknięcie | Mózg uzupełnia kształty | Ikony, wskazówki przewijania |
Typografia
| Element | Rozmiar | Grubość | Wysokość wiersza |
|---|---|---|---|
| Tekst główny | 16px | 400 | 1,5–1,7 |
| Nagłówki | 24–48px | 600–700 | 1,1–1,2 |
| Etykiety UI | 12–14px | 500 | 1,3–1,4 |
| Podpisy | 12px | 400 | 1,4 |
Role kolorów
| Rola | Tryb jasny | Tryb ciemny |
|---|---|---|
| Tło | #ffffff | #0f172a |
| Powierzchnia | #f4f5f7 | #1e293b |
| Obramowanie | #e4e6ea | #334155 |
| Tekst | #1a1a2e | #f1f5f9 |
| Tekst przygaszony | #6b7280 | #94a3b8 |
| Kolor główny | #3b82f6 | #60a5fa |
| Powodzenie | #22c55e | #4ade80 |
| Błąd | #ef4444 | #f87171 |
Skala odstępów
| Token | Wartość | Zastosowanie |
|---|---|---|
| –space-1 | 4px | Odstępy między ikonami |
| –space-2 | 8px | Elementy w wierszu |
| –space-4 | 16px | Domyślne odstępy |
| –space-6 | 24px | Wewnętrzne odstępy kart |
| –space-8 | 32px | Odstępy między sekcjami |
| –space-16 | 64px | Sekcje strony |
Lista kontrolna projektu
Przed opublikowaniem dowolnego interfejsu należy sprawdzić:
Gestalt
- [ ] Elementy powiązane znajdują się bliżej siebie niż elementy niepowiązane (bliskość)
- [ ] Podobne funkcje mają podobne style (podobieństwo)
- [ ] Pierwszy plan jest wyraźnie oddzielony od tła (figura–tło)
- [ ] Wzrok naturalnie podąża przez układ (ciągłość)
Typografia
- [ ] Bazowy rozmiar czcionki wynosi co najmniej 16px
- [ ] Wysokość wiersza tekstu głównego wynosi co najmniej 1,5
- [ ] Długość wiersza nie przekracza 75 znaków
- [ ] Hierarchia jest czytelna (można rozróżnić 3 poziomy)
- [ ] W całym projekcie stosowana jest spójna skala
Kolor
- [ ] Cały tekst spełnia wymaganie kontrastu 4,5:1 (WCAG AA)
- [ ] Kolor nie jest jedynym wskaźnikiem (stosowane są również ikony lub etykiety)
- [ ] Tryb ciemny zaprojektowano świadomie
- [ ] Zachowano proporcje 60-30-10
Hierarchia wizualna
- [ ] Można wskazać najważniejszy element
- [ ] Wzrok podąża w zamierzonej kolejności
- [ ] Każda sekcja zawiera jedno wyraźne CTA
- [ ] Skala typograficzna jest spójna
Odstępy
- [ ] Wszystkie odstępy korzystają ze zdefiniowanej skali (bez arbitralnych wartości)
- [ ] Karty i komponenty mają spójne odstępy wewnętrzne
- [ ] Odstępy na urządzeniach mobilnych zapewniają komfort użytkowania
- [ ] Wyrównanie do siatki jest spójne (baza 8px)
Interakcja
- [ ] Czy użytkownicy mogą realizować cele bez zastanawiania się nad obsługą narzędzia?
- [ ] Czy UI dostosowuje się do bieżącego kontekstu?
- [ ] Czy narzędzia są widoczne tylko wtedy, gdy są potrzebne?
- [ ] Czy wielokrotne używanie interfejsu pozwala poznawać szybsze metody pracy?
Interfejsy AI
- [ ] Każde stwierdzenie dotyczące faktów ma możliwe do prześledzenia źródło
- [ ] Transmisja strumieniowa pokazuje etapy procesu, a nie tylko wskaźnik ładowania
- [ ] Stany błędów są prezentowane otwarcie, a nie ukrywane
- [ ] Wyniki o niskim poziomie pewności są wyróżnione wizualnie
Kontrola według Dieter Rams
- [ ] Czy można coś usunąć?
- [ ] Czy każdy element pełni określoną funkcję?
- [ ] Czy za 5 lat projekt nadal będzie wyglądał aktualnie?
- [ ] Czy zaprojektowano każdy stan?
Zasoby
Książki: - As Little Design as Possible autorstwa Sophie Lovell (Dieter Rams) - The Elements of Typographic Style autorstwa Robert Bringhurst
Narzędzia: - Narzędzie WebAIM do sprawdzania kontrastu - Generator skali typograficznej - Figma Tokens Studio — zarządzanie tokenami projektowymi
Systemy projektowe: - Apple HIG - Material Design 3 - Radix UI - shadcn/ui
Studia przypadków projektowych
Dogłębne analizy 48 wyjątkowych produktów, dokumentujące wzorce i zasady, które warto wykorzystać.
Narzędzia deweloperskie i AI
| Produkt | Kluczowy wkład |
|---|---|
| Figma | Obecność wielu użytkowników, panele uwzględniające kontekst |
| Warp | Terminal oparty na blokach, pomost CLI–GUI |
| Framer | Wizualne projektowanie responsywne, kontrolki właściwości |
| Vercel | Doskonały tryb ciemny, nastrojowa prezentacja statusu |
| Linear | Optimistic UI, obsługa przede wszystkim za pomocą klawiatury |
| Raycast | System rozszerzeń, szybkie działania |
| Stripe | Znakomita dokumentacja, projektowanie API |
| Perplexity | AI eksponująca źródła, fazy strumieniowego generowania |
| Obsidian | Modułowość oparta na lokalnym przechowywaniu danych, interfejsy grafów wiedzy |
Narzędzia natywne dla Apple i narzędzia kreatywne
| Produkt | Kluczowy wkład |
|---|---|
| Flighty | 15 inteligentnych stanów, Live Activities, wizualizacja danych |
| Halide | Inteligentna aktywacja, sterowanie gestami |
| Bear | Typografia na pierwszym planie, tagowanie bezpośrednio w tekście |
| Craft | Natywność przede wszystkim na wielu platformach, zagnieżdżone strony |
| Things | Daty odroczenia, wzorce szybkiego wprowadzania |
| Darkroom | Wciągający ciemny UI, edycja skoncentrowana na zdjęciu |
| Procreate | Narzędzia kreatywne obsługiwane przede wszystkim gestami |
| Overcast | Niewidoczna inżynieria dźwięku jako projektowanie interfejsu |
| Camo | Profesjonalny UI do produkcji wideo |
| Ivory | Dopracowana oś czasu, swobodna precyzja |
| Anybox | Przejrzystość zgodna z natywnymi wzorcami platformy |
| Drafts | Klarowne zapisywanie treści skoncentrowane na tekście |
| Notion Calendar | Precyzja kalendarza, integracja z przestrzenią roboczą |
Produktywność, wiedza i finanse
| Produkt | Kluczowy wkład |
|---|---|
| Superhuman | Reguła 100 ms, nauka obsługi palety poleceń, wdrożenie oparte na ćwiczeniach |
| Notion | System bloków, polecenia z ukośnikiem |
| Arc | Przestrzenie, widok dzielony, pasek poleceń |
| Todoist | Ciepły minimalizm, maksymalna powściągliwość |
| Amie | Produktywność dająca radość, ciepły minimalizm |
| Loom | Przyjazny profesjonalizm asynchronicznego wideo |
| Pitch | Wyrazisty język projektowania prezentacji |
| Readwise Reader | Narzędzia do pogłębionej lektury, kosmiczna identyfikacja marki |
| Copilot Money | Filmowa wizualizacja danych finansowych |
| 1Password | Bezpieczeństwo bez zbędnych utrudnień |
| Mercury | Filmowe wyrafinowanie bankowości |
Produkty konsumenckie, społeczności i zaufanie
| Produkt | Kluczowy wkład |
|---|---|
| Spotify | Kolor, emocje i skala |
| Duolingo | Grywalizacja jako język projektowania |
| Signal | Bezpieczeństwo dzięki prostocie |
| Airbnb | Zaufanie w skali platformy handlowej |
| Bluesky | Przejrzystość algorytmów |
| Letterboxd | Kino jako obiekt społeczny |
| Strava | Dane GPS jako waluta społeczna |
| Apple Music | Redakcyjny charakter, dźwięk przestrzenny |
| Headspace | Spokój jako strategia projektowania interfejsu |
| Zomato | UX kulinarny oparty na wyrazistej osobowości |
Produkty fizyczne, gry i dostępność
| Produkt | Kluczowy wkład |
|---|---|
| Balatro | Pętle informacji zwrotnej, systemy odczuwania rozgrywki |
| Rivian | Fotografia przygodowa i monumentalna typografia |
| Teenage Engineering | Ograniczenia jako tożsamość estetyczna |
| OKO | Dostępność oparta na dźwięku i haptyce |
| CARROT Weather | Osobowość jako wyróżnik aplikacji użytkowej |
Ten przewodnik rozwija się wraz z praktyką. Zasady projektowania są ponadczasowe, lecz ich zastosowanie ewoluuje wraz z technologią i pogłębianiem wiedzy.