Curso de CSS / Estados de formulário: foco, validação, disabled e readonly
O CSS pode estilizar foco, validade e controles de formulário desabilitados ou somente leitura, mas o HTML define seus rótulos, restrições e comportamento de envio. :invalid pode corresponder antes da interação, enquanto :user-invalid ajuda a atrasar a estilização de erro até que o navegador considere apropriado.
Associe rótulos e instruções aos controles
Se o atributo for de label e o ID da campo de entrada forem especificados como iguais, o nome do item e a campo de entrada estão conectados. Os espaços reservados desaparecem assim que você começa a digitar, então eles não ocupam o lugar de nomes ou condições importantes. Para explicações adicionais, deixe a frase visível e especifique o ID da frase em aria-describedby.
<label for="email">Email address (required)</label>
<input id="email" name="email" type="email" required
placeholder="name@example.com" aria-describedby="email-help">
<p id="email-help">Enter name@example.com in the same format.</p>
O código parcial acima representa brevemente a seção de e-mail do exemplo completo abaixo. id identifica o objeto no documento, e name é o nome do item nos dados enviados. Se name não estiver presente, ele não será incluído em envios normais, mesmo que você possa digitá-lo na tela. Para a composição de rótulos e descrições, consulte o guia de rótulo de formulário W3C e o guia de entrada de formulário W3C: instruções para formulários.
Dimensione os controles para telas estreitas e texto maior
Se você depender apenas da largura inerente da campo de entrada, ela poderá ultrapassar uma tela estreita quando o tamanho da fonte for aumentado. Defina a largura máxima do formulário e use width: 100% e box-sizing: border-box juntos na campo de entrada. Isso garantirá que a borda e o padding também sejam incluídos dentro da largura especificada.
*, *::before, *::after { box-sizing: border-box; }
form { max-width: 28rem; }
input { width: 100%; min-width: 0; padding: .65rem; font: inherit; }
Esta regra está incluída na seção de estilo de todo o exemplo. font: inherit permite que a campo de entrada e os botões sigam a fonte, o tamanho e a altura da linha do texto, e min-width ajuda a reduzir o tamanho mínimo que impede a redução mesmo ao inserir a campo de entrada em um Flexbox/Grid. Uma altura fixa não é usada para que os itens abaixo se movam para baixo naturalmente, mesmo quando a descrição é aumentada ou as letras são ampliadas.
Separe o estado de foco e os erros de validação
:focus corresponde ao elemento que atualmente tem foco, e :focus-visible corresponde se o navegador determinar que precisa exibir o foco. Ele é exibido principalmente durante a navegação pelo teclado, mas também pode ser exibido clicando com o mouse na campo de entrada de texto, então não deve ser entendido como “aplica-se apenas ao teclado.” a descrição de :focus-visible na MDN . Para aplicar a indicação de foco de forma consistente também aos links, compare Estados de links e foco visível do teclado.
O foco indica o item que você está manipulando atualmente, e erros indicam itens que não atenderam às condições de entrada. Como ambos os estados podem estar presentes ao mesmo tempo, o exemplo inteiro mostra o foco com um contorno azul e o erro com uma borda vermelho-escuro e uma mensagem de erro. Deixe algum espaço ao redor do contorno para evitar que ele seja cortado e evite remover o contorno sem fornecer outro indicador de foco.
:invalid corresponde se o valor atual for inválido, então um campo de entrada obrigatório vazio também é correspondido desde o início. :user-invalid corresponde quando o navegador exibirá uma condição de erro após a interação do usuário. Quando você exibe algo, como ao terminar de digitar ou ao tentar enviar, pode depender do comportamento do seu navegador. O laboratório verifica os erros pressionando o botão Enviar. a descrição de :user-invalid na MDN .
Se você precisar considerar alvos de suporte mais antigos, deve verificar se o seletor é suportado e projetar um fluxo de verificação separado. Mesmo que a decoração de erro não apareça porque o seletor não é suportado, isso não significa que as verificações obrigatórias e de formatação do HTML desapareçam. Escolha uma cor de foco suficientemente distinta do fundo real e também verifique as condições de aplicação do Guia de Contraste Não-Texto do W3C.
Compare required, validade, disabled e readonly
| situação | significado | Foco e envio geral |
|---|---|---|
required |
O usuário deve inserir um valor | Focável se for item ativo; Valores vazios estão sujeitos à validação no envio |
:valid·:invalid |
Se as condições de validação HTML foram atendidas | Os resultados da verificação são determinados independentemente da forma da borda |
disabled |
Atualmente indisponível | Normalmente excluído da navegação por tabulação e envios |
readonly |
Não é possível modificar valores como entrada de texto suportada | Focável e selecionável; Se o nome existir, inclua-o no envio |
readonly é suportado por controles específicos semelhantes a texto e não é uma maneira geral de tornar um elemento select somente leitura. Controles somente leitura suportados são excluídos da validação de restrição, enquanto controles nomeados ainda podem enviar dados de formulário. Diferencie esse comportamento de controles desabilitados. Veja HTML Standard: construindo a lista de entradas, MDN: readonly.
Este campo de e-mail demonstra um formato como name@example.com. Passar na verificação de validade não confirma que a conta existe ou pode receber e-mails. A validação HTML type="email" não aceita todos os formatos de endereços internacionalizados; partes locais não ASCII não são apresentadas aqui como entrada garantida válida. Para mais detalhes, veja as condições de type="email" no padrão HTML.
Execute o exemplo e inspecione os campos enviados
Salve o seguinte código como form-states.html em UTF-8 e abra-o no seu navegador. HTML e CSS determinam o estado do formulário. O pequeno trecho de JavaScript no final é um código auxiliar para interceptar envios válidos e exibir uma lista de dados na tela, sem enviá-los ao servidor ou realizar qualquer verificação adicional de entrada. Se o JavaScript estiver desativado, a função de saída do resultado não funcionará.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Comparing form states and submitted fields</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 1rem; color: #183044; font-family: sans-serif; line-height: 1.6; }
main { max-width: 46rem; margin-inline: auto; }
h1 { font-size: 1.5rem; } h2 { font-size: 1.2rem; }
button, input { font: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 3px solid #164f73; outline-offset: 3px; }
form { max-width: 28rem; }
.field { margin-block: 1.25rem; }
label { display: block; margin-bottom: .35rem; font-weight: 700; }
input { display: block; width: 100%; min-width: 0; padding: .65rem;
border: 2px solid #6d7e8b; border-radius: .3rem; background: white; color: #183044; }
input:required { border-inline-start-width: 4px; }
input:user-invalid { border-color: #9d2632; }
.help, .error { margin-block: .4rem 0; }
.error { display: none; color: #9d2632; }
input:user-invalid + .error { display: block; }
input[readonly] { background: #eef6fa; }
input:disabled { background: #eceff2; color: #465766; cursor: not-allowed; }
button { padding: .65rem 1rem; border: 1px solid #164f73; border-radius: .3rem;
background: #166b92; color: white; }
output { display: block; margin-block: 1rem; white-space: pre-wrap; overflow-wrap: anywhere; }
</style>
</head>
<body>
<main>
<h1>Check input states and submitted data</h1>
<form id="demo-form">
<div class="field">
<label for="email">Email address (required)</label>
<input id="email" name="email" type="email" autocomplete="email" required
placeholder="name@example.com" aria-describedby="email-help email-error">
<p id="email-error" class="error">Enter an email address in a format such as name@example.com; do not leave the field empty.</p>
<p id="email-help" class="help">This sample input checks the address format. It does not check whether the example address receives mail.</p>
</div>
<div class="field">
<label for="plan">Plan (read-only)</label>
<input id="plan" name="plan" type="text" value="Basic" readonly>
</div>
<div class="field">
<label for="coupon">Coupon (currently disabled)</label>
<input id="coupon" name="coupon" type="text" value="WELCOME" disabled>
</div>
<button type="submit">Check submitted fields</button>
</form>
<output id="result" for="email plan coupon" aria-live="polite"></output>
<script>
const form = document.getElementById("demo-form");
form.addEventListener("submit", (event) => {
event.preventDefault();
const entries = Array.from(new FormData(form).entries());
document.getElementById("result").textContent = JSON.stringify(entries, null, 2);
});
</script>
</main>
</body>
</html>
- Deixe o campo de e-mail em branco e pressione Check submitted fields (verificar campos enviados). Verifique seu navegador para instruções de entrada obrigatórias e mensagens de erro.
- Digite
abcno e-mail e envie novamente. Uma nova lista de resultados não deve ser exibida devido a um erro de formato. - Digite
name@example.come envie. A lista inclui email e plan com valor Basic; o campo coupon, desabilitado, não aparece. - Use Tab para percorrer o campo Email, o campo Plan e o botão de envio, nessa ordem. Cupons inativos são ignorados na ordem normal de tabulação, e planos somente leitura podem receber foco.
- No exemplo completo, remova apenas o atributo disabled do cupom. O campo passa a receber foco e coupon com valor WELCOME é incluído nos dados enviados. Depois restaure disabled.
- Remova apenas o atributo
readonlydo plano e tente editá-lo. Após a comparação, restaure seu valor para “Basic” e adicionereadonlynovamente. - Reduza a largura da tela e ajuste as configurações de ampliação do navegador ou tamanho da fonte. Verifique se a campo de entrada, a borda de foco e as frases de erro não estão cortadas ou sobrepostas.
Entenda os limites do CSS e da validação do navegador
O CSS é responsável por mostrar o estado de um item. A verificação pelo navegador pode reduzir erros de entrada do usuário, mas pode ser contornada com ferramentas de desenvolvedor ou requisições separadas, então o serviço real deve revalidar os valores permitidos, o comprimento, permissões, etc., no servidor. As frases de erro descrevem especificamente os itens problemáticos e suas soluções, e um fluxo separado para preservar as informações de entrada também é projetado quando ocorre um erro no servidor.
Se o resultado for inesperado, confira os pares for/id, name, required, type e os atributos disabled e readonly. Para mensagens que não aparecem após o envio, verifique o suporte a :user-invalid e a relação de irmãos do seletor explicada em Combinadores e pseudoclasses. Para foco invisível, procure regras que substituem outline.




