SW Core
SW Core / CSS / Formulário que trava (sw-trava)

Formulário que trava (sw-trava) CSS

O botão "Enviar" fica apagado até a pessoa preencher tudo certo, e o campo errado só fica vermelho depois que ela mexeu nele. Sem JavaScript.

O que é

Coloque sw-trava na tag <form> e pronto: enquanto faltar um campo obrigatório ou tiver um e-mail mal digitado, o botão de enviar fica apagado e não aceita clique. Quando tudo estiver certo, ele acende. Os campos que a pessoa já preencheu ganham borda verde (certo) ou vermelha (errado) — mas só depois que ela mexeu, para não "gritar" com ninguém antes de começar.

É só CSS. O SW Core usa as regras que o próprio HTML já tem: required (obrigatório), type="email", minlength (mínimo de letras), pattern (formato) etc. O navegador sabe se cada campo está certo, e o CSS apaga o botão de envio enquanto houver algum errado. Funciona com os campos do SW Core (sw-fld / sw-inp) ou com campos comuns.

Quando usar

  • Formulário de contato ou de orçamento: evita a mensagem chegar sem e-mail ou telefone.
  • Cadastro e newsletter: o botão só libera com o e-mail certo e o "aceito os termos" marcado.
  • Agendamento: não deixa enviar sem data e horário.
  • Precisa de mensagem de erro escrita embaixo do campo ("Digite um e-mail válido")? Some com a Validação do SW Core — as duas funcionam juntas.

Comece aqui

  1. 1

    Coloque o SW Core no <head>. A trava é só CSS: não precisa do arquivo de JavaScript.

    <link rel="stylesheet" href="swcore/swcore.min.css">
  2. 2

    Ponha sw-trava no <form> e required nos campos obrigatórios. Digite um e-mail aqui e veja o botão acender:

    <form sw-trava action="/newsletter" method="post" class="flx f-wr alc gap-3">
      <input sw-inp type="email" name="email" required placeholder="seu@email.com" aria-label="E-mail">
      <button sw-btn="pri">Quero receber</button>
    </form>

Todas as variações

Cada quadro abaixo é o componente de verdade, rodando. O código embaixo é exatamente o que está no quadro: copie e cole.

1. As regras do HTML que ele respeita

Cada quadro é um formulário com sw-trava e uma regra diferente. O botão só acende quando a regra é cumprida. Clique fora do campo depois de digitar para ver a borda vermelha ou verde. (Os quadros não enviam nada.)

required — obrigatório <form sw-trava class="flx f-cl gap-2"> <input sw-inp required placeholder="Seu nome" aria-label="Nome"> <button sw-btn="pri p">Enviar</button> </form>
type="email" — tem que ser e-mail <form sw-trava class="flx f-cl gap-2"> <input sw-inp type="email" required placeholder="seu@email.com" aria-label="E-mail"> <button sw-btn="pri p">Enviar</button> </form>
minlength — mínimo de letras <form sw-trava class="flx f-cl gap-2"> <input sw-inp type="password" required minlength="8" placeholder="Senha (8+ letras)" aria-label="Senha"> <button sw-btn="pri p">Criar conta</button> </form>
pattern — formato (aqui: CEP com 8 números) <form sw-trava class="flx f-cl gap-2"> <input sw-inp required pattern="[0-9]{5}-?[0-9]{3}" inputmode="numeric" placeholder="00000-000" aria-label="CEP"> <button sw-btn="pri p">Calcular frete</button> </form>
checkbox required — tem que marcar <form sw-trava class="flx f-cl gap-2"> <label sw-chk><input type="checkbox" required> Aceito os termos</label> <button sw-btn="pri p">Continuar</button> </form>
select required — tem que escolher <form sw-trava class="flx f-cl gap-2"> <select sw-inp required aria-label="Horário"> <option value="">Escolha o horário</option> <option>09:00</option> <option>14:00</option> </select> <button sw-btn="pri p">Agendar</button> </form>

2. Botões que ele trava e que ele deixa em paz

A trava apaga o botão de enviar: todo <button> sem tipo (o padrão do HTML é enviar) e todo type="submit". Botão com type="button" continua clicável — use nele "Cancelar", "Limpar", ajuda etc.

Enviar trava; Cancelar (type="button") continua livre
<form sw-trava class="flx f-wr alc gap-3">
  <input sw-inp type="tel" required placeholder="(00) 00000-0000" aria-label="WhatsApp">
  <button type="button" sw-btn="ghost sec">Cancelar</button>
  <button type="submit" sw-btn="suc">Me chame no WhatsApp</button>
</form>

Tabela de opções

PalavraO que fazExemplo
No formulário
sw-travaLiga a trava do botão de enviar e as bordas verde/vermelha. Vai na tag <form>.<form sw-trava>
Regras do HTML (nos campos)
requiredCampo obrigatório. Em checkbox: tem que estar marcado. Em select: a primeira opção precisa ter value="".<input required>
type="email"Aceita só e-mail (tem que ter @ e domínio).<input type="email">
type="url"Aceita só endereço de site (começando com http:// ou https://).<input type="url">
minlength / maxlengthMínimo / máximo de letras.<input minlength="8">
min / maxMenor / maior número ou data aceita.<input type="number" min="1" max="10">
patternFormato exigido (expressão regular). Ex.: CEP, placa, telefone.pattern="[0-9]{5}-?[0-9]{3}"
Botões
<button> (sem type)É botão de enviar: fica apagado enquanto houver erro.<button sw-btn="pri">Enviar</button>
type="submit"Também fica apagado enquanto houver erro.<button type="submit">
type="button"Não é afetado: continua clicável.<button type="button">Cancelar</button>

Receitas prontas — usos reais

Situações que aparecem em quase todo site. Copie a que servir.

Formulário de contato completo Ao vivo
<form sw-trava action="/contato" method="post" class="flx f-cl gap-3">
  <div sw-fld="float">
    <input sw-inp id="nome" name="nome" required placeholder=" ">
    <label for="nome">Seu nome</label>
  </div>
  <div sw-fld="float">
    <input sw-inp id="email" name="email" type="email" required placeholder=" ">
    <label for="email">E-mail</label>
  </div>
  <div sw-fld="float">
    <textarea sw-inp id="msg" name="mensagem" required minlength="10" placeholder=" "></textarea>
    <label for="msg">Como podemos ajudar?</label>
  </div>
  <label sw-chk><input type="checkbox" name="aceite" required> Concordo em receber o retorno por e-mail</label>
  <button sw-btn="pri">Enviar mensagem</button>
</form>
Agendamento: data, horário e WhatsApp Ao vivo
<form sw-trava action="/agendar" method="post" class="flx f-cl gap-3">
  <div sw-fld>
    <label for="dia">Dia</label>
    <input sw-inp id="dia" name="dia" type="date" required>
  </div>
  <div sw-fld>
    <label for="hora">Horário</label>
    <select sw-inp id="hora" name="hora" required>
      <option value="">Escolha</option>
      <option>09:00</option>
      <option>10:30</option>
      <option>14:00</option>
    </select>
  </div>
  <div sw-fld>
    <label for="zap">WhatsApp</label>
    <input sw-inp id="zap" name="whatsapp" type="tel" required pattern="[0-9 ()-]{10,}" placeholder="(00) 00000-0000">
  </div>
  <button sw-btn="suc"><i class="swi-calendar-check"></i> Confirmar horário</button>
</form>
Newsletter no rodapé Ao vivo
<form sw-trava action="/newsletter" method="post" class="flx f-wr alc gap-2">
  <input sw-inp type="email" name="email" required placeholder="Seu melhor e-mail" aria-label="E-mail">
  <button sw-btn="pri"><i class="swi-envelope"></i> Assinar</button>
</form>

Precisa de quê

  • swcore.min.css — a trava.
  • swcore.compl.min.css — só se usar ícone swi-* no botão.

Cuidados — erros comuns

  • Sem nenhuma regra (required, type="email"…) nos campos, a trava não tem o que conferir: o botão fica sempre aceso.
  • Botão de ajuda, "mostrar senha" ou "Cancelar" dentro do form precisa de type="button" — senão a trava apaga ele também (e, sem o type, ele ainda enviaria o formulário).
  • Em <select required>, a primeira opção ("Escolha…") tem que ter value="", senão ela conta como escolhida.
  • A trava é conforto para quem preenche. Sempre confira os dados de novo no servidor: qualquer pessoa pode enviar dados sem passar pelo formulário.
  • O botão só fica apagado visualmente e sem clique; a tecla Enter dentro de um campo ainda pode tentar enviar — aí o próprio navegador barra e mostra o aviso dele.

O que ele não faz

  • Não escreve mensagem de erro embaixo do campo — só pinta a borda. Para mensagens, use a Validação (sw-valid).
  • Não confere regra que depende de outro campo (ex.: "repetir senha igual à senha") nem consulta o servidor (ex.: "e-mail já cadastrado").