Internet odwiedzającego zrywa się w trakcie ładowania Twojego formularza. Rozszerzenie Chrome psuje Twój JavaScript. Starsza przeglądarka nie obsługuje używanego przez Ciebie JavaScriptu. Czytnik ekranu nie potrafi poruszać się po formularzu, bo etykiety są ukryte przez CSS.
Formularze to ścieżki krytyczne. Użytkownicy muszą móc je wysłać. Formularz nie może po prostu się zepsuć. Stopniowe ulepszanie to zasada budowania formularzy działających wszędzie, a potem dodawania usprawnień dla przeglądarek, które je obsługują.
Ten artykuł pokazuje, jak budować formularze, które łagodnie się degradują, działają bez JavaScriptu i pozostają dostępne dla wszystkich.
Czym jest stopniowe ulepszanie?
Stopniowe ulepszanie oznacza zaczynanie od podstawowego, działającego formularza, który działa w najstarszych przeglądarkach i bez JavaScriptu, a potem dokładanie usprawnień dla nowoczesnych przeglądarek. Warstwa 1 (HTML) daje podstawowy formularz z polami, etykietami i przyciskiem wysyłania, który nie potrzebuje JavaScriptu i działa wszędzie. Warstwa 2 (CSS) stylizuje formularz kolorami, odstępami i układem, więc formularz nadal działa, jeśli CSS się nie załaduje, choć wygląda wtedy źle. Warstwa 3 (JavaScript) dodaje walidację w czasie rzeczywistym, płynne animacje i wysyłanie przez AJAX, więc formularz nadal działa, jeśli JavaScript zawiedzie, i po prostu wysyła się tradycyjnie. Jeśli którakolwiek warstwa zawiedzie, użytkownik nadal dostaje działający formularz. To właśnie odporność.
Podstawa: HTML, który działa
Zacznij od semantycznego HTML z właściwymi etykietami oraz elementami fieldset i legend. Podstawowy formularz wygląda tak: <form action="/submit" method="POST"> <label for="email">Email</label> <input type="email" id="email" name="email" required> <label for="message">Message</label> <textarea id="message" name="message" required></textarea> <button type="submit">Send</button> </form>. Ten formularz działa bez JavaScriptu, bez CSS, w starych przeglądarkach, z czytnikami ekranu i z nawigacją klawiaturą. To Twoja podstawa. Nigdy nie usuwaj elementów z DOM i nie zastępuj ich elementami renderowanymi przez JavaScript, bo jeśli JavaScript zawiedzie, formularz się zepsuje. Zachowaj semantyczny HTML.
Łagodna degradacja z CSS
Nakładaj usprawnienia CSS na HTML. Ładnie ostyluj formularz. Ale jeśli CSS zawiedzie, formularz nadal działa.
Nie ukrywaj etykiet przez CSS, polegając na placeholderach, bo czasem CSS się nie ładuje, a czytniki ekranu potrzebują etykiet w HTML. Nie używaj CSS do ukrywania oznaczeń pól wymaganych, bo jeśli Twoja własna "gwiazdka wymagalności" się nie załaduje, użytkownicy nie rozpoznają, które pola są wymagane. Użyj zamiast tego atrybutu HTML required. Unikaj wizualnego ukrywania etykiety i pokazywania placeholdera za pomocą label { display: none; } i input::placeholder { content: 'Email'; }. Zamiast tego zostaw etykietę w HTML i stylizuj ją dowolnie za pomocą label { font-weight: bold; color: #333; }.
Usprawnienia JavaScript, które degradują się łagodnie
Dodawaj usprawnienia JavaScript, ale tylko jeśli formularz już działa. Użyj wykrywania funkcji, by sprawdzić, czy przeglądarka obsługuje to, czego potrzebujesz: if (window._blocked_) { // Use _blocked_ for AJAX submission } else { // Form submits traditionally }. Nie zakładaj, że funkcje istnieją. Załóż, że mogą nie istnieć. Najpierw wykryj.
Walidacja w czasie rzeczywistym z rozwiązaniem zapasowym
Użyj walidacji HTML jako podstawy za pomocą <input type="email" required>, by przeglądarka walidowała przy wysyłaniu. Potem dodaj walidację JavaScript działającą w czasie rzeczywistym: input.addEventListener('blur', () => { if (!isValid(input.value)) { input.classList.add('invalid'); showError(input, 'Invalid email'); } });. Pokazuje błędy w trakcie pisania, a jeśli JavaScript zawiedzie, wbudowana walidacja przeglądarki nadal działa. Użytkownik dostaje korzyść z informacji zwrotnej w czasie rzeczywistym, a jeśli JavaScript zawiedzie, dostaje informację od przeglądarki przy wysyłaniu. Tak czy inaczej walidacja się odbywa.
Wysyłanie AJAX z tradycyjnym rozwiązaniem zapasowym
Zbuduj tradycyjny formularz wysyłany po stronie serwera, a potem przechwyć wysłanie i użyj zamiast tego AJAX: form.addEventListener('submit', async (e) => { e.preventDefault(); const response = await _blocked_('/submit', { method: 'POST', body: new FormData(form) }); if (response.ok) { showMessage('Success'); } });. Jeśli JavaScript zawiedzie, preventDefault nigdy się nie wykona, formularz zostanie wysłany tradycyjnie, a użytkownik dostanie przeładowanie strony zamiast płynnego UX. Ale formularz zadziała.
Dostępność jako stopniowe ulepszanie
Dostępność to nie dodatkowa funkcja. To podstawa. Buduj dostępne formularze.
Etykiety muszą być powiązane z polami za pomocą atrybutów for i id. Nie atrybutów data, nie etykiet aria, które można przeoczyć. Właściwe etykiety.
<label for="email">Email</label>
<input id="email">
Używaj semantycznych elementów HTML (fieldset, legend, button, input). Nie divów ostylowanych na przyciski.
Nawigacja klawiaturą musi działać. Tab przechodzi przez wszystkie pola. Shift+Tab wraca. Enter wysyła. Spacja przełącza pola wyboru. To działa domyślnie przy semantycznym HTML. Nie psuj tego JavaScriptem.
Gdy podstawy działają, dodaj etykiety ARIA dla czytników ekranu. Dodaj wskaźniki fokusu dla użytkowników klawiatury. Ale to usprawnienia nałożone na dostępny HTML.
Testowanie odporności
Przetestuj formularz z wyłączonym JavaScriptem. Wyłącz JavaScript w przeglądarce i spróbuj wysłać formularz. Jeśli formularz się psuje, nie jest odporny.
Przetestuj przy wolnych sieciach. Ogranicz połączenie do 2G. Jeśli formularz ładuje się w nieskończoność, odwiedzający ze słabym internetem wyjdą.
Przetestuj w starszych przeglądarkach. Użyj BrowserStack lub podobnego narzędzia, by przetestować w IE 11 (jeśli jeszcze potrzeba). Sprawdź, jakie funkcje nie są obsługiwane.
Przetestuj z czytnikami ekranu. Użyj NVDA (Windows) lub VoiceOver (Mac). Posłuchaj, jak formularz jest odczytywany. Jeśli nic nie ma sensu dla czytnika ekranu, popraw to.
Przetestuj tylko klawiaturą. Nie używaj myszy. Czy da się poruszać po formularzu? Czy da się go wysłać?
Wykrywanie funkcji, a nie przeglądarki
Nie sprawdzaj konkretnych przeglądarek. Sprawdzaj funkcje zamiast wykrywania przeglądarki, jak w if (navigator.userAgent.includes('Chrome')) { /* use _blocked_ */ }. Zamiast tego użyj wykrywania funkcji, jak w if (window._blocked_) { /* use _blocked_ */ }. Wykrywanie funkcji jest bardziej niezawodne, bo aktualizacja przeglądarki dodająca obsługę _blocked_ będzie działać z Twoim kodem, a wykrywanie przeglądarki nie.
Jak WEMASY buduje odporne formularze
Formularze WEMASY są zbudowane na zasadach stopniowego ulepszania: działają bez JavaScriptu, mają etykiety i semantyczny HTML na miejscu, mają opcjonalne usprawnienia JavaScript, więc starsze przeglądarki dostają działający formularz, a nowoczesne płynne interakcje.
Zobacz funkcje odporności w swoim planie WEMASY.