Lekcja 19
Formularze: inputy, labelki, błędy i stany walidacji
Formularze są miejscem, w którym użytkownik przekazuje dane aplikacji. Dobry CSS nie tylko „upiększa” pola, ale pomaga rozumieć, co wpisać, gdzie jest fokus, co jest wymagane i jak naprawić błąd.
Cele lekcji
Po ukończeniu tej lekcji będziesz umieć:
- budować semantyczne pola formularza z powiązanymi labelkami,
- stylować inputy bez utraty dostępności,
- projektować czytelny stan
:focus-visible, - odróżniać tekst pomocniczy od komunikatu błędu,
- stosować
aria-describedbyiaria-invalid, - rozumieć różnicę między
disabledireadonly.
Kontekst praktyczny
Formularze pojawiają się w logowaniu, rejestracji, checkoutach, filtrach, wyszukiwarkach, ustawieniach konta i panelach administracyjnych. Są mało widowiskowe, ale bardzo wrażliwe na błędy UX: słaby label, niewidoczny fokus albo komunikat błędu bez kontekstu potrafią zatrzymać użytkownika.
HTML przed CSS
Zanim napiszesz style, upewnij się, że pole ma właściwy typ, labelkę i atrybuty pomagające przeglądarce. CSS nie naprawi formularza, który od początku jest zbudowany z anonimowych pól bez opisu.
<label for="email">Adres e-mail</label>
<input id="email" name="email" type="email" autocomplete="email" required>
type, autocomplete i required poprawiają klawiatury mobilne, autouzupełnianie i natywną walidację. To część jakości formularza, nie dodatek.
Labelki i opisy
Label powinien być widoczny i jednoznaczny. Placeholder może podpowiadać format, ale nie powinien zastępować labelki, bo znika po wpisaniu tekstu i bywa słabszy kontrastowo.
<div class="field">
<label class="field__label" for="password">Hasło</label>
<input
class="field__control"
id="password"
name="password"
type="password"
aria-describedby="password-hint"
>
<p class="field__hint" id="password-hint">
Minimum 8 znaków, w tym jedna cyfra.
</p>
</div>
for w labelce musi wskazywać na id pola. Dzięki temu kliknięcie labelki ustawia fokus w polu.Bazowy styl pola
Kontrolka formularza powinna mieć pełną szerokość kontenera, wystarczający rozmiar dotykowy, czytelne obramowanie i odziedziczoną typografię.
.field__control {
width: 100%;
min-height: 2.85rem;
padding: .75rem .9rem;
border: 1px solid #cbd5e1;
border-radius: .75rem;
background: #fff;
color: #0f172a;
font: inherit;
}
font: inherit jest ważne także w formularzach, bo inputy, selecty i buttony mogą mieć domyślne style niezależne od reszty strony.
Focus i czytelność
Stan fokusu powinien być widoczny bez zgadywania. W formularzu użytkownik często przechodzi klawiaturą przez wiele pól, więc fokus musi jasno pokazywać aktualne miejsce pracy.
.field__control:focus-visible {
border-color: #2563eb;
outline: 3px solid #bfdbfe;
outline-offset: 2px;
}
Dobry fokus nie polega wyłącznie na zmianie koloru ramki. Dodatkowy outline jest odporniejszy na różne tła i błędy kontrastu.
Stany walidacji
Stan błędu powinien wskazać pole, pokazać komunikat i wyjaśnić, co poprawić. Sam czerwony border to za mało, bo część użytkowników nie rozróżnia kolorów albo korzysta z czytnika ekranu.
<input
class="field__control field__control--invalid"
id="email"
type="email"
aria-invalid="true"
aria-describedby="email-error"
>
<p class="field__error" id="email-error">
Wpisz adres w formacie nazwa@domena.pl.
</p>
aria-invalid="true"informuje technologię asystującą, że pole ma błąd.aria-describedbyłączy pole z komunikatem błędu albo tekstem pomocniczym.- Komunikat powinien mówić, jak naprawić problem, nie tylko że „pole jest błędne”.
Disabled i readonly
disabled oznacza, że pola nie można edytować ani wysłać z formularzem. readonly pozwala odczytać i zaznaczyć wartość, ale blokuje edycję. Wizualnie oba stany powinny być spokojniejsze niż zwykłe pole, ale nie mogą wyglądać jak błąd.
.field__control:disabled {
background: #e2e8f0;
color: #64748b;
cursor: not-allowed;
}
.field__control[readonly] {
background: #f8fafc;
}
Jeżeli pole jest niedostępne, pokaż powód w tekście pomocniczym. Użytkownik nie powinien zgadywać, co odblokuje edycję.
Demo formularza
Demo pokazuje pełne pole z hintem, stan błędu, stan poprawny oraz pole niedostępne. Zwróć uwagę, że każdy komunikat jest widoczny tekstowo, a nie tylko przez kolor ramki.
Najczęstsze błędy początkujących
- Ukrywanie labelki i poleganie wyłącznie na placeholderze.
- Usuwanie fokusu z pól formularza bez widocznej alternatywy.
- Pokazywanie błędu tylko kolorem ramki, bez komunikatu tekstowego.
- Brak powiązania komunikatu błędu z polem przez
aria-describedby. - Nadużywanie
disabled, gdy wystarczy wyjaśnić, co użytkownik ma zrobić. - Zbyt małe pola i przyciski na ekranach dotykowych.
Mini zadanie
Zbuduj prosty formularz zapisu do newslettera.
- Dodaj pole e-mail z widoczną labelką.
- Dodaj tekst pomocniczy pod polem.
- Przygotuj wariant błędu z
aria-invalidi komunikatem tekstowym. - Dodaj stan
:focus-visibledla inputa i przycisku. - Sprawdź, czy formularz da się przejść klawiaturą i czy nie ma poziomego overflow na 390px.
Checklista
- Każde pole ma widoczną labelkę powiązaną przez
foriid. - Placeholder nie zastępuje labelki.
- Inputy mają
font: inherit, pełną szerokość i wygodny rozmiar dotykowy. - Fokus jest wyraźny i widoczny na jasnym tle.
- Błędy mają komunikat tekstowy, nie tylko czerwony kolor.
- Rozumiem różnicę między
disabledireadonly.
Podsumowanie lekcji
Dostępny formularz zaczyna się od dobrego HTML: właściwego typu pola, widocznej labelki i opisów. CSS powinien wzmacniać semantykę przez czytelny fokus, jasne komunikaty błędów, spokojne stany niedostępne i stabilny układ na małych ekranach.
Kolejny krok roadmapy to karty, listy i sekcje treści.
Przejdź do Lekcji 20