Criação de formulários incríveis com HTML5

HTML5 Rocks

Introdução

Nem todo mundo gosta de formulários, mas o HTML5 traz grandes melhorias, tanto para os desenvolvedores que criam formulários quanto para os usuários que os preenchem. Com os novos elementos, atributos e tipos de entrada de formulário, a validação baseada no navegador, as técnicas de estilo CSS3 e o objeto FormData, ficou mais fácil e, espera-se, mais agradável criar formulários.

There is even more up to date forms guidance on our new Web Fundamentals site.

Suporte a navegadores

Até a data deste artigo, o suporte para todos os novos elementos, atributos e tipos de formulário e entrada varia muito entre os navegadores. Até mesmo entre os navegadores que suportam determinado recurso, o comportamento pode ser diferente de um navegador para outro. Contudo, o estado do suporte de formulários em HTML5 vem mudando rapidamente e está cada vez melhor. Até a data do artigo, estes gráficos (link em inglês) eram os mais atualizados que foi possível encontrar e apresentavam detalhes sobre o estado do suporte dos navegadores aos formulários em HTML5.

Visão geral do que mudou

Novos elementos

O HTML5 apresenta cinco novos elementos relacionados às entradas e aos formulários.

Elemento Finalidade Observações
progress (link em inglês) Representa o andamento da execução de uma tarefa. O elemento progress pode representar o andamento do upload de um arquivo.
meter (link em inglês) Representa uma medida escalar dentro de um intervalo conhecido. O elemento meter pode ser usado para representar algo como uma medida de temperatura ou peso.
datalist (link em inglês) Representa um conjunto de elementos option que podem ser usados em combinação com o novo atributo list para entrada de criação de menus suspensos. Quando a entrada com a lista de dados associada fica em destaque, um menu suspenso aparece e apresenta os valores de datalist.
keygen (link em inglês) Um controle para geração de um par de chaves. Quando o formulário é enviado, a chave privada fica armazenada no keystore, e a chave pública é enviada ao servidor.
output (link em inglês) Exibe os resultados de um cálculo. Um exemplo do uso do elemento output é a exibição da soma dos valores de dois elementos de entrada.

Novos tipos de entrada

O HTML5 apresenta 13 novos tipos de entrada. Quando visualizados em um navegador sem suporte, estes tipos de entrada são convertidos em entrada de texto.

Tipo de entrada Finalidade Observações
tel Usado para inserir um número de telefone. O tel não impõe nenhuma sintaxe particular, portanto, se quiser determinar um formato específico, use pattern ou setCustomValidity() para validação adicional.
search Solicita aos usuários que digitem o texto pelo qual desejam buscar. A diferença entre search e text é basicamente estilística. O uso de uma entrada do tipo search pode fazer com que o campo de entrada fique com o mesmo estilo dos campos de pesquisa da plataforma usada.
url Usado para inserir um URL único. A função do url é inserir um URL único e absoluto (link em inglês), que representa uma grande extensão de valores.
email Usado para inserir um único endereço de e-mail ou uma lista de endereços de e-mail. Se for especificado o atributo multiple, podem ser inseridos vários endereços de e-mail, separados por vírgulas.
datetime Usado para inserir data e hora com o fuso horário em UTC.
date Usado para inserir uma data sem fuso horário.
month Usado para inserir uma data com ano e mês, sem fuso horário.
week Para inserir uma data formada por um número de ano e um número de semana, mas sem fuso horário. Um exemplo deste formato é 2011-W05 para a quinta semana de 2011.
time Usado para inserir um valor de horário com hora, minuto, segundos e fração de segundos, mas sem fuso horário.
datetime-local Para inserir data e hora sem fuso horário.
number Para entrada numérica. Os valores válidos são números de ponto flutuantes (link em inglês).
range Para entrada numérica, mas ao contrário de number, o valor real não é importante. A implementação do controle de intervalo é um controle deslizante na maioria dos navegadores que têm suporte.
color Usado para escolher a cor em um controle de cores. O valor deve ser uma cor simples, válida e em minúscula (link em inglês) como #ffffff.

Novos atributos de entrada

O HTML5 também apresenta vários novos atributos para os elementos de formulário e entrada.

Atributo Finalidade Observações
autofocus Foca a entrada no elemento quando a página é carregada. autofocus pode ser aplicado para entrada, seleção, área de texto e botão.
placeholder Dá ao usuário a dica sobre qual tipo de dado inserir. O valor do placeholder aparece em texto claro até que o elemento seja destacado e o usuário insira alguns dados. Pode ser especificado na entrada e área de texto.
form Especifica um ou mais formulários aos quais o elemento de entrada pertence. Usando o atributo form, os elementos de entrada podem ser colocados em qualquer lugar da página, não apenas no elemento de formulário. Além disso, um único elemento de entrada também pode ser associado a mais de um formulário.
required Um atributo boleano que significa que o elemento é obrigatório. O atributo required é útil para realizar a validação baseada no navegador sem usar JavaScript personalizado.
autocomplete Especifica que um campo não deve ser preenchido automaticamente ou pré-preenchido pelo navegador de acordo com as entradas anteriores de um usuário. O atributo autocomplete serve para campos como número de cartão de crédito ou senha de autenticação, casos em que o preenchimento automático não é recomendável. Por padrão, autocomplete possui o estado on, portanto, se desejar desativá-lo, coloque-o em off.
pattern Usado para validar o valor de um elemento com relação a uma expressão regular. Ao usar um pattern, você deve especificar também um valor title para dar ao usuário uma descrição do padrão esperado.
dirname Usado para enviar a direcionalidade do controle com o formulário. Por exemplo, se o usuário inserir dados de texto com direcionalidade da direita para a esquerda e o elemento de entrada contiver o atributo dirname, então, uma indicação da direcionalidade da direita para a esquerda será enviada junto com o valor de entrada.
novalidate Usado para desativar a validação de envio de formulário quando especificado em um elemento de formulário.
formaction Usado para substituir o atributo action no elemento de formulário. Este atributo é suportado nos elementos input e button.
formenctype Usado para substituir o atributo enctype no elemento de formulário. Este atributo é suportado nos elementos input e button.
formmethod Usado para substituir o atributo method no elemento de formulário. Este atributo é suportado nos elementos input e button.
formnovalidate Usado para substituir o atributo novalidate no elemento de formulário. Este atributo é suportado nos elementos input e button.
formtarget Usado para substituir o atributo target no elemento de formulário. Este atributo é suportado nos elementos input e button.

Objeto FormData

Um dos aprimoramentos do XMLHttpRequest (link em inglês) é a introdução do objeto FormData (link em inglês). Com o objeto FormData, você pode criar e enviar um conjunto de pares de chave/valor e, opcionalmente, arquivos usando XMLHttpRequest. Quando essa técnica é usada, os dados são enviados no mesmo formato em que seriam enviados pelo método submit() do formulário com o tipo de codificação multipart/form-data.

FormData fornece uma maneira de criar formulários em HTML durante a execução usando JavaScript e, então, enviá-los usandoXMLHttpRequest.send(). Segue um exemplo simples:

var formData = new FormData();
formData.append("part_num", "123ABC"); 
formData.append("part_price", 7.95);
formData.append("part_image", somefile)

var xhr = new XMLHttpRequest();
xhr.open("POST", "http://some.url/");  
xhr.send(formData);

Você pode usar FormData para incluir dados adicionais em um formulário existente antes de enviá-lo.

var formElement = document.getElementById("someFormElement");
var formData = new FormData(formElement);
formData.append("part_description", "The best part ever!");

var xhr = new XMLHttpRequest();
xhr.open("POST", "http://some.url/");
xhr.send(formData);

Validação baseada em navegador

Sejamos honestos. Validar dados de formulário é uma tarefa bem chata, mas que precisa ser feita de qualquer maneira. Para realizar a validação de formulário do lado do cliente, é provável que você escreva algum código de JavaScript personalizado ou use uma biblioteca para executar tarefas como confirmar se as entradas são válidas ou garantir que os campos obrigatórios sejam preenchidos antes de enviar o formulário.

Com os novos atributos de entrada, como required e pattern, usados em combinação com seletores de pseudoclasse CSS, fica mais fácil criar as confirmações e exibir feedback para o usuário. Existem outras técnicas de validação avançada que permitem usar JavaScript para configurar regras e mensagens de validade personalizadas ou para determinar se um elemento é inválido e o motivo.

Atributo required

Se o atributo required estiver presente, o campo deve conter um valor quando o formulário for enviado. Segue um exemplo de um campo de entrada para endereço de e-mail obrigatório, que garante que o campo tenha um valor e que o valor seja um endereço de e-mail válido, como definido aqui (link em inglês).

<input type="email" id="email_addr" name="email_addr" required />

Atributo pattern

O atributo pattern especificou uma expressão regular usada para validar um campo de entrada. Esse exemplo representa um campo de entrada de texto obrigatório para um número de peça. Para efeito desse exemplo, digamos que um número de peça seja formado por três letras maiúsculas seguidas de quatro dígitos. O uso de required e pattern garante que o campo tenha um valor e que o valor corresponda ao formato correto para um número de peça. Se o usuário passar o mouse no campo, a mensagem no atributo title é exibida.

<input type="text" id="part" name="part" required pattern="[A-Z]{3}[0-9]{4}"
       title="Part numbers consist of 3 uppercase letters followed by 4 digits."/>

De acordo com o exemplo anterior, você pode contornar o campo de entrada em vermelho se um número de peça inválido for inserido. Para fazer isso, adicione este CSS para fazer com que o campo de entrada apareça com contorno vermelho se o valor for inválido.

:invalid {
  border: 2px solid #ff0000;
}

Atributo formnovalidate

O atributo formnovalidate pode ser aplicado aos elementos input ou button. Se estiver presente, a validação de envio do formulário é desativada. Este é um exemplo em que o envio de um formulário pelo botão Enviar exige uma entrada válida, mas o envio pelo botão Salvar não exige.

<input type="text" id="part" name="part" required pattern="[A-Z]{3}[0-9]{4}"
       title="Part numbers consist of 3 uppercase letters followed by 4 digits."/>
<input type="submit" formnovalidate value="Save">
<input type="submit" value="Submit">

API de validação de restrição

A API de validação de restrição (link em inglês) fornece ferramentas avançadas para trabalhar com validação personalizada. A API permite executar tarefas como configurar um erro personalizado, confirmar se um elemento é válido e determinar o motivo pelo qual o elemento é inválido. Este exemplo mostra um erro personalizado se os valores em dois campos não corresponderem.

<label>Email:</label>
<input type="email" id="email_addr" name="email_addr">

<label>Repeat Email Address:</label>
<input type="email" id="email_addr_repeat" name="email_addr_repeat" oninput="check(this)">

<script>
function check(input) {
  if (input.value != document.getElementById('email_addr').value) {
    input.setCustomValidity('The two email addresses must match.');
  } else {
    // input is valid -- reset the error message
    input.setCustomValidity('');
  }
}
</script>

Tudo junto

Este é um exemplo de formulário de solicitação de reserva que reúne vários tipos de entrada, validação de formulário e seletores de CSS e estilo.

$99.00

Este é o HTML e o JavaScript para o formulário:

<form oninput="total.value = (nights.valueAsNumber * 99) + 
 ((guests.valueAsNumber - 1) * 10)">

  <label>Full name:</label>
  <input type="text" id="full_name" name="full_name" placeholder="Jane Doe" required>

  <label>Email address:</label>
  <input type="email" id="email_addr" name="email_addr" required>

  <label>Repeat email address:</label>
  <input type="email" id="email_addr_repeat" name="email_addr_repeat" required 
   oninput="check(this)">

  <label>Arrival date:</label>
  <input type="date" id="arrival_dt" name="arrival_dt" required>
  
  <label>Number of nights (rooms are $99.00 per night):</label>
  <input type="number" id="nights" name="nights" value="1" min="1" max="30" required>

  <label>Number of guests (each additional guest adds $10.00 per night):</label>
  <input type="number" id="guests" name="guests" value="1" min="1" max="4" required>

  <label>Estimated total:</label>
  $<output id="total" name="total">99</output>.00
  <br><br>

  <label>Promo code:</label>
  <input type="text" id="promo" name="promo" pattern="[A-Za-z0-9]{6}" 
   title="Promo codes consist of 6 alphanumeric characters.">

  <input type="submit" value="Request Reservation" /> 
</form>

<script>
function check(input) {
  if (input.value != document.getElementById('email_addr').value) {
    input.setCustomValidity('The two email addresses must match.');
  } else {
    // input is valid -- reset the error message
    input.setCustomValidity('');
  }
}
</script>

Este é o CSS que acompanha o código de formulário:

:invalid { 
  border-color: #e88;
  -webkit-box-shadow: 0 0 5px rgba(255, 0, 0, .8);
  -moz-box-shadow: 0 0 5px rbba(255, 0, 0, .8);
  -o-box-shadow: 0 0 5px rbba(255, 0, 0, .8);
  -ms-box-shadow: 0 0 5px rbba(255, 0, 0, .8);
  box-shadow:0 0 5px rgba(255, 0, 0, .8);
}

:required {
  border-color: #88a;
  -webkit-box-shadow: 0 0 5px rgba(0, 0, 255, .5);
  -moz-box-shadow: 0 0 5px rgba(0, 0, 255, .5);
  -o-box-shadow: 0 0 5px rgba(0, 0, 255, .5);
  -ms-box-shadow: 0 0 5px rgba(0, 0, 255, .5);
  box-shadow: 0 0 5px rgba(0, 0, 255, .5);
}

form {
  width:300px;
  margin: 20px auto;
}

input {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  border:1px solid #ccc;
  font-size:20px;
  width:300px;
  min-height:30px;
  display:block;
  margin-bottom:15px;
  margin-top:5px;
  outline: none;

  -webkit-border-radius:5px;
  -moz-border-radius:5px;
  -o-border-radius:5px;
  -ms-border-radius:5px;
  border-radius:5px;
}

input[type=submit] {
  background:none;
  padding:10px;
}

Fontes

Comments

0