Capítulo 12
Formulários
5 min de leitura 886 palavras 2 gravuras
Este capítulo marca campos que a pessoa preenche. O Contato da Oficina Costeira, coletivo fictício de design em João Pessoa, demonstra validação do navegador. Nada é enviado a um servidor. O exemplo correspondente é 12-formularios, no pacote que acompanha o volume.
Este volume tem 52 capítulos. Ciclo: ler → copiar → mudar uma coisa → prever → recarregar → conferir.
O que você vai aprender
- Ligar
labeleid. - Cancelar o envio e testar apenas a validação local.
- Escolher
typeadequado (text,email,url). - Marcar
requiredsem inventar cadastro. - Agrupar rádio e caixa com
fieldsetelegend. - Distinguir envio de estudo e publicação com dados reais (esta última não existe aqui).
O form não grava ficha neste volume
form agrupa controles. action seria a URL que recebe os dados. method seria get ou post.
Neste volume não há processamento no servidor. O formulário é uma demonstração local. Por isso:
<form action="#" method="get" onsubmit="return false" autocomplete="off">
action indica o destino de um envio. O valor # sozinho não impede envio: em HTTP, um formulário GET pode colocar campos na URL e pedir a página ao servidor. Aqui, onsubmit="return false" é um pequeno apoio pronto que cancela esse envio depois da validação. Copie esse atributo também. Não há banco nem e-mail de verdade. Use apenas valores fictícios.
Erro comum: apontar action para um serviço desconhecido “só para ver”. O exercício não envia.
label aponta para id
Todo campo visível tem rótulo. O for do label copia o id do controle. Clicar no texto foca o campo. O leitor de tela anuncia o nome.
<label for="nome">Nome</label>
<input id="nome" name="nome" type="text" autocomplete="name">
name é o que viajaria no envio. Mesmo nesta demonstração, mantenha name para reconhecer a estrutura. Placeholder não substitui label. Placeholder some quando a pessoa digita.
Mude só o texto do label de “Nome” para “Nome completo”. Preveja o rótulo visível. Recarregue. Confira. O id continua nome.
Tipos de input
type="text" é o padrão. Outros tipos mudam teclado no celular e validação:
email— exige formato com@url— exige URLtel— teclado numérico; não valida telefone brasileiro sozinhonumber— número;min,max,stepdate/time— seletor nativopassword— mascara; não use para senha real neste volumesearch— campo de buscafile— arquivo; não envie
<label for="email">E-mail</label>
<input id="email" name="email" type="email" autocomplete="email" required>
O e-mail da Oficina Costeira de estudo pode ser nara@oficina.example. Domínio .example não entrega correio. Serve para testar o formato.
required, textarea, select
required impede o envio vazio. O navegador mostra aviso nativo. A referência pronta também mostra um retorno local, sem enviar campos.
<label for="mensagem">Mensagem</label>
<textarea id="mensagem" name="mensagem" rows="4" required></textarea>
<label for="assunto">Assunto</label>
<select id="assunto" name="assunto">
<option value="oficina">Oficina</option>
<option value="projeto">Projeto</option>
</select>
<button type="submit">Simular envio</button>
button type="submit" inicia a validação. O apoio pronto cancela o envio quando os campos são válidos. Texto do botão descreve a ação. Evite só “OK”.
Abra o exemplo. Deixe o e-mail vazio e acione o botão. Preveja o aviso do navegador. Não há carta saindo da máquina.

fieldset, rádio e caixa
Rádios do mesmo grupo compartilham name. Só um fica marcado. Caixas (checkbox) são independentes.
<fieldset>
<legend>Formato de resposta (demonstração)</legend>
<p>
<input type="radio" id="formato-email" name="formato" value="email" checked>
<label for="formato-email">E-mail fictício</label>
</p>
<p>
<input type="radio" id="formato-nenhum" name="formato" value="nenhum">
<label for="formato-nenhum">Sem resposta</label>
</p>
</fieldset>
<fieldset>
<legend>Interesses (demonstração)</legend>
<p>
<input type="checkbox" id="interesse-cartaz" name="interesse" value="cartaz">
<label for="interesse-cartaz">Cartaz</label>
</p>
</fieldset>
legend nomeia o grupo. Sem fieldset, os rádios são um monte de botões soltos para o leitor de tela.
optgroup agrupa option em select longo. Na Oficina, dois assuntos bastam.
Página Contato completa
Skip-link, lang="pt-BR", menu com aria-current="page" em Contato, main id="conteudo", o form, rodapé avisando que nada é enviado.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Contato — Oficina Costeira</title>
</head>
<body>
<a class="skip" href="#conteudo">Pular para o conteúdo</a>
<header>
<p><a href="index.html">Oficina Costeira</a></p>
<nav aria-label="Principal">
<ul>
<li><a href="index.html">Início</a></li>
<li><a href="contato.html" aria-current="page">Contato</a></li>
</ul>
</nav>
</header>
<main id="conteudo" tabindex="-1">
<h1>Contato</h1>
<p>Este formulário não envia nada. É só marcação e validação do navegador.</p>
<form action="#" method="get" onsubmit="return false" autocomplete="off">
<p>
<label for="nome">Nome</label>
<input id="nome" name="nome" type="text" required>
</p>
<p>
<label for="email">E-mail</label>
<input id="email" name="email" type="email" required>
</p>
<p>
<button type="submit">Simular envio</button>
</p>
</form>
</main>
</body>
</html>
Arquivo no disco: a marcação. Página no navegador: avisos nativos. Teste em 127.0.0.1: o envio é cancelado e os campos não entram na URL. Publicação pública com ficha real não faz parte deste volume.

Erro comum: label sem for, ou for="email" com id="e-mail". O clique no texto não foca. O leitor lê “edição” sem nome.
O que não fazer
Não peça CPF, cartão, senha de banco. Não ligue serviço de e-mail de terceiros no exercício. O exemplo completo usa autocomplete="off" para reduzir o preenchimento automático de dados reais. Os atributos autocomplete="name" e autocomplete="email" acima mostram os nomes usados em formulários reais; digite apenas valores fictícios aqui.
pattern com expressão regular fica para depois, se precisar. required e type="email" já ensinam validação.
Atividades
- Por que precisamos cancelar o envio, além de usar
action="#"? - O que quebra se
foreidnão forem iguais? - Qual a diferença entre rádios com o mesmo
namee caixas com o mesmoname? - No exemplo, envie o form vazio e depois com e-mail sem
@. O que o navegador fez em cada caso?
Respostas comentadas
- Porque
#sozinho não cancela envio. O apoio pronto cancela o envio após a validação, para estudar marcação sem mandar campos a um servidor. A Oficina Costeira de estudo não tem backend. PHP está em outro curso. - O rótulo deixa de associar. Clique no texto não foca. Tecnologia assistiva anuncia campo sem nome.
- Rádios com o mesmo
namesão uma escolha. Caixas com o mesmonamepodem marcar várias; o envio real agruparia valores. Aqui o envio é simulado. - Vazio com
required: aviso de campo obrigatório. Sem@emtype="email": aviso de formato. A página não “cadastra” ninguém.
Referências
O arquivo completo
Referência do exemplo 12-formularios, reproduzida aqui para que você possa conferir sem sair da página.
assets/javascript/simulacao.js
const form=document.querySelector("#simulacao");if(form){form.querySelector("button[type=submit]").disabled=false;form.addEventListener("submit",event=>{event.preventDefault();document.querySelector("#retorno").textContent="Simulação concluída. Nada foi enviado ou guardado.";});}