Skip to content
This page has been auto-translated and may contain errors.View in English

Formulários e inputs ​

docs.scrimba.com

Praticamente todo site que faz algo por você, uma caixa de busca, um login, uma finalização de compra, um campo de comentário, é construído a partir de um formulário. Um formulário é o que faz a página parar de só falar com o visitante e começar a ouvi-lo: ele coleta o que a pessoa digita, marca ou seleciona, e passa esses dados para serem processados. Este capítulo trata do HTML que torna isso possível.

O elemento form ​

Um formulário é um contêiner que agrupa as coisas que um visitante preenche. Você envolve seus inputs e um botão dentro de um elemento <form>, e o trabalho do formulário é reunir tudo e enviar quando o visitante terminar.

html
<form>
  <label>Seu nome</label>
  <input>
  <button>Enviar</button>
</form>

Pense nisso como um formulário de papel que você preenche no consultório médico. A folha contém todas as caixinhas, você escreve em cada uma, e no final você devolve a folha inteira de uma vez. O elemento <form> é essa folha.

Um <form> é o contêiner que reúne seus controles e os envia como um único pacote. Dois atributos decidem o que acontece no envio: action é o endereço para onde os dados são enviados, e method é como eles são enviados.

html
<form action="/subscribe" method="post">
  <label for="email">Endereço de e-mail</label>
  <input id="email" name="email" type="email">
  <button type="submit">Inscrever-se</button>
</form>

Quando o visitante dispara o envio, o navegador coleta todo controle nomeado dentro do formulário, empacota os valores e envia uma requisição para o endereço em action. Você não precisa programar nada disso. O elemento <form> te dá esse comportamento de graça, e é justamente por isso que agrupar controles em um formulário real é melhor do que espalhar inputs soltos pela página.

Um <form> é um mecanismo nativo de envio: o comportamento embutido do navegador que reúne os controles do formulário em uma requisição e a envia, sem precisar de nenhum script. No envio, o navegador lê o action (a URL para onde a requisição vai) e o method (get ou post, tratados mais adiante neste capítulo), serializa os controles na requisição e navega até o destino. É esse comportamento padrão que faz um formulário continuar funcionando com o JavaScript desativado ou ainda não carregado, e é essa a base sobre a qual você constrói, não algo que você substitui.

html
<form action="/subscribe" method="post">
  <label for="email">Endereço de e-mail</label>
  <input id="email" name="email" type="email">
  <button type="submit">Inscrever-se</button>
</form>

Dois comportamentos costumam pegar as pessoas desprevenidas. Primeiro, um formulário é enviado ao apertar Enter quando o foco está em um campo de texto de uma linha, não só ao clicar em um botão, então o envio pelo teclado já vem embutido e vale a pena testar. Segundo, o envio padrão recarrega ou navega a página; quando você trata um formulário com JavaScript, chama event.preventDefault() para impedir essa navegação e assumir o controle. Trate o envio nativo como o mínimo garantido: ele deve fazer algo sensato mesmo antes de qualquer script rodar. O aprimoramento progressivo, que consiste em adicionar script sobre um HTML que já funciona, é o motivo para começar por aqui.

JunoO elemento form Um <form> é o contêiner que guarda seus inputs e um botão, e ele envia tudo junto quando alguém faz a submissão. Pense no formulário de papel de um balcão: uma folha só, várias caixinhas, devolvida de uma vez. Envolva seus campos em um form e você ganha esse comportamento de reunir-e-enviar sem fazer nada complicado.
JunoO elemento form O <form> agrupa seus controles e os envia; action diz para onde, method diz como. Você ganha a coleta e o envio de graça, então prefira um formulário real em vez de inputs soltos mais o seu próprio manipulador de clique. Isso economiza código e funciona antes de qualquer script carregar.
JunoO elemento form O envio nativo reúne os controles e manda uma requisição para action sem nenhum script envolvido, e é exatamente por isso que um formulário continua funcionando com JavaScript desativado. Lembre-se: ele é enviado ao apertar Enter em um campo de texto, não só ao clicar. Quando você assume o controle com JavaScript, event.preventDefault() impede a navegação padrão, e o formulário simples por baixo continua sendo sua rede de segurança.

Inputs e labels ​

Um <input> é a caixa em que o visitante digita. Sozinho, porém, um input é uma caixa vazia sem nenhuma pista do que ela representa. É para isso que serve um label: é o texto que diz ao visitante o que colocar na caixa.

html
<label for="city">Cidade</label>
<input id="city">

Todo input precisa de um label. Você conecta os dois dando ao input um id e apontando o label para ele com for, usando a mesma palavra nos dois lugares. Uma vez ligados, clicar no label coloca o cursor na caixa, o que é uma pequena gentileza que torna o formulário mais fácil de usar para todo mundo.

Um <input> coleta um único valor; um <label> dá nome a ele. Você os associa fazendo o atributo for do label coincidir com o id do input:

html
<label for="username">Nome de usuário</label>
<input id="username" name="username" type="text" required>

Alguns atributos merecem lugar na maioria dos inputs. name é a chave sob a qual o valor é enviado (tratado na seção sobre nomeação). required bloqueia o envio até o campo ser preenchido. placeholder mostra um texto de dica esmaecido dentro da caixa, mas um placeholder não é um label: ele desaparece no instante em que alguém começa a digitar, então não pode substituir o label de verdade. Todo input ainda precisa do seu próprio <label>.

Existem duas formas de associar um <label> ao seu controle, e a distinção importa para a acessibilidade. A primeira é a associação explícita: o label carrega um atributo for cujo valor é igual ao id do controle. A segunda é a associação implícita: você envolve o controle dentro do próprio elemento label, e nenhum for ou id é necessário.

html
<!-- explícita: for corresponde ao id -->
<label for="phone">Telefone</label>
<input id="phone" name="phone" type="tel">

<!-- implícita: o input fica dentro do label -->
<label>
  Telefone
  <input name="phone" type="tel">
</label>

Ambas dão ao controle um nome acessível, o texto que um leitor de tela anuncia quando o campo recebe foco, para que um visitante que não consiga ver o layout ainda saiba o que digitar. Prefira a associação explícita: ela resiste a layouts CSS que afastam o label do input, e funciona quando a estilização força os dois a se separarem. Um campo sem label associado é anunciado como uma caixa de edição vazia sem propósito, uma das falhas de acessibilidade mais comuns da web. O capítulo de acessibilidade aprofunda esse assunto.

JunoInputs e labels O <input> é a caixa onde as pessoas digitam, e o <label> é o texto que diz o que vai ali. Ligue os dois com for e id correspondentes, e clicar no label leva direto para a caixa. Dê um label para cada input; uma caixa solitária sem nenhuma palavra ao lado só confunde as pessoas.
JunoInputs e labels Faça o for do label coincidir com o id do input e os dois ficam ligados. Use o required para bloquear envios vazios, mas não deixe um placeholder fazer o papel de label: ele desaparece no segundo em que alguém digita. Label de verdade, em todo campo, sem exceção.
JunoInputs e labels Duas formas de ligar um label: for coincidindo com id, ou envolver o input dentro do label. As duas dão ao campo um nome acessível, o texto que um leitor de tela lê em voz alta, e o par explícito for/id é a escolha mais robusta quando o CSS separa as coisas. Um campo sem label é lido como uma caixa sem nome, uma das falhas de acessibilidade mais comuns que existem.

Outros controles ​

Nem tudo é uma caixa de texto simples. Algumas perguntas são melhor respondidas marcando, escolhendo ou selecionando de uma lista. Uma caixa de marcação (uma checkbox) é uma chave de ligado ou desligado, e um dropdown deixa alguém escolher uma opção entre várias.

html
<label>
  <input type="checkbox"> Quero receber a newsletter
</label>

<label for="size">Tamanho</label>
<select id="size">
  <option>Pequeno</option>
  <option>Médio</option>
  <option>Grande</option>
</select>

Você não precisa memorizar tudo isso. O ponto por enquanto é que um formulário pode fazer suas perguntas do jeito que combinar: digitando, marcando ou escolhendo de uma lista.

O elemento <input> muda de forma com base no seu atributo type, e o tipo certo te dá um teclado melhor, validação embutida e um seletor nativo de graça:

html
<input type="email">     <!-- valida o formato do @, teclado de e-mail no celular -->
<input type="number">    <!-- teclado numérico, setas para incrementar/decrementar -->
<input type="password">  <!-- mascara os caracteres -->
<input type="date">      <!-- seletor de data nativo -->
<input type="checkbox">  <!-- uma única alternância ligado/desligado -->
<input type="radio">     <!-- escolher uma opção dentro de um grupo -->

Além do <input>, três elementos cobrem o resto. <textarea> é uma caixa de texto de múltiplas linhas para escritas mais longas. <select> com filhos <option> é uma lista dropdown. E quando você precisa agrupar campos relacionados visualmente e semanticamente, envolva-os em um <fieldset> com um <legend> que nomeie o grupo:

html
<fieldset>
  <legend>Velocidade de entrega</legend>
  <label><input type="radio" name="speed" value="standard"> Padrão</label>
  <label><input type="radio" name="speed" value="express"> Expressa</label>
</fieldset>

<label for="message">Mensagem</label>
<textarea id="message" name="message" rows="4"></textarea>

Botões também têm um type. type="submit" envia o formulário (o padrão para um botão dentro de um form), type="reset" limpa todos os campos de volta ao valor inicial, e type="button" não faz nada por conta própria e existe para o JavaScript se conectar a ele.

Cada tipo de controle carrega um comportamento que vale conhecer antes de colocar no ar. Botões de rádio são agrupados por um name compartilhado: só um rádio de um grupo pode estar selecionado por vez, e é esse agrupamento que os torna mutuamente exclusivos, então um name ausente ou incompatível quebra silenciosamente o grupo em alternâncias independentes.

html
<fieldset>
  <legend>Velocidade de entrega</legend>
  <label><input type="radio" name="speed" value="standard" checked> Padrão</label>
  <label><input type="radio" name="speed" value="express"> Expressa</label>
</fieldset>

Um <fieldset> e um <legend> não são apenas visuais. O <legend> é anunciado por leitores de tela como contexto para todo controle do conjunto, então um rádio dentro do fieldset "Velocidade de entrega" é lido como "Velocidade de entrega, Padrão", o que faz a diferença entre um formulário compreensível e uma lista de opções soltas. Mais duas observações para produção. Uma checkbox só envia seu valor quando está marcada; uma caixa desmarcada fica totalmente ausente da submissão, então o servidor não recebe nada em vez de receber um valor falso, o que muda a forma como você lê os dados do outro lado. E type="submit" é o tipo padrão de um <button> dentro de um formulário, então um <button> simples que você pretendia usar como gatilho de JavaScript vai enviar o formulário e recarregar a página, a menos que você defina type="button". Esse padrão pega as pessoas o tempo todo.

JunoOutros controles Um formulário pode perguntar de mais de um jeito: uma caixa de marcação para sim-ou-não, um dropdown para escolher uma coisa entre várias em uma lista. Uma checkbox é <input type="checkbox">, e um dropdown é um <select> contendo opções <option>. Não precisa memorizar tudo; o formulário tem mais do que caixas simples quando a pergunta pede isso.
JunoOutros controles O type do input muda sua forma: email, number, date, password, checkbox, radio, cada um com um teclado ou seletor adequado. Use <textarea> para texto longo, <select> para um dropdown, e um <fieldset> com <legend> para agrupar campos relacionados. Fique atento aos tipos de botão: submit é o padrão dentro de um formulário.
JunoOutros controles Rádios se agrupam por um name compartilhado, e um <legend> dá a todo controle do fieldset um contexto falado, então é estrutura, não decoração. Duas armadilhas: uma checkbox desmarcada não envia nada, e não um valor falso, e um <button> simples assume type="submit" por padrão, então vai recarregar a página a menos que você defina type="button".

Como os dados do formulário são nomeados e enviados ​

Quando um formulário é enviado, cada resposta precisa de um rótulo para que quem a recebe saiba de qual caixa ela veio. Esse rótulo é o name do input. Você o define uma vez, e ele acompanha o valor.

html
<label for="city">Cidade</label>
<input id="city" name="city">

Se o visitante digitar "Lisboa" nessa caixa, o formulário envia o par "city é Lisboa". O name é como o lado que recebe distingue uma resposta de outra. Um input sem name fica totalmente de fora da submissão, então esse pequeno atributo é o que realmente faz o dado aparecer.

Os dados do formulário são enviados como um conjunto de pares nome/valor: o name de cada controle se torna a chave e o que o visitante digitou se torna o valor. Só os controles com um name são incluídos, então é o name que transforma um controle em dado enviado.

html
<form action="/search" method="get">
  <label for="q">Buscar</label>
  <input id="q" name="q" type="search">
  <label for="sort">Ordenar por</label>
  <select id="sort" name="sort">
    <option value="recent">Mais recentes</option>
    <option value="top">Mais avaliados</option>
  </select>
  <button type="submit">Buscar</button>
</form>

O atributo method escolhe como esses pares viajam. method="get" os anexa à URL como uma query string (/search?q=botas&sort=recent), o que serve bem para buscas e filtros que você possa querer salvar ou compartilhar. method="post" coloca-os no corpo da requisição, fora de vista, o que serve para qualquer coisa que altere dados ou não deva aparecer em uma URL, como uma senha ou um pagamento.

Toda submissão é um conjunto de pares nome/valor, e três detalhes decidem como eles são codificados e enviados.

O method é o primeiro. get serializa os pares na URL como uma query string, o texto ?chave=valor&chave=valor depois do endereço. Isso torna a requisição repetível e passível de ser salva como favorito, e significa que os valores ficam visíveis na URL, no histórico do navegador e nos logs do servidor, então get serve para leituras (buscas, filtros) e nunca para segredos. post carrega os pares no corpo da requisição, fora da URL, o que é a escolha certa para qualquer coisa que altere o estado ou seja sensível.

O enctype é o segundo: a codificação que diz como o corpo é formatado. O padrão, application/x-www-form-urlencoded, empacota os pares em uma única string chave=valor&..., o que serve bem para texto. Para enviar um arquivo escolhido, você precisa mudar para enctype="multipart/form-data", o formato que consegue carregar bytes de arquivo junto com campos de texto; um input de arquivo não vai fazer upload corretamente sem isso.

html
<form action="/upload" method="post" enctype="multipart/form-data">
  <label for="avatar">Foto de perfil</label>
  <input id="avatar" name="avatar" type="file">
  <button type="submit">Enviar</button>
</form>

O terceiro é o autocomplete, e é onde a nomeação certa se paga em experiência de uso e acessibilidade. Um token de autocomplete diz ao navegador o que um campo significa em termos padronizados, para que ele possa oferecer o valor salvo correto: autocomplete="email", autocomplete="name", autocomplete="current-password", autocomplete="street-address". Esses tokens são um vocabulário fixo, não texto livre, e acertá-los permite que um navegador ou gerenciador de senhas preencha um formulário em um toque, o que importa mais ainda para quem digita no celular ou usa tecnologia assistiva.

html
<label for="email">E-mail</label>
<input id="email" name="email" type="email" autocomplete="email">

Manter as verificações embutidas confiáveis é uma tarefa separada, tratada no capítulo de validação de formulário; esta seção é sobre como o dado é formatado e enviado depois de já estar válido.

JunoComo os dados do formulário são nomeados e enviados O name de cada input é a etiqueta da sua resposta, para que quem recebe saiba que um valor veio da caixa de cidade e não da de e-mail. Defina o name, e o valor da caixa é enviado como um par rotulado. Esqueça isso, e o campo fica silenciosamente fora, o que confunde muita gente na primeira vez que um formulário não devolve nada.
JunoComo os dados do formulário são nomeados e enviados O dado enviado são pares nome/valor, e só os controles com um name entram. Escolha o method de acordo com a tarefa: get coloca os valores na URL para buscas e filtros que você talvez queira salvar, post os esconde no corpo para qualquer coisa que altere dados ou guarde um segredo. Senha na URL é o erro que você nunca deve cometer.
JunoComo os dados do formulário são nomeados e enviadosget escreve os pares na URL, então serve para leituras e nunca para segredos; post os carrega no corpo. Mude o enctype para multipart/form-data ou um input de arquivo não vai fazer upload. E vale a pena investir nos tokens de autocomplete, como email e current-password: eles são um vocabulário fixo, e acertá-los permite que um celular ou gerenciador de senhas preencha o formulário em um toque.