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

Formulários e entradas

docs.scrimba.com

Quase todo site que faz algo por você, uma caixa de busca, um login, um checkout, um campo de comentário, é construído em um formulário. Um formulário é como uma página deixa de falar para o visitante e começa a escutar: coleta o que alguém digita, marca ou seleciona, e entrega esses dados para serem processados. Este capítulo é sobre o 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 suas entradas 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 como um formulário de papel que você preenche no consultório do médico. A folha contém todas as caixas, você escreve em cada uma e, no final, devolve a folha inteira de uma vez. O elemento <form> é essa folha.

Um <form> é o contêiner que coleta seus controles e os envia como um pacote único. Dois atributos decidem o que acontece ao enviar: action é o endereço para o qual os dados são enviados e method é como 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 aciona um envio, o navegador coleta todo controle nomeado dentro do formulário, empacota os valores e envia uma solicitação para o endereço action. Você não precisa conectar nada disso você mesmo. O elemento <form> oferece esse comportamento gratuitamente, razão pela qual agrupar controles em um formulário real é melhor do que espalhar entradas soltas pela página.

Um <form> é um mecanismo nativo de envio: o comportamento integrado do navegador que reúne os controles do formulário em uma solicitação e a envia, sem nenhum script necessário. Ao enviar, o navegador lê o action (a URL para a qual a solicitação vai) e method (get ou post, coberto mais adiante neste capítulo), serializa os controles na solicitação e navega. Esse padrão é a razão pela qual um formulário ainda funciona com JavaScript desabilitado ou ainda não carregado, que é a linha de base a partir da qual você constrói em vez da coisa 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 pegam as pessoas desprevenidas. Primeiro, um formulário envia ao pressionar Enter quando o foco está em um campo de texto de uma única linha, não apenas ao clicar em um botão, então o envio por teclado é integrado e vale a pena testar. Segundo, o envio padrão recarrega ou navega a página; quando você manipula um formulário com JavaScript, você chama event.preventDefault() para parar essa navegação e tomar conta. Trate o envio nativo como a base: ele deve fazer algo sensato mesmo antes de qualquer script rodar. Melhoramento progressivo, colocando script em cima de HTML funcionando, é a razão para começar aqui.

JunoO elemento form Um <form> é o contêiner que mantém suas entradas e um botão, e envia tudo junto quando alguém envia. Imagine o formulário de papel em uma mesa: uma folha, muitas caixas, devolvidas todas de uma vez. Envolva seus campos em um formulário e você consegue 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ê consegue reunir e enviar gratuitamente, então escolha um formulário real em vez de entradas soltas mais seu próprio manipulador de clique. Economiza código e funciona antes de qualquer script carregar.
JunoO elemento form O envio nativo reúne os controles e envia uma solicitação para action sem envolvimento de script, que é exatamente por que um formulário ainda funciona quando JavaScript está desligado. Lembre-se que envia ao pressionar Enter em um campo de texto, não apenas em um clique. Quando você realmente tomar conta com JavaScript, event.preventDefault() interrompe a navegação padrão, e o formulário simples embaixo fica como sua rede de segurança.

Entradas e rótulos

Um <input> é a caixa em que um visitante digita. Por si só, porém, uma entrada é uma caixa vazia sem nenhuma pista do que é. É para isso que serve um rótulo: é a parte de texto que diz ao visitante o que colocar na caixa.

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

Toda entrada precisa de um rótulo. Você conecta os dois dando à entrada um id e apontando o rótulo para ela com for, usando a mesma palavra em ambos. Uma vez que estão vinculados, clicar no rótulo coloca o cursor na caixa, que é uma pequena gentileza que torna o formulário mais fácil de usar para todos.

Um <input> coleta um único valor; um <label> o nomeia. Você os associa combinando o atributo for do rótulo com o id da entrada:

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

Alguns atributos merecem seu lugar na maioria das entradas. name é a chave sob a qual o valor é enviado (coberto na seção de nomenclatura). required bloqueia o envio até que o campo seja preenchido. placeholder mostra texto de dica fraca dentro da caixa, mas um placeholder não é um rótulo: desaparece no momento em que alguém digita, então não pode substituir a coisa real. Toda entrada ainda precisa de seu próprio <label>.

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

html
<!-- explicit: for matches id -->
<label for="phone">Telefone</label>
<input id="phone" name="phone" type="tel">

<!-- implicit: the input sits inside the label -->
<label>
  Telefone
  <input name="phone" type="tel">
</label>

Ambos dão ao controle um nome acessível, o texto que um leitor de tela anuncia quando o campo ganha foco, então um visitante que não consegue ver o layout ainda sabe o que digitar. Prefira associação explícita: sobrevive a layouts CSS que movem o rótulo longe da entrada, e funciona quando o estilo força os dois a se separarem. Um campo sem rótulo associado é anunciado como uma caixa de edição vazia sem propósito, que é uma das falhas de acessibilidade mais comuns na web. O capítulo sobre acessibilidade vai mais longe nisto.

JunoEntradas e rótulos O <input> é a caixa em que as pessoas digitam, e o <label> é o texto dizendo a elas o que vai lá. Vincule-os com for e id correspondentes e clicar no rótulo pula direto para a caixa. Dê a cada entrada um rótulo; uma caixa solitária sem palavras ao lado confunde apenas as pessoas.
JunoEntradas e rótulos Combine o for do rótulo com o id da entrada e os dois estão vinculados. Confie em required para bloquear envios vazios, mas não deixe um placeholder fazer as vezes de rótulo: desaparece no segundo em que alguém digita. Rótulo real, todo campo, sem exceções.
JunoEntradas e rótulos Duas maneiras de vincular um rótulo: for combinando com id, ou envolver a entrada dentro do rótulo. Ambas dão ao campo um nome acessível, o texto que um leitor de tela lê em voz alta, e explícito for/id é a escolha mais robusta quando CSS puxa as coisas para longe. Um campo sem rótulo é lido como uma caixa sem nome, que é uma das falhas de acessibilidade mais comuns por aí.

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 seleção (uma checkbox) é uma chave ligado-ou-desligado, e um dropdown deixa alguém escolher uma opção de várias.

html
<label>
  <input type="checkbox"> Envie-me o boletim informativo
</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 isso. O ponto por enquanto é que um formulário pode fazer suas perguntas da maneira que for adequada: digite-a, marque-a ou escolha-a de uma lista.

O elemento <input> muda de forma baseado em seu atributo type, e o tipo certo oferece um teclado melhor, validação integrada e um seletor nativo gratuitamente:

html
<input type="email">     <!-- valida a forma @, teclado de e-mail no celular -->
<input type="number">    <!-- teclado numérico, incrementadores para cima/baixo -->
<input type="password">  <!-- mascara os caracteres -->
<input type="date">      <!-- seletor de data nativo -->
<input type="checkbox">  <!-- uma única chave ligado/desligado -->
<input type="radio">     <!-- escolha um de um grupo -->

Além de <input>, três elementos cobrem o resto. <textarea> é uma caixa de texto multilinha para escrita mais longa. <select> com filhos <option> é uma lista suspensa. E quando você precisa de campos relacionados agrupados visual e semanticamente, envolva-os em um <fieldset> com uma <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"> Expresso</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 formulário), type="reset" limpa cada campo de volta ao seu valor inicial, e type="button" não faz nada por si só e está lá para JavaScript se conectar.

Cada tipo de controle carrega comportamento que vale a pena saber antes de você enviá-lo. Botões de rádio são agrupados por um name compartilhado: apenas um rádio em um grupo pode ser selecionado por vez, e esse agrupamento é o 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"> Expresso</label>
</fieldset>

Um <fieldset> e <legend> não são apenas visuais. O <legend> é anunciado por leitores de tela como contexto para cada controle no conjunto, então um rádio dentro do fieldset "Velocidade de entrega" é lido como "Velocidade de entrega, Padrão", que é a diferença entre um formulário compreensível e uma lista de opções desconectadas. Mais duas notas de produção. Uma checkbox envia seu valor apenas quando está marcada; uma caixa desmarcada está completamente ausente do envio, então o servidor não vê nada em vez de um falso, o que molda como você lê os dados do outro lado. E type="submit" é o tipo padrão para um <button> dentro de um formulário, então um <button> vazio que você pretendia como um gatilho JavaScript enviará o formulário e recarregará a página a menos que você configure type="button". Esse padrão pega as pessoas constantemente.

JunoOutros controles Um formulário pode fazer perguntas de mais de uma maneira: uma caixa de seleção para sim-ou-não, um dropdown para escolher uma coisa de uma lista. Uma checkbox é <input type="checkbox">, e um dropdown é um <select> contendo escolhas <option>. Sem necessidade de memorizá-los; o formulário tem mais do que caixas simples quando uma pergunta precisa.
JunoOutros controles O type da entrada o remodela: email, number, date, password, checkbox, radio, cada um com um teclado ou seletor apropriado. Escolha <textarea> para texto longo, <select> para um dropdown, e um <fieldset> com uma <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 agrupam por um name compartilhado, e uma <legend> dá a cada controle no fieldset contexto falado, então é estrutura, não decoração. Duas armadilhas: uma checkbox desmarcada não envia nada em absoluto, nem um falso, e um <button> vazio padrão é type="submit", então recarregará a página a menos que você configure type="button".

Como dados de formulário são nomeados e enviados

Quando um formulário é enviado, cada resposta precisa de um rótulo para que quem a receba saiba de qual caixa veio. Esse rótulo é o name da entrada. Você o define uma vez e ele viaja com o valor.

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

Se o visitante digitar "São Paulo" nessa caixa, o formulário envia o par "city é São Paulo". O name é como o lado receptor diferencia uma resposta da outra. Uma entrada sem name é deixada de fora do envio inteiramente, então esse pequeno atributo é o que realmente faz os dados 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 inseriu se torna o valor. Apenas controles com um name são incluídos, então um name é o que transforma um controle em dados enviados.

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 recente</option>
    <option value="top">Melhor avaliado</option>
  </select>
  <button type="submit">Buscar</button>
</form>

O atributo method escolhe como esses pares viajam. method="get" os anexa à URL como uma string de consulta (/search?q=boots&sort=recent), o que é adequado para buscas e filtros que você pode marcar ou compartilhar. method="post" os coloca no corpo da solicitação fora do alcance, o que é adequado para qualquer coisa que altere dados ou não deva estar em uma URL, como uma senha ou um pagamento.

Cada envio é 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 string de consulta, o texto ?key=value&key=value após o endereço. Isso torna a solicitação repetível e marcável, e significa que os valores estão visíveis na URL, no histórico do navegador e nos logs do servidor, então get é para leituras (buscas, filtros) e nunca para segredos. post carrega os pares no corpo da solicitação em vez disso, fora da URL, que é a escolha para qualquer coisa que mude 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 string key=value&..., que é bom para texto. Para enviar um arquivo escolhido, você deve mudar para enctype="multipart/form-data", o formato que pode carregar bytes de arquivo junto com campos de texto; uma entrada de arquivo não fará upload corretamente sem ele.

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 é autocomplete, e é onde a nomenclatura retorna em UX e acessibilidade. Um token autocomplete diz ao navegador o que um campo significa em termos padrão, para que possa oferecer o valor salvo certo: 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, que importa mais para pessoas digitando em um telefone ou usando tecnologia assistiva.

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

Manter as verificações integradas corretas é um trabalho separado, coberto no capítulo sobre validação de formulário; esta seção é sobre como os dados são moldados e enviados uma vez que são válidos.

JunoComo dados de formulário são nomeados e enviados O name de cada entrada é a etiqueta em sua resposta, para que o receptor saiba que um valor veio da caixa de cidade e não da de e-mail. Configure name e o valor da caixa é enviado como um par rotulado. Esqueça, e esse campo é silenciosamente deixado de fora, o que confunde muitas pessoas a primeira vez que um formulário não envia nada.
JunoComo dados de formulário são nomeados e enviados Os dados enviados são pares nome/valor, e apenas controles com um name são incluídos. Escolha o method para combinar com o trabalho: get coloca valores na URL para buscas e filtros que você pode marcar, post os esconde no corpo para qualquer coisa que altere dados ou guarde um segredo. Senhas em uma URL é o erro a nunca cometer.
JunoComo dados de formulário são nomeados e enviadosget escreve os pares na URL, então é para leituras e nunca para segredos; post os carrega no corpo. Mude enctype para multipart/form-data ou uma entrada de arquivo não fará upload. E gaste o esforço em tokens autocomplete como email e current-password: eles são um vocabulário fixo, e acertá-los permite que um telefone ou gerenciador de senhas preencha o formulário em um toque.