Guide / 12 min

Zasady projektowania dla inżynierów oprogramowania

Zasady projektowania dla inżynierów oprogramowania: kompletny przewodnik

Zaktualizowano 9 lutego 2026

Aktualizacja z lutego 2026: Dodano dwie nowe sekcje — Wzorce interakcji (8 paradygmatów na podstawie analizy Framer, Flighty, Halide, Warp, Bear, Craft i Superhuman) oraz Wzorce interfejsów AI (projektowanie z cytatami na pierwszym planie, fazy streamingu, przejrzystość błędów z Perplexity). Zaktualizowano sekcję Wzorce webowe do 2026 roku, uwzględniając anchor positioning, animacje sterowane przewijaniem oraz @starting-style. Zaktualizowano sekcję dotyczącą dostępności, aby odzwierciedlić standaryzację ISO dla WCAG 2.2. Szczegółowe analizy 16 wyjątkowych produktów można znaleźć w sekcji Studia projektowe.

Przez lata studiowałem design, jednocześnie tworząc oprogramowanie — przyswajałem zasady od legend takich jak Dieter Rams i analizowałem interfejsy produktów takich jak Linear, Stripe czy Raycast. Ten przewodnik stanowi destylat tej wiedzy w kompleksowe kompendium, którego sam potrzebowałem, gdy zacząłem zwracać uwagę na to, jak moje oprogramowanie wygląda i jak się z niego korzysta.

Design to nie dekoracja. To komunikacja. Każdy piksel komunikuje funkcję, hierarchię i znaczenie. Różnica między oprogramowaniem, które wygląda amatorsko, a oprogramowaniem, które wygląda profesjonalnie, polega na zrozumieniu tych zasad i ich konsekwentnym stosowaniu.

Ten przewodnik zakłada, że czytelnik potrafi już pisać kod. Uczy patrzenia — rozumienia, dlaczego niektóre interfejsy wydają się intuicyjne, a inne chaotyczne, i co ważniejsze — jak tworzyć te pierwsze.


Spis treści

Część 1: Podstawy

  1. Psychologia Gestalt
  2. Typografia
  3. Teoria koloru
  4. Hierarchia wizualna
  5. Odstępy i rytm
  6. Zasady animacji

Część 2: Interakcja i AI

  1. Wzorce interakcji
  2. Wzorce interfejsów AI

Część 3: Filozofia projektowania

  1. Dieter Rams: dziesięć zasad

Część 4: Implementacja

  1. Wzorce webowe 2026
  2. System design tokens
  3. Tryb ciemny zrobiony dobrze
  4. Przepływy pracy z Figma

Część 5: Materiały referencyjne

  1. Tabele szybkiego odniesienia
  2. Lista kontrolna projektu
  3. Studia projektowe

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("[email protected]", 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

The file write was blocked due to sensitive file permissions. The translation is complete — here’s what was produced:

Batch 3 (pl) — color-theory, visual-hierarchy, spacing-rhythm:

  • Added the missing Teoria koloru section (wasn’t in the previous file)
  • Refined Hierarchia wizualna — improved phrasing (“sprawiają wrażenie naturalnych i intuicyjnych”), consistent lowercase in hierarchy tool descriptions, polished applied patterns translations
  • Refined Odstępy i rytm — improved quote translation, better table header (“Szybka ściągawka z odstępów”), clearer phrasing throughout
  • Removed Zasady animacji which was incorrectly included (belongs to batch 4)
  • All code blocks, WCAG placeholder, technical terms, and URLs preserved exactly
  • Formal register with impersonal constructions (można, warto) throughout
  • Correct grammatical cases and gender agreement

Would you like to approve the write to .claude/i18n/cache/pl/design/batch_3.md?

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ć

  1. Użytkownik włączył prefers-reduced-motion css @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } }

  2. Animacja nie wnosi informacji — zbędne kółka ładowania, podskakujące elementy

  3. Użytkownik się spieszy — stany błędów, walidacja formularzy, wyniki wyszukiwania
  4. Animacja spowalniałaby powtarzane czynności — skróty klawiaturowe powinny pomijać animacje
  5. 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 czynią proces działania maszyny widocznym, a jej wyniki — weryfikowalnymi.”

Interfejsy AI stoją przed wyjątkowymi wyzwaniami: użytkownicy nie są w stanie przewidzieć wyników, nie mogą zweryfikować poprawności na pierwszy rzut oka i często nie potrafią odróżnić, czy system działa prawidłowo, czy uległ awarii.

Główny problem

Tradycyjne oprogramowanie Oprogramowanie AI
Wynik jest przewidywalny Wynik bywa różny
Błędy są oczywiste Błędy wyglądają wiarygodnie
Użytkownicy weryfikują poprzez testowanie Użytkownicy weryfikują poprzez sprawdzanie źródeł
Ładowanie = czekanie Ładowanie = praca (pokaż to)
Zaufanie domyślne Zaufanie trzeba zdobyć

Projektowanie z naciskiem na cytowania (Perplexity)

Każde stwierdzenie faktograficzne musi być powiązane ze źródłem. Perplexity umieszcza cytowania inline [1] przy każdym twierdzeniu, z podglądem po najechaniu kursorem i stałym panelem ź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 generujące twierdzenia bez możliwości śledzenia źródeł. Jeśli model nie jest w stanie podać cytowania, interfejs powinien to oznaczyć.

Wskaźniki faz streamingu (Perplexity)

Warto pokazywać użytkownikom, co AI właśnie robi, a nie tylko, że coś się dzieje. Zamiast ogólnych spinnerów należy stosować wskaźniki faz: „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;
}

Przejrzystość błędów

Gdy AI zawodzi lub nie jest pewne wyniku, należy to jasno pokazać — nie ukrywać za pewnie brzmiącym tekstem.

Sytuacja Zły wzorzec Dobry wzorzec
Niska pewność Stwierdzenie z pewnością „Nie jestem pewien, ale…” z wyciszonym stylem
Brak źródeł Generowanie tekstu „Nie udało mi się znaleźć źródeł dla tego twierdzenia”
Sprzeczne źródła Ciche wybranie jednego Pokazanie obu z zaznaczonym konfliktem
Nieaktualne informacje Przedstawienie jako bieżące „Stan na [data]…” ze wskaźnikiem aktualności

Kluczowy wniosek: Użytkownicy wybaczają AI, które jest szczere co do niepewności. Nie wybaczają AI, które myli się z pewnością siebie.


Dieter Rams: dziesięć zasad

„Mniej, ale lepiej.” — Dieter Rams

Dieter Rams to najbardziej wpływowy projektant wzornictwa przemysłowego XX wieku. Jako szef działu designu w Braun w latach 1961–1995 tworzył produkty, które pozostają ponadczasowe dekady później. Jego praca bezpośrednio zainspirowała język projektowania Apple.

Dziesięć zasad dobrego designu

1. Dobry design jest innowacyjny Nie kopiuj. Łącz rozwijającą się technologię z innowacyjnym projektowaniem.

2. Dobry design czyni produkt użytecznym Każdy element musi służyć celowi. Forma podąża za funkcją.

3. Dobry design jest estetyczny Piękno nie jest powierzchowne — jest niezbędne. Produkty, z których korzystamy codziennie, wpływają na nasze samopoczucie.

4. Dobry design czyni produkt zrozumiałym Użytkownicy nie powinni potrzebować instrukcji. Interfejs uczy sam siebie.

5. Dobry design jest dyskretny Design powinien wspierać, a nie przytłaczać. Gwiazdą jest treść użytkownika, nie interfejs.

/* 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 stosuj dark patterns. Nie składaj nadmiernych obietnic. Bądź transparentny wobec ograniczeń.

7. Dobry design jest trwały Unikaj trendów, które szybko się zestarzeją. Klasyka zamiast mody.

MODNE (szybko się zestarzeje):    PONADCZASOWE:
- Ekstremalny glassmorphism       - Czysta typografia
- Neonowe kolory, efekty glitch   - Subtelna głębia
- Agresywne gradienty             - Neutralna paleta z przemyślanym akcentem

8. Dobry design jest dopracowany w każdym detalu Nic nie może być przypadkowe. Stany ładowania, puste stany, stany błędów — wszystko zaprojektowane.

9. Dobry design jest przyjazny dla środowiska Wydajność to kwestia ekologiczna. Szanuj uwagę użytkownika. Efektywny kod.

10. Dobry design to jak najmniej designu Usuń wszystko, co zbędne. Najlepszy design jest niewidoczny.


Wzorce webowe 2026

Współczesny web design wykorzystuje natywne możliwości CSS, które w wielu przypadkach eliminują potrzebę stosowania JavaScript. Lata 2025–2026 wprowadziły anchor positioning, animacje sterowane przewijaniem i @starting-style do produkcyjnych przeglądarek.

Container queries

Wymiarowanie komponentów na podstawie ich kontenera, a nie viewportu.

.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()

Selekcja rodzica na podstawie dzieci — wcześniej niemożliwa 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);
}

Natywne zagnieżdżanie 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;
  }
}

Integracja z HTMX

Interaktywność sterowana serwerem bez ciężkich 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>

Anchor positioning

Natywne pozycjonowanie CSS jednego elementu względem drugiego — bez JavaScript. Tooltipy, popovery i menu rozwijane, które podążają za swoimi elementami wyzwalającymi.

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

Powiązanie postępu animacji z pozycją przewijania. Wskaźniki postępu czytania, efekty paralaksy i sekwencje ujawniania 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

Definiowanie stylów początkowych dla elementów wchodzących do DOM — umożliwia animacje wejścia wyłącznie w 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 design tokens

Kompletny system tokenów 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;
}

Dark mode — jak zrobić to dobrze

Nie wystarczy odwrócić kolory — trzeba zaprojektować interfejs z myślą o ciemnym kontekście.

@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 dark mode: - Zmniejsz nasycenie kolorów na dużych powierzchniach - Zwiększ jasność kolorów akcentujących - Wzmocnij cienie (wymagają większego kontrastu) - Projektuj dark mode świadomie, nie jako dodatek na końcu


Przepływy ekstrakcji z Figma

Przekształcenie plików projektowych w kod produkcyjny wymaga systematycznej ekstrakcji 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 najczystszą ścieżkę ekstrakcji:

Kroki eksportu: 1. Otwórz plik w Figma → panel Local Variables 2. Kliknij menu kolekcji → „Export to JSON” 3. Zapisz 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

Właściwości niestandardowe 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 dark mode:

@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 Color:

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 projektantowi

Co projektanci powinni wyeksportować:

Typ zasobu Format Uwagi
Kolory Variables JSON Uwzględnij tryb jasny i ciemny
Typografia Eksport stylów Krój, rozmiar, grubość, line-height
Odstępy Variables JSON Udokumentowana jednostka bazowa
Ikony SVG Obrysowe, jednokolorowe
Obrazy PNG @2x/@3x lub WebP Ze kompresją
Komponenty Linki do Figma Do referencji podczas implementacji

Kryteria bramy jakości:

  • [ ] Wszystkie kolory zdefiniowane jako zmienne (bez zakodowanych na stałe wartości hex)
  • [ ] Typografia korzysta ze zdefiniowanych stylów tekstu
  • [ ] Odstępy zgodne z systemem siatki (baza 8px)
  • [ ] Dostarczone warianty dark mode
  • [ ] Udokumentowane stany interaktywne (hover, active, disabled)
  • [ ] Oznaczone responsywne breakpointy
  • [ ] Odnotowane wymagania dostępności (współczynniki kontrastu)

Deweloper otrzymuje:

  1. Pliki tokenów (JSON/CSS/Swift w zależności od platformy)
  2. Specyfikacje komponentów z wymiarami
  3. Wyeksportowane zasoby w wymaganych formatach
  4. Dokumentację interakcji (stany, animacje)
  5. Adnotacje dotyczące dostępności

Tabele szybkiego odniesienia

Zasady Gestalt

Zasada Reguła Zastosowanie
Bliskość Powiązane = blisko Formularze, sekcje
Podobieństwo Ten sam wygląd = ta sama funkcja Przyciski, karty
Figura-tło Wyraźne rozdzielenie warstw Modale, karty
Ciągłość Podążaj za liniami Osie czasu, wyrównanie
Domknięcie Mózg dopełnia kształty Ikony, wskazówki przewijania

Typografia

Element Rozmiar Grubość Line height
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 Dark mode
Tło #ffffff #0f172a
Powierzchnia #f4f5f7 #1e293b
Obramowanie #e4e6ea #334155
Tekst #1a1a2e #f1f5f9
Tekst wyciszony #6b7280 #94a3b8
Kolor główny #3b82f6 #60a5fa
Sukces #22c55e #4ade80
Błąd #ef4444 #f87171

Skala odstępów

Token Wartość Zastosowanie
–space-1 4px Odstępy ikon
–space-2 8px Elementy inline
–space-4 16px Domyślne odstępy
–space-6 24px Padding kart
–space-8 32px Odstępy sekcji
–space-16 64px Sekcje strony

Lista kontrolna projektu

Przed wdrożeniem dowolnego interfejsu należy zweryfikować:

Gestalt

  • [ ] Powiązane elementy są bliżej siebie niż niepowiązane (Bliskość)
  • [ ] Podobne funkcje mają podobne style (Podobieństwo)
  • [ ] Wyraźne rozdzielenie pierwszego planu i tła (Figura-tło)
  • [ ] Wzrok naturalnie podąża przez układ (Ciągłość)

Typografia

  • [ ] Bazowy rozmiar czcionki wynosi co najmniej 16px
  • [ ] Line height dla tekstu głównego wynosi 1,5+
  • [ ] Długość wiersza nie przekracza 75 znaków
  • [ ] Hierarchia jest czytelna (3 rozróżnialne poziomy)
  • [ ] Spójna skala w całym projekcie

Kolor

  • [ ] Cały tekst spełnia kontrast 4,5:1 (WCAG AA)
  • [ ] Kolor nie jest jedynym wskaźnikiem (dodatkowe ikony/etykiety)
  • [ ] Dark mode zaprojektowany świadomie
  • [ ] Zachowana proporcja 60-30-10

Hierarchia wizualna

  • [ ] Można wskazać najważniejszy element (#1)
  • [ ] Wzrok podąża w zamierzonej kolejności
  • [ ] Jedno wyraźne CTA na sekcję
  • [ ] Spójna skala typograficzna

Odstępy

  • [ ] Wszystkie odstępy korzystają ze zdefiniowanej skali (bez magicznych liczb)
  • [ ] Karty/komponenty mają spójny padding
  • [ ] Odstępy na urządzeniach mobilnych są komfortowe
  • [ ] Spójne wyrównanie do siatki (baza 8px)

Interakcja

  • [ ] Czy użytkownicy mogą osiągnąć cele bez zastanawiania się nad narzędziem?
  • [ ] Czy UI dostosowuje się do bieżącego kontekstu?
  • [ ] Czy narzędzia są widoczne tylko wtedy, gdy są potrzebne?
  • [ ] Czy wielokrotne użycie uczy szybszych metod?

Interfejsy AI

  • [ ] Każde twierdzenie faktyczne ma identyfikowalne źródło
  • [ ] Streaming pokazuje fazy procesu, nie tylko wskaźnik ładowania
  • [ ] Stany błędów są przejrzyste, nie ukryte
  • [ ] Wyniki o niskim poziomie pewności są wizualnie wyróżnione

Test Dietera Ramsa

  • [ ] Czy można coś usunąć?
  • [ ] Czy każdy element pełni funkcję?
  • [ ] Czy za 5 lat będzie wyglądać przestarzale?
  • [ ] Czy zaprojektowano każdy stan?

Zasoby

Książki: - As Little Design as Possible — Sophie Lovell (Dieter Rams) - The Elements of Typographic Style — Robert Bringhurst

Narzędzia: - WebAIM Contrast Checker - Type Scale Generator - Figma Tokens Studio — Zarządzanie design tokens

Systemy projektowe: - Apple HIG - Material Design 3 - Radix UI - shadcn/ui


Studia projektowe

Szczegółowe analizy 16 wyjątkowych produktów, dokumentujące wzorce i zasady warte zastosowania.

Narzędzia deweloperskie

Produkt Kluczowy wkład
Figma Obecność wieloosobowa, panele kontekstowe
Warp Terminal blokowy, most CLI-GUI
Framer Wizualne projektowanie responsywne, kontrolki właściwości
Vercel Wzorcowy dark mode, subtelne wskaźniki statusu
Linear Optimistic UI, przepływ pracy oparty na klawiaturze
Raycast System rozszerzeń, szybkie akcje

Aplikacje natywne iOS (laureaci Apple Design Award)

Produkt Kluczowy wkład
Flighty 15 inteligentnych stanów, Live Activities, wizualizacja danych
Halide Inteligentna aktywacja, sterowanie gestami
Bear Priorytet typografii, tagowanie inline
Craft Natywne podejście międzyplatformowe, zagnieżdżone strony
Things Odroczone terminy, wzorce szybkiego wprowadzania

Produktywność i AI

Produkt Kluczowy wkład
Superhuman Zasada 100 ms, nauka palety poleceń, wdrażanie przez praktykę
Perplexity AI z priorytetem cytowań, fazowe przesyłanie strumieniowe
Notion System bloków, polecenia slash
Arc Przestrzenie, widok dzielony, pasek poleceń
Stripe Wzorcowa dokumentacja, projektowanie API

Ten przewodnik rozwija się poprzez praktykę. Zasady projektowania są ponadczasowe, ale ich zastosowanie ewoluuje wraz z technologią i zrozumieniem.