Nesta página38
- DR
- Quando usar rádios (árvore de decisão)
- Anatomia de um Grupo de Rádio Adequado
- Linha de base semântica de copiar e colar (sem CSS sofisticado ainda)
- CSS mínimo para usabilidade (aparência nativa, grandes alvos, foco claro)
- Validação suave e acessível (usa primeiro o navegador)
- Custom-Styled “Card” Radios (without breaking accessibility)
- Copy-paste HTML
- CSS mínimo e robusto
- Notas de comportamento (por que esse padrão funciona)
- Opcional: validação suave (nativo primeiro)
- Estratégias de validação que não incomodam
- Princípios
- Linha de base (somente nativo)
- Erros inline amigáveis (aprimoramento progressivo)
- document.getElementById('nextBtn').addEventListener('click', () => {
- primeiro
- Server-side & network fallbacks
- Integração Formspree (aprimoramento progressivo)
- HTML nativo (sempre funciona)
- Aprimoramento de JS (boa UX, melhor rastreamento)
- Controle de spam sem prejudicar as conversões
- Linhas de assunto que refletem a escolha do rádio (caixa de entrada limpa)
- Armadilhas comuns a serem evitadas
- Internacionalização e Inclusão
- Idioma, rótulos e tom
- Etiquetas longas e opções de múltiplas linhas
- Suporte da direita para a esquerda (RTL)
- Acessibilidade além do ARIA
- Lista de verificação de teste (para impressão)
- Desempenho e facilidade de manutenção
- Análise e Experimentação
- Antipadrões (não faça isso)
- Lista de Verificação Final
- Recursos
- Especificações e padrões de autoria
- Guias de referência
- Testes e Ferramentas
Os botões de opção parecem simples. Um clique, uma escolha. No entanto, eles também são uma das maneiras mais fáceis de comprometer a experiência do usuário e a acessibilidade. Oculte a entrada nativa, pule oconjunto de camposelegendaou valide de forma muito agressiva e você enviará um formulário que confunde os usuários de teclado, frustra os leitores de tela e prejudica as conversões.
Este guia mostra como fazer rádios da maneira certa em 2025: rápido de escolher, fácil de escanear, totalmente acessível e mensurável. Começaremos com uma linha de base semântica limpa e, em seguida, aplicaremos CSS moderno para que os rádios possam parecer cartões ou controles segmentados sem interromper o comportamento do teclado ou do leitor de tela.
Você verá padrões de validação práticos que não incomodam, layouts responsivos que mantêm os alvos grandes em dispositivos móveis e snippets de produção que você pode colar em qualquer pilha. Também abordaremos análises, ideias A/B e uma configuração do Formspree para que você possa capturar resultados imediatamente.
A quem se destina: designers, desenvolvedores front-end e profissionais de marketing que se preocupam com ambosacessibilidadeeconversão. Não são necessárias estruturas pesadas, apenas HTML sólido, CSS focado e um pequeno aprimoramento progressivo.
No final, você saberá:
- Quando os rádios batem seleções, caixas de seleção ou alternações
- Como construir um grupo de rádio acessível (
fieldset,legend, rotulagem, foco) - Como estilizar rádios de “cartão” personalizados sem ocultar a entrada
- Como validar com a API HTML Constraint (e enviar bem mensagens)
- Como conectar rádios ao Formspree e medir seleções
DR
- Usarrádiosexatamenteumescolha dentro de um conjunto bem definido (idealmente2–6 opções) que deve servisível de uma só vez.
- Sempre embrulhe os rádios em
+, dê a eles omesmonomee torne cada opção umclicável. - Não oculte entradas com
exibição:nenhum; guarde-osfocalizável(por exemplo,opacity:0; position:absolute; inset:0) entãoTabulação/Setas/Espaçotrabalhar. - Torne as metas grandes: pelo menos44×44px, com umanel de focoisso é claramente visível.
- Valide com oAPI de restrição HTML(
exigido,reportValidity()) e, em seguida, aprimore as mensagens, e não o contrário. - Se você tiver muitas opções ou elas não estiverem familiarizadas, adicionetexto auxiliarsob cada rótulo e considerepesquisar ou agruparem vez de.
- No celular, empilheuma coluna; em telas largas,2–3 colunasvia grade CSS.
- Medida: rastrearimpressões, seleção e envioe teste A/Bordem de opçõesecopiar.
- Para o Formspree, mantenhaPOST nativocomo um substituto; adicionarbuscarapenas como aprimoramento progressivo.
Quando usar rádios (árvore de decisão)
Q1. O usuário está escolhendo exatamente uma opção?
- Não →Usarcaixas de seleção(0–muitos) ou umalternar(binário) ou repensar a tarefa.
- Sim →Vá para o segundo trimestre.
Q2. As opções precisam estar visíveis à primeira vista?
- Sim →Usarrádios(melhor para digitalização e escolha rápida).
- Não (o espaço é apertado/muitas opções)→ Considere umselecione(suspenso). Se as escolhas são críticas e beneficiam da comparação, prefira rádios e redesenhe o layout.
Q3. Quantas opções?
- 2–6→ Os rádios são ideais.
- 7–10→ Os rádios ainda podem funcionar com agrupamento ouduas colunasgrade; caso contrário, use uma lista selecionada ou pesquisável.
- >10→ Use umselecione com pesquisaou umpassoisso restringe o conjunto primeiro.
Q4. As opções são estados mutuamente exclusivos?
- Sim →Rádios.
- Não / combinações fazem sentido →Caixas de seleção.
Q5. A escolha desencadeará diferentes perguntas de acompanhamento?
- Sim →Os rádios ainda estão bem. Mostrar acompanhamentoscondicionalmente, mas mantenha os campos ocultosfora da ordem de tabulaçãoe fluxo SR até ser revelado.
- Não →Grupo de rádio simples.
Q6. Familiar versus descritivo?
- Rótulos familiares(por exemplo, “Pequeno/Médio/Grande”) → rótulos curtos são suficientes.
- Desconhecido ou de alto risco(por exemplo, “SEO técnico vs. SEO de conteúdo”) → adicionarmicrocópia(descrição de uma linha) sob cada rótulo.
P7. Primeiro o celular?
- Sim (sempre)→ Usarpilha de uma colunacom espaçamento generoso e texto de 16–18px. Promova omais escolhidoopção em direção ao topo.
Exemplos práticos
- Seu formulário: “Qual serviço?” → Os rádios vencem uma seleção porque os usuários devem comparar as opções lado a lado. Mantenha 3 cartões (Link Building, SEO, Web Dev) com subtexto curto.
- Velocidade de envio: 3–4 velocidades mutuamente exclusivas → Rádios (com deltas de preços no subtexto).
- Frequência do boletim informativo: Diário/Semanal/Mensal → Rádios.
- Interesses (pode escolher vários)→ Não são rádios; use caixas de seleção.
Anatomia de um Grupo de Rádio Adequado
Linha de base semântica de copiar e colar (sem CSS sofisticado ainda)
Por que cada parte é importante
+dá ao grupo um nome para leitores de tela e define o contexto para todos.- Igual
nometorna as entradas mutuamente exclusivas. - Clicável
em torno de cada entradaoferece uma enorme área de toque/clique (44px +). obrigatóriona primeira rádiopermite que o navegador valide o grupo nativamente.- Texto auxiliar(
dica de serviço) etexto de erro(service-error) são separados para que você possa mostrar/ocultar erros sem mover as coisas. - Não são necessárias funções ARIA.As rádios nativas já expõem a semântica correta.
CSS mínimo para usabilidade (aparência nativa, grandes alvos, foco claro)
/* Layout e espaçamento */
rótulo de campo {
exibição: flexível;
alinhar itens: centro;
lacuna: 0,6rem;
preenchimento: 0,65rem 0,8rem; /* grande toque no alvo */
raio da fronteira: .6rem;
cursor: ponteiro;
}
/* Foco do teclado: destaca todo o rótulo quando a entrada está focada */
.field label:has(input:focus-visible) {
contorno: 3px sólido #3b82f6;
deslocamento de contorno: 2px;
}
/* Estado selecionado (opcional, o ponto nativo ainda é exibido) */
.field label:has(input:checked) {
plano de fundo: #f1f5ff;
}
/* Texto do erro */
.error { cor: #b91c1c; margem superior: 0,5rem; tamanho da fonte: .9rem; }
Dica:
:tem()oferece aquele “anel de foco em todo o cartão” sem ocultar a entrada real. Se um navegador mais antigo não for compatível, os usuários ainda terão o anel de foco nativo no próprio rádio.
Validação suave e acessível (usa primeiro o navegador)
Deixe o navegador lidar com a parte “você deve escolher uma” e, em seguida, mostre seu erro embutido, se necessário.
const form = document.getElementById('quote-form');
grupo const = document.getElementById('grupo de serviço');
erro const = document.getEementById('erro de serviço');
form.addEventListener('submit', (e) => {
// Aciona a UI de validação nativa (funciona porque o primeiro rádio tem `required`)
if (!form.reportValidity()) {
// Opcional: exibe um erro inline amigável também
error.hidden = false;
group.setAttribute('aria-invalid', 'true');
e.preventDefault();
} else {
erro.hidden = true;
group.removeAttribute('aria-invalid');
Comportamento que você deve esperar (e testar):
Teclado:
Tab uma vez para entrar no grupo; usar
- Teclas de setamover-se;Espaçoseleciona.Leitores de tela:A legenda é lida como o rótulo do grupo; cada opção é anunciada com o estado “selecionado/não selecionado”.
- Toque em:Tocar na etiqueta alterna o rádio (graças à embalagem da etiqueta).
- Rádios “Card” com estilo personalizado (sem quebrar a acessibilidade)Copiar e colar HTML
Custom-Styled “Card” Radios (without breaking accessibility)
Copy-paste HTML
CSS mínimo e robusto
:raiz{
--marca:#0b5cff; --anel: rgba(11,92,255,0,35);
--border:#e5e7eb; --bg:#fff; --mutado:#6b7280;
--raio:14px;
}
/* Grade */
.card-group{
exibição: grade; lacuna: 16px;
colunas de modelo de grade: repetir (3, minmax (0,1fr));
}
@media (largura máxima: 900px){ .card-group{ grid-template-columns:1fr 1fr; } }
@media (largura máxima: 640px){ .card-group{ grid-template-columns:1fr; } }
/* Etiqueta do cartão */
.cartão{
posição:relativo;
exibição: grade; itens de lugar:centro; alinhamento de texto:centro;
lacuna:6px; preenchimento: 18px;
borda: 1px var sólido (--borda); raio-da-borda:var(--raio);
plano de fundo:var(--bg);
cursor:ponteiro; seleção de usuário: nenhum;
transição: box-shadow 0,15s, cor da borda 0,15s, transformação 0,02s;
}
.card:hover{box-shadow:0 8px 20px rgba(0,0,0,.06); }
/* Mantém o foco da entrada nativa: no display:none */
.entrada de cartão{
posição:absoluta; inserção:0; opacidade:0;
}
/* Anel de foco do teclado em todo o cartão */
.card:has(input:foco-visível){
box-shadow:0 0 0 3px var(--ring);
cor da borda: var(--marca);
}
/* Estado selecionado */
.card:has(input:verificado){
cor da borda: var(--marca);
box-shadow:0 0 0 3px var(--ring);
}
/* Conteúdo */
.card-title{ peso da fonte:700; cor:#111; }
.card-sub{tamanho da fonte:14px; cor:var(--silenciado); }
/* Texto do erro */
.erro{cor:#b91c1c; margem superior: 0,5rem; tamanho da fonte: .9rem; }
Notas de comportamento (por que esse padrão funciona)
- Não
exibição:nenhumna entrada → teclado, os usuários podem entrar;Teclas de setaseleção de movimento;Espaçoseleciona. - O cartão inteiro é clicável porque a entrada está dentro do
etiqueta. :tem()vamos estilizarfocoeverificadoestados no cartão pai sem hacks ARIA.- Grade responsiva fornece1–3 colunasautomaticamente; os alvos de toque permanecem grandes.
Opcional: validação suave (nativo primeiro)
const form = document.getElementById('plano');
const err = document.getElementById('erro do plano');
form.addEventListener('submit', (e) => {
if (!form.reportValidity()) { // usa o `required` no primeiro rádio
err.hidden = false;
e.preventDefault();
} else {
err.hidden = true;
}
});
Estratégias de validação que não incomodam
Uma grande validação é invisível até que seja necessária. Esta é uma abordagem específica para rádio que é rápida, acessível e relaxante para os usuários.
Princípios
- Nativo primeiro.Deixe o HTML lidar com “um deve ser selecionado”.
- Adiar erros.Não grite com os usuários antes que eles tentem continuar.
- Aponte para o problema.Anuncie erros, mude o foco de maneira inteligente e mantenha o texto curto.
- Limpar na mudança.Assim que uma escolha válida for feita, remova o erro.
Linha de base (somente nativo)
Somente HTML pode impor a regra comobrigatórioem uma rádio do grupo.
Isso já fornece: setas do teclado, espaço para selecionar e validação no nível do navegador.
Erros inline amigáveis (aprimoramento progressivo)
Desligue o pop-up do navegador e manipule as mensagens inline para que correspondam ao seu design.
HTML (adicionar uma região de erro)
CSS (estilo simples)
.erro { cor:#b91c1c; margem superior: 0,5rem; tamanho da fonte: .9rem; }
JS (adiar erros, anunciar corretamente)
const formulário = document.getElementById('quote');
const grupo = document.getElementById('svc');
const err = document.getElementById('svc-err');
rádios const = form.querySelectorAll('input[nome="serviço"]');
deixe tentado = falso; // mostra erros somente após o usuário tentar continuar
função hasSelection() {
return [...rádios].alguns(r => r.checked);
}
function showError(msg='Escolha uma opção.') {
err.textContent = mensagem;
err.oculto = falso;
group.setAttribute('aria-inválido', 'true');
// Acrescenta o erro aoscribedby para que os SRs o anunciem em seguida
group.setAttribute('aria-describedby', 'svc-hint svc-err');
}
função clearError() {
err.oculto = verdadeiro;
group.removeAttribute('aria-inválido');
group.setAttribute('aria-describedby', 'svc-hint');
}
form.addEventListener('submit', (e) => {
tentou = true;
if (!hasSelection()) {
e.preventDefault();
showError();
// Traga o grupo à vista e coloque o foco no primeiro rádio
radios[0].focus();
group.scrollIntoView({ behavior: 'smooth', block: 'center' });
} senão {
limparErro();
// Não importune cedo; claro assim que escolherem algo
radios.forEach(r => {
r.addEventListener('change', () => {
if (tentativa) clearError();
});
});
Por que isso funciona
Sem bolhas de dicas de ferramentas do navegador; os usuários veem erros
embutido
- ao lado do grupo.Os leitores de tela ouvem olegenda
- , então oerro, graças aária-descrita por.
Erros só aparecemdepois - uma tentativa de envio (ou ao retornar para corrigir).Validação suave por etapa (formulários em várias etapas)Se você clicar no botão “Avançar”, valide apenas essa etapa.
document.getElementById('nextBtn').addEventListener('click', () => {
if (!hasSelection()) {
showError();
} else {
clearError();
// avança para a próxima etapa...
}
});
Mensagens personalizadas com Constraint API (opcional)
Se preferir manter o modelo de validade do navegador, defina uma mensagem personalizada no
primeiro
rádio no grupo.const primeiroRadio = rádios[0];form.addEventListener('submit', (e) => {
if (!hasSelection()) {
firstRadio.setCustomValidity('Escolha uma opção.');
// Aciona a UI nativa; ou chama form.reportValidity()
e.preventDefault();
form.reportValidity();
} else {
firstRadio.setCustomValidity('');
Use-o quando quiser a “bolha” nativa mais seu próprio texto; caso contrário, siga o método embutido acima para obter uma interface de usuário consistente.
Resumo de erros (para formulários longos)
Se o seu formulário for longo, adicione um
resumo principal
que está vinculado à área do problema.
Há um problema: Escolha um serviço.
função showSummary() {
const sum = document.getElementById('resumo do erro');
soma.oculto = falso;
sum.querySelector('a').focus(); // RSs anunciam o alerta
}
Fallbacks do lado do servidor e de rede
A validação do lado do cliente melhora a UX, mas
sempre
valide no servidor (ou pelo seu serviço de envio) também. Se o envio falhar, retorne a página com:
Server-side & network fallbacks
Há um problema: Escolha um serviço.
const sum = document.getElementById('resumo do erro');
soma.oculto = falso;
sum.querySelector('a').focus(); // RSs anunciam o alerta
}
Fallbacks do lado do servidor e de rede
A validação do lado do cliente melhora a UX, mas
sempre
valide no servidor (ou pelo seu serviço de envio) também. Se o envio falhar, retorne a página com:
Client-side validation improves UX, but always validate on the server (or by your submission service) too. If submission fails, return the page with:
- O anteriora seleção persistiue
- Omesmo erro embutidoao lado do grupo.
Integração Formspree (aprimoramento progressivo)
Faça os rádios funcionarem mesmo se o JavaScript falhar e, em seguida, aprimore-os para obter um agradecimento mais suave e análises melhores.
HTML nativo (sempre funciona)
id="citação"
action="https://formspree.io/f/seu_form_id"
método="POST"
>
Escolha uma opção.
Nome completo
E-mail
Algo deu errado. Por favor, tente novamente.
Obrigado! Entraremos em contato em breve.
O que isso oferece:
- Funciona com JS desativado (bom para SEO, confiabilidade).
- O navegador lida com “um deve ser selecionado” (
obrigatóriono primeiro rádio). - Formspree recebe
serviço,nome,e-maile_assunto.
Aprimoramento de JS (boa UX, melhor rastreamento)
Intercepte o envio, valide, envie combuscare mostre um agradecimento embutido (ou redirecionamento).
(function(){
const form = document.getElementById('quote');
const okMsg = document.getElementById('form-success');
const errMsg = document.getElementById('form-error');
const submitBtn = form.querySelector('button[type="submit"]');
// Opcional: capturar UTM + contexto da página
function appendMeta(fd){
const url = new URL(location.href
const v = url.searchParams.get(k);
if(v) fd.append(k, v);
fd.append('page_url', location.href); e.preventDefault();
// Use native validity (includes radio required)
if (!form.reportValidity()) return;
const fd = new FormData(form);
// Don’t send honeypot if filled (treat as spam)
if (fd.get('company')) return; // silently drop bots
appendMeta(fd);
submitBtn.disabled = true;
const original = submitBtn.textContent;
submitBtn.textContent = 'Submitting…';
okMsg.hidden = true; errMsg.hidden = true;
try{
const res = await fetch(form.action, {
method: 'POST',
body: fd,
headers: { 'Accept': 'application/json' }
});
if(res.ok){
form.reset();
const res = await fetch(form.action, {
method: 'POST',
body: fd,
headers: { 'Accept': 'application/json' }
});
if(res.ok){
form.reset();
okMsg.hidden = false;
// Optional: fire analytics
if (window.gtag) gtag('event','generate_lead',{método:'formspree', serviço: fd.get('service')});
// Opcional: redirecionamento após sucesso
// setTimeout(()=> location.href = '/obrigado/', 1200);
} senão {
errMsg.hidden = falso;
}
} pegar {
errMsg.hidden = falso;
} finalmente {
enviarBtn.disabled = falso;
submitBtn.textContent = original;
}
});
})();
Notas
- Definir
Aceitar: aplicação/jsonentão o Formspree retorna JSON e você pode decidir sucesso/falha de forma limpa. - Usar
form.reportValidity()portanto, o navegador impõe a seleção do rádio e o formato do e-mail antes do envio. - Mantenha o nativo
ação/métodoentão o formulário ainda funciona sem JS.
Controle de spam sem prejudicar as conversões
- Pote de mel(incluído acima) captura muitos bots sem atrito.
- Tempo: adicione um
oculto começou_emquando a página carrega; ignore os envios mais rápido do que, digamos, 2 segundos. - Sinais de conteúdo: se você vir valores indesejados repetidos, filtre-os nas regras do Formspree ou no pós-processamento.
document.getElementById('started_at').value = Date.now();
// no manipulador de envio antes de enviar:
const iniciado = Number(fd.get('started_at'));
if (Date.now() - iniciado <2000) return; // parece um bot
Linhas de assunto que refletem a escolha do rádio (caixa de entrada limpa)
Você pode personalizar_assuntoda rádio selecionada:
serviço const = fd.get('serviço'); // por exemplo, "seo"
fd.set('_subject', `Novo lead ${service} do formulário de contato`);
Armadilhas comuns a serem evitadas
- Escondendo rádios com
exibição:nenhum.Usaropacidade:0; posição:absoluta; inserção:0dentro da etiqueta para que os teclados ainda funcionem. - Esquecendo
conjunto de campos/legenda.Os leitores de tela dependem deles para contextualizar. - Validação excessiva antecipadamente.Mostrar erros após enviar/Avançar e limpar assim que o usuário corrigir o grupo.
- Não capturando o contexto.Adicionar
URL_da_página,referenciador, e campos UTM, você se agradecerá mais tarde.
Internacionalização e Inclusão
Idioma, rótulos e tom
- Use o
da página idioma(e alternar páginas por localidade):… - Mantenha os rótulos curtos edescritivo, evite jargões específicos da cultura.
- Prefiraneutrofraseado (“Escolha um plano”) em vez de suposições (“Qual é o seu orçamento?”).
- Localizarerrosetexto auxiliarcom um dicionário simples digitado por
document.documentElement.lang.
const i18n = {
pt: { escolha: 'Por favor, escolha uma opção.' },
es: { escolha: 'Escolha uma opção, por favor.' },
ar: { escolha: 'يُرجى اختيار خيار واحد.' }
};
const t = (k) => (i18n[document.documentElement.lang] || i18n.en)[k];
errorEl.textContent = t('escolher');
Etiquetas longas e opções de múltiplas linhas
- Deixe os rótulosembrulhar; nunca trunque palavras cruciais.
- Mantenha a área de acerto grande mesmo quando o texto for quebrado: use preenchimento noetiqueta, não apenas a entrada.
.card {tamanho embutido: 100%; preenchimento: 16px; }
.card .card-title { peso da fonte: 700; altura da linha: 1,25; }
.card .card-sub {tamanho da fonte: 14px; altura da linha: 1,4; }
Suporte da direita para a esquerda (RTL)
Usar CSSpropriedades lógicase:dir()então você não precisa de estilos separados.
/* Espaçamento que inverte em RTL automaticamente */
.card { preenchimento embutido: 16px; bloco de preenchimento: 16px; }
/* Anel de foco que respeita a direção */
.card:has(input:foco-visível) {
contorno: 3px var sólido (--ring);
deslocamento de contorno: 2px;
}
/* Opcional: ajustes específicos de direção */
:dir(rtl) .card-group { direção: rtl; }
Acessibilidade além do ARIA
- Garantircontraste ≥ 4,5:1para rótulos e estados de foco.
- Alvos de toque ≥44×44 pixels(preenchimento em vez do tamanho da fonte).
- Não comunique o estado apenas pela cor; usarbordas, ícones ou texto.
Lista de verificação de teste (para impressão)
- Semântica: Os rádios estão dentro
conjunto de camposcom um visívellegenda. - Teclado: Tab entra no grupo;setasmover;Espaçoseleciona.
- Leitores de tela: Lenda anunciada; cada opção diz selecionado/não selecionado.
- Foco: Anel visível nocartão inteiro(e na entrada nativa).
- Área de acerto: o rótulo inteiro é clicável; funciona no celular.
- Validação: Sem erros até enviar/Próximo; erros claros na mudança.
- Copiar: As opções são curtas; o texto auxiliar esclarece as diferenças.
- Disposição: 1 coluna em telefones; 2–3 na área de trabalho; sem recorte de excesso.
- i18n: Erros/rótulos localizados; o texto longo é moldado graciosamente; RTL OK.
- Análise: Eventos para impressão, seleção, envio.
- Desempenho: Sem bibliotecas de UI pesadas; CSS mínimo; nenhuma mudança de layout.
Desempenho e facilidade de manutenção
- Favorentradas nativas+ CSS leve; evite substituir rádios por divs.
- Mantenha o CSS modular (propriedades personalizadas para cores, raio, anel).
- Evite
exibição:nenhumem insumos; usaropacidade:0; posição:absoluta; inserção:0portanto a acessibilidade permanece intacta. - Adiar JS não crítico; mantenha os aprimoramentos abaixo de aproximadamente 2–5 KB, quando possível.
- Usarconsultas de contêineres(quando disponível) em vez de pontos de interrupção de mídia complexos para formulários incorporados.
@container (largura mínima: 680px) {
.card-group {colunas de modelo de grade: 1fr 1fr 1fr; }
}
Análise e Experimentação
Rastreie a intenção e os pontos de atrito:
// Dispara quando o grupo de rádio fica visível
gtag?.('evento','form_step_view', { etapa: 1, formulário: 'contato' });
// Dispara na seleção
document.querySelectorAll('input[name="service"]').forEach(r => {
r.addEventListener('change', () => {
gtag?.('event','radio_select', { group: 'service', valor: r.value });
});
});
// Dispara no envio bem-sucedido
gtag?.('evento','generate_lead', { formulário: 'contato', serviço: formulário.serviço.valor });
Teste A/B:
- Ordem de opções(mais escolhidos primeiro)
- Cópia do CTA(“Obter minha proposta gratuita” versus “Obter meu orçamento”)
- Texto auxiliarpresença
Antipadrões (não faça isso)
- Ocultando entradas com
exibição:nenhum(quebra o teclado e SRs). - Desaparecido
conjunto de campos/legenda. - Pequenas áreas atingidas (apenas o pequeno ponto clicável).
- Estado de seleção somente de cor; foco invisível.
- Validandoanteso usuário tenta prosseguir.
- Incluir de 10 a 20 opções em rádios; use uma seleção pesquisável.
Lista de Verificação Final
conjunto de campos+legendapresente- Igual
nome, únicovalore - Etiquetas envolvem entradas; cartão inteiro clicável
- Anel de foco claramente visível
obrigatóriona primeira rádio; erros inline suaves- Grade de 1 a 3 colunas responsiva, grandes alvos de toque
- Sequências localizadas; RTL seguro através de propriedades lógicas
- Análise ao visualizar/selecionar/enviar
- A validação do lado do servidor espelha as regras do cliente
Recursos
Especificações e padrões de autoria
- Padrão HTML –
: semântica nativa, agrupamento pornome, formar comportamento. - Práticas de Autoria WAI-ARIA 1.2 – Grupo de Rádio: comportamento esperado do teclado (Tab no grupo,Setapara mover,Espaçopara selecionar), padrões de rotulagem.
- WCAG 2.2fundamentos para rádios:
- 2.1.1Teclado(tudo operável via teclado)
- 2.4.7Foco visível(foco claramente visível)
- 2.5.5Tamanho alvo(≥44×44px recomendado)
- 1.4.3Contraste (Mínimo)
Guias de referência
- MDN: Entrada de rádio,
etiqueta,conjunto de campos/legenda, validação de formulário (API de validação de restrição). - Sistema de Design GOV.UK – Rádios: orientação excelente e testada em batalha sobre redação e erros.
- Componentes Inclusivos (Heydon Pickering): padrões e críticas práticas.
Confira nosso blog recente emComo procurar oportunidades de postagem de convidados no Ahrefs (guia passo a passo)
Testes e Ferramentas
- machado DevTools(extensão do navegador) – verificações automáticas a11y.
- Informações sobre acessibilidade– testes rápidos guiados.
- Farol– sinais de desempenho + acessibilidade.
- Verificador de contraste WebAIM– verifique o contraste da cor.
- Leitores de telapara verificar o comportamento real:
- NVDA(Janelas),MANDÍBULAS(Janelas),VozOver(macOS/iOS),TalkBack(Android).
- Passagem manual do teclado: Tab no grupo → As setas se movem → Seleciona o espaço → o anel de foco permanece óbvio.
Confira nossorevisão de Noções de Marketing
FAQs (breves e práticas)
Apontar para2–6. Se você tiver de 7 a 10, agrupe ou use uma grade de duas colunas. Acima de ~10, mude para umselecione (com pesquisa)ou redesenhe para restringir as escolhas primeiro.
Somente se houver umclara inadimplência da maioriae não distorcerá os dados. A pré-seleção acelera a conclusão, mas pode reduzir a escolha deliberada. Se não tiver certeza,não pré-selecione.
Rádios: escolha única, as opções devem servisívellado a lado.
Selecione: escolha única quando o espaço é apertado ou as opções são muitas.
Caixas de seleção:0–muitosescolhas (não mutuamente exclusivas).
Sim. Mantenha oentrada nativa focável(não usedisplay:none). Coloque a entradadentro do, defina-o comoopacidade:0; posição:absoluta; inserção:0;e estilize o rótulo. Usar:has(entrada:foco-visível)e:tem(entrada:verificado)para direcionar o foco/estados selecionados.
Use HTML primeiro: coloqueobrigatóriona primeira rádioe ligueform.reportValidity()(ou deixe o navegador manipular o envio). Para uma interface de usuário mais agradável, mostre um breveerro embutidoperto do grupodepoisa primeira tentativa, eclaro sobre a mudança.
role="radiogrupo"? Não para rádios nativas. Um verdadeiroconjunto de campos+legendajá dá aos leitores de tela o contexto certo. Adicione ARIA apenas se você estiver construindo umtotalmente personalizadowidget (evite se possível).
Mostrar/ocultar os acompanhamentosdepoisuma seleção. Quando oculto, tambémdesabilitaresses controles para que fiquem fora da ordem de tabulação e não sejam enviados. Quando revelado, mova o foco de forma sensata e certifique-se de que os rótulos permaneçam claros.
Fluxo do teclado, foco visível, anúncios do leitor de tela (leitura de legenda, estado selecionado anunciado), áreas de ocorrências móveis, tempo de validação (sem irritação antecipada) e valores selecionadospersistirem erro do lado do servidor.
