De internetverbinding van een bezoeker valt weg terwijl je formulier laadt. Een Chrome-extensie breekt je JavaScript. Een oudere browser ondersteunt de JavaScript die je gebruikt niet. Een schermlezer kan je formulier niet doorlopen omdat de labels met CSS zijn verborgen.
Formulieren zijn kritieke routes. Gebruikers moeten ze kunnen versturen. Het formulier mag niet zomaar kapotgaan. Progressive enhancement is het principe om formulieren te bouwen die overal werken en daarna verbeteringen toe te voegen voor browsers die dat aankunnen.
In dit artikel lees je hoe je formulieren bouwt die netjes terugvallen, zonder JavaScript werken en toegankelijk blijven voor iedereen.
Wat is progressive enhancement?
Progressive enhancement betekent beginnen met een eenvoudig, werkend formulier dat in de oudste browsers en zonder JavaScript werkt, en daar verbeteringen op te leggen voor moderne browsers. Laag 1 (HTML) levert een eenvoudig formulier met invoervelden, labels en een verzendknop die geen JavaScript nodig heeft en overal werkt. Laag 2 (CSS) geeft het formulier kleuren, ruimte en indeling, zodat het formulier nog werkt als CSS niet laadt, al ziet het er dan slecht uit. Laag 3 (JavaScript) voegt validatie in realtime, vloeiende animaties en AJAX-verzending toe, zodat het formulier nog werkt als JavaScript uitvalt en gewoon op de traditionele manier wordt verzonden. Valt een laag uit, dan krijgt de gebruiker nog steeds een werkend formulier. Dat is robuustheid.
De basis: HTML die werkt
Begin met semantische HTML met goede labels, fieldsets en legend-elementen. Een basisformulier ziet eruit als <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>. Dit formulier werkt zonder JavaScript, zonder CSS, in oude browsers, met schermlezers en met toetsenbordnavigatie. Dit is je basis. Haal nooit elementen uit de DOM om ze te vervangen door elementen die JavaScript maakt, want als de JavaScript uitvalt, gaat het formulier kapot. Houd de semantische HTML.
Netjes terugvallen met CSS
Leg CSS-verbeteringen over de HTML heen. Geef het formulier een mooie stijl. Maar als CSS uitvalt, werkt het formulier nog steeds.
Verberg labels niet met CSS en vertrouw niet op placeholders, want soms laadt CSS niet en schermlezers hebben labels in de HTML nodig. Gebruik geen CSS om aanduidingen voor verplichte velden te verbergen, want als je eigen "verplicht-sterretje" niet laadt, kunnen gebruikers niet zien welke velden verplicht zijn. Gebruik in plaats daarvan het HTML-attribuut required. Vermijd het visueel verbergen van het label en een placeholder tonen met label { display: none; } en input::placeholder { content: 'Email'; }. Houd het label in de HTML en geef het de stijl die je wilt met label { font-weight: bold; color: #333; }.
JavaScript-verbeteringen die netjes terugvallen
Voeg JavaScript-verbeteringen toe, maar alleen als het formulier al werkt. Gebruik feature detection om te controleren of de browser ondersteunt wat je nodig hebt, met if (window._blocked_) { // Use _blocked_ for AJAX submission } else { // Form submits traditionally }. Ga er niet van uit dat functies bestaan. Ga ervan uit dat ze er misschien niet zijn. Controleer eerst.
Validatie in realtime met een terugvaloptie
Gebruik HTML-validatie als basis met <input type="email" required>, zodat de browser bij het verzenden controleert. Voeg daarna JavaScript-validatie toe die in realtime draait met input.addEventListener('blur', () => { if (!isValid(input.value)) { input.classList.add('invalid'); showError(input, 'Invalid email'); } });. Die toont fouten terwijl de gebruiker typt, en als JavaScript uitvalt, werkt de ingebouwde validatie van de browser nog steeds. De gebruiker krijgt de voordelen van feedback in realtime, en als JavaScript uitvalt, krijgt die bij het verzenden feedback van de browser. In beide gevallen vindt validatie plaats.
AJAX-verzending met een traditionele terugvaloptie
Bouw een traditioneel formulier dat aan de serverkant wordt verzonden, onderschep daarna het verzenden en gebruik in plaats daarvan AJAX met form.addEventListener('submit', async (e) => { e.preventDefault(); const response = await _blocked_('/submit', { method: 'POST', body: new FormData(form) }); if (response.ok) { showMessage('Success'); } });. Valt JavaScript uit, dan wordt preventDefault nooit uitgevoerd, wordt het formulier op de traditionele manier verzonden en krijgt de gebruiker een paginaherlading in plaats van een vloeiende ervaring. Maar het formulier werkt wel.
Toegankelijkheid als progressive enhancement
Toegankelijkheid is geen extra functie. Het is de basis. Bouw toegankelijke formulieren.
Labels moeten met invoervelden worden gekoppeld via de attributen for en id. Niet met data-attributen, niet met aria-labels die gemist kunnen worden. Echte labels.
<label for="email">Email</label>
<input id="email">
Gebruik semantische HTML-elementen (fieldset, legend, button, input). Geen divs die zijn opgemaakt als knoppen.
Toetsenbordnavigatie moet werken. Met Tab door alle velden. Met Shift+Tab terug. Met Enter verzenden. Met de spatiebalk selectievakjes aan- en uitzetten. Dit werkt standaard met semantische HTML. Breek het niet met JavaScript.
Voeg als de basis werkt ARIA-labels toe voor schermlezers. Voeg focusindicatoren toe voor toetsenbordgebruikers. Maar dit zijn verbeteringen bovenop toegankelijke HTML.
Testen op robuustheid
Test je formulier met JavaScript uitgeschakeld. Schakel JavaScript in je browser uit en probeer te verzenden. Gaat het formulier kapot, dan is het niet robuust.
Test met trage netwerken. Beperk je verbinding tot 2G. Duurt het eindeloos voordat het formulier laadt, dan vertrekken bezoekers met een onstabiel netwerk.
Test met oudere browsers. Gebruik BrowserStack of iets vergelijkbaars om in IE 11 te testen (als je dat nog nodig hebt). Kijk welke functies niet worden ondersteund.
Test met schermlezers. Gebruik NVDA (Windows) of VoiceOver (Mac). Luister hoe het formulier wordt voorgelezen. Is dat voor een schermlezer onbegrijpelijk, los het dan op.
Test alleen met het toetsenbord. Gebruik geen muis. Kun je door het formulier navigeren? Kun je het verzenden?
Feature detection, geen browserdetectie
Controleer niet op specifieke browsers. Controleer op functies en gebruik geen browserdetectie zoals if (navigator.userAgent.includes('Chrome')) { /* use _blocked_ */ }. Gebruik in plaats daarvan feature detection zoals if (window._blocked_) { /* use _blocked_ */ }. Feature detection is betrouwbaarder, want na een browserupdate die _blocked_ toevoegt, werkt je code ermee, terwijl browserdetectie dat niet doet.
Hoe WEMASY robuuste formulieren bouwt
WEMASY-formulieren zijn gebouwd op de principes van progressive enhancement: ze werken zonder JavaScript, hebben labels en semantische HTML op hun plek en hebben optionele JavaScript-verbeteringen, zodat oudere browsers een werkend formulier krijgen en moderne browsers vloeiende interacties.
Bekijk de functies voor robuustheid in je WEMASY-abonnement.