Melhoria progressiva de formulários: formulários resilientes

Aprende a melhoria progressiva de formulários. Cria formulários que funcionam sem JavaScript e melhora a experiência quando o JavaScript está disponível.

Rascunho

A internet de um visitante vai abaixo enquanto o teu formulário carrega. Uma extensão do Chrome estraga o teu JavaScript. Um navegador mais antigo não suporta o JavaScript que estás a usar. O leitor de ecrã da pessoa não consegue navegar no teu formulário porque as etiquetas estão escondidas com CSS.

Os formulários são caminhos críticos. Os utilizadores precisam de os enviar. O formulário não pode simplesmente avariar. A melhoria progressiva é o princípio de criar formulários que funcionam em todo o lado e só depois acrescentar melhorias para os navegadores que as suportam.

Este artigo explica como criar formulários que degradam com elegância, funcionam sem JavaScript e continuam acessíveis a todos.

O que é a melhoria progressiva?

Melhoria progressiva significa começar com um formulário básico e funcional, que funciona nos navegadores mais antigos e sem JavaScript, e depois juntar melhorias por cima para os navegadores modernos. A camada 1 (HTML) dá um formulário básico com campos, etiquetas e um botão de envio que não precisa de JavaScript e funciona em todo o lado. A camada 2 (CSS) dá estilo ao formulário com cores, espaçamento e layout, de modo que o formulário continua a funcionar se o CSS não carregar, só que fica feio. A camada 3 (JavaScript) acrescenta validação em tempo real, animações suaves e envio por AJAX, de modo que o formulário continua a funcionar se o JavaScript falhar e limita-se a enviar da forma tradicional. Se alguma camada falhar, o utilizador continua a ter um formulário que funciona. Isto é resiliência.

A base: HTML que funciona

Começa com HTML semântico, com etiquetas, fieldsets e elementos legend bem usados. Um formulário base é assim: <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>. Este formulário funciona sem JavaScript, sem CSS, em navegadores antigos, com leitores de ecrã e com navegação por teclado. Esta é a tua base. Nunca removas elementos do DOM para os substituir por elementos desenhados com JavaScript, porque se o JavaScript falhar, o formulário avaria. Mantém o HTML semântico.

Degradação elegante com CSS

Junta melhorias de CSS por cima do HTML. Dá ao formulário um bom estilo. Mas se o CSS falhar, o formulário continua a funcionar.

Não escondas etiquetas com CSS para depender de marcadores de posição, porque algum CSS não carrega e os leitores de ecrã precisam das etiquetas no HTML. Não uses CSS para esconder os indicadores de campo obrigatório, porque se a tua "estrela de obrigatório" personalizada não carregar, os utilizadores não percebem quais os campos obrigatórios. Usa antes o atributo required do HTML. Evita esconder a etiqueta visualmente e mostrar um marcador de posição em vez dela com label { display: none; } e input::placeholder { content: 'Email'; }. Em vez disso, mantém a etiqueta no HTML e dá-lhe o estilo que quiseres com label { font-weight: bold; color: #333; }.

Melhorias de JavaScript que degradam bem

Junta melhorias de JavaScript, mas só se o formulário já funcionar. Usa a deteção de funcionalidades para verificar se o navegador suporta o que precisas com if (window._blocked_) { // Use _blocked_ for AJAX submission } else { // Form submits traditionally }. Não assumas que as funcionalidades existem. Assume que podem não existir. Deteta primeiro.

Validação em tempo real com alternativa

Usa a validação do HTML como base com <input type="email" required>, para o navegador validar ao enviar. Depois junta validação em JavaScript que corre em tempo real com input.addEventListener('blur', () => { if (!isValid(input.value)) { input.classList.add('invalid'); showError(input, 'Invalid email'); } });. Mostra os erros enquanto o utilizador escreve e, se o JavaScript falhar, a validação integrada do navegador continua a funcionar. O utilizador tem o benefício do feedback em tempo real e, se o JavaScript falhar, recebe o feedback do navegador no momento do envio. Seja como for, há validação.

Envio por AJAX com alternativa tradicional

Cria um formulário tradicional que envia para o servidor e depois interceta o envio e usa AJAX com form.addEventListener('submit', async (e) => { e.preventDefault(); const response = await _blocked_('/submit', { method: 'POST', body: new FormData(form) }); if (response.ok) { showMessage('Success'); } });. Se o JavaScript falhar, o preventDefault nunca corre, o formulário envia da forma tradicional e o utilizador vê a página recarregar em vez de uma experiência suave. Mas o formulário funciona.

Acessibilidade como melhoria progressiva

A acessibilidade não é uma funcionalidade extra. É a base. Cria formulários acessíveis.

As etiquetas têm de estar ligadas aos campos com os atributos for e id. Não com atributos data, nem com aria-labels que se podem perder. Etiquetas a sério.

<label for="email">Email</label>

<input id="email">

Usa elementos HTML semânticos (fieldset, legend, button, input). Não divs com estilo para parecerem botões.

A navegação por teclado tem de funcionar. Tab para percorrer todos os campos. Shift+Tab para voltar atrás. Enter para enviar. Espaço para marcar caixas de seleção. Isto funciona por omissão com HTML semântico. Não o estragues com JavaScript.

Depois de a base funcionar, junta etiquetas ARIA para leitores de ecrã. Junta indicadores de foco para quem usa o teclado. Mas estas são melhorias por cima de um HTML acessível.

Testar a resiliência

Testa o teu formulário com o JavaScript desativado. Desativa o JavaScript no navegador e tenta enviar. Se o formulário avariar, não é resiliente.

Testa com redes lentas. Limita a ligação a 2G. Se o formulário demorar uma eternidade a carregar, os visitantes com internet instável vão-se embora.

Testa com navegadores mais antigos. Usa uma ferramenta de testes em vários navegadores para testar no IE 11 (se ainda for preciso). Vê que funcionalidades não são suportadas.

Testa com leitores de ecrã. Usa o NVDA (Windows) ou o VoiceOver (Mac). Ouve como o formulário é anunciado. Se não fizer sentido para um leitor de ecrã, corrige.

Testa só com o teclado. Não uses o rato. Consegues navegar no formulário? Consegues enviá-lo?

Deteção de funcionalidades, não de navegadores

Não verifiques navegadores específicos. Verifica funcionalidades, em vez de usares a deteção de navegador como if (navigator.userAgent.includes('Chrome')) { /* use _blocked_ */ }. Usa antes a deteção de funcionalidades como if (window._blocked_) { /* use _blocked_ */ }. A deteção de funcionalidades é mais fiável, porque uma atualização do navegador que acrescente suporte para _blocked_ vai funcionar com o teu código, mas a deteção de navegador não.

Como a WEMASY cria formulários resilientes

Os formulários da WEMASY são criados com princípios de melhoria progressiva: funcionam sem JavaScript, têm etiquetas e HTML semântico no sítio certo e têm melhorias de JavaScript opcionais, para que os navegadores mais antigos tenham um formulário que funciona e os navegadores modernos tenham interações suaves.

Vê as funcionalidades de resiliência no teu plano da WEMASY.

Perguntas frequentes

O meu formulário precisa mesmo de funcionar sem JavaScript?
Nos formulários críticos (contacto, checkout, registo), sim. Alguns utilizadores têm o JavaScript desativado ou avariado. Algum JavaScript falha em redes instáveis. Alguns navegadores mais antigos não suportam JavaScript moderno. Criar uma alternativa garante que todos conseguem usar o teu formulário. Com o criador de websites da WEMASY, podes configurar isto diretamente no teu website.
Como testo se o meu formulário funciona sem JavaScript?
Desativa o JavaScript no navegador. Chrome: Definições > Privacidade > Definições de conteúdo > JavaScript > Desativado. Firefox: about:config > javascript.enabled > false. Tenta enviar o formulário. Se falhar, o teu formulário não é resiliente.
O que é a deteção de funcionalidades e porque é melhor do que a deteção de navegador?
A deteção de funcionalidades verifica se uma funcionalidade específica existe (if window._blocked_) em vez de verificar o tipo de navegador. É mais fiável porque as atualizações dos navegadores acrescentam funcionalidades. A deteção de navegador deixa de funcionar com versões novas.
Devo esconder as etiquetas dos formulários e depender de marcadores de posição?
Não. Mantém sempre as etiquetas no HTML. Se o CSS não carregar, o marcador de posição desaparece. Os utilizadores e os leitores de ecrã precisam da etiqueta.
Como faço o envio por AJAX funcionar com uma alternativa tradicional?
Cria um formulário que envia para um URL de ação. Interceta o envio com JavaScript e usa _blocked_ para enviar por AJAX. Se o JavaScript falhar, o formulário envia da forma tradicional. Os dois caminhos funcionam.
O que devo testar para garantir que o meu formulário é resiliente?
Testa sem JavaScript. Testa em redes lentas. Testa com leitores de ecrã. Testa a navegação só com o teclado. Testa em navegadores mais antigos. Testa no telemóvel. Se tudo passar, o teu formulário é resiliente.

Põe isto em prática
no teu próprio site.

Começa grátis com a WEMASY e cria o teu site em poucos minutos.