Corrige interfaces responsivas e problemas de viewport mobile. Trigger em: "responsivo", "mobile", "nao pega 100%", "cortando na tela", "quebrou no celular", "scroll horizontal", "viewport", "safe area", "notch", "bottom sheet", "modal no mobile", "confirmacao de exclusao", "modal de confirmar", "undo", "grid quebrado", "overflow", "converter para mobile", "adaptar layout".
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Converte interface pensada para desktop em interface que funciona de verdade em telas pequenas, e define os padroes de modal, formulario e confirmacao que a conversao expoe. Diferente da skill 02 (que decide como a interface vai parecer antes de existir), esta skill audita e conserta o que ja existe.
Esta skill segue GLOBAL.md, policies/execution.md, policies/handoffs.md, policies/token-efficiency.md, policies/stack-flexibility.md, policies/evals.md e policies/visual-diff-precision.md (validar correção de layout comparando screenshot antes/depois — decompor em passes de zoom, não afirmar "corrigido" a partir de uma olhada única).
Para catalogo completo de bugs com snippet de fix por framework (Tailwind, CSS puro, styled-components), consultar docs/skill-guides/responsive-conversion.md apenas quando necessario.
Em telas alteradas, complemente a comparação visual com teclado, zoom, conteúdo longo e estados relevantes; marque cada verificação indisponível. skills/91-unslop/references/evidencia-web.md separa o que foi observado do que ainda é hipótese.
Fronteira com skills vizinhas:
min-w-0 daqui frequentemente resolve os doisRodar nesta ordem. Cada fase alimenta a seguinte — pular fase gera fix superficial que reaparece.
Mapear onde o layout assume largura de desktop:
# Larguras fixas em px (o suspeito numero 1)
grep -rn "width: *[0-9]\{3,\}px\|w-\[[0-9]\{3,\}px\]\|min-width: *[0-9]\{3,\}px" src/ app/
# Alturas de viewport legadas (quebram com barra do browser mobile)
grep -rn "100vh\|h-screen\|min-h-screen" src/ app/
# Grids com contagem fixa de coluna
grep -rn "grid-cols-[3-9]\|grid-template-columns" src/ app/Cada hit e um candidato — nao um bug confirmado. Confirmar na Fase 2.
Nao confiar em "parece ok no devtools responsivo". Testar em 3 larguras que quebram coisas diferentes:
| Largura | Representa | O que quebra tipicamente |
|---|---|---|
| 320px | iPhone SE / Android pequeno | Largura fixa, botao com texto longo, tabela |
| 390px | iPhone padrao atual | Grid de 2 colunas apertado, modal com padding grande |
| 768px | Tablet retrato / limiar | Layout que troca de sidebar para hamburger no ponto errado |
Quando houver Playwright no projeto (skill 05), preferir teste automatizado de viewport a inspecao manual — o teste vira regressao.
Usar o catalogo abaixo. Fix sem entender a causa raiz reaparece na proxima tela.
Reconferir as 3 larguras da Fase 2 e a largura desktop original — conversao mobile que quebra o desktop nao e conversao, e troca de bug. Largura que quebrou volta pra Fase 3 pra reclassificar a causa raiz (o fix provavelmente resolveu o sintoma numa largura e criou outro numa diferente) — nao ajustar o CSS até "parecer ok" sem reclassificar.
O sintoma mais comum e quase sempre a mesma causa raiz: item de flex/grid tem min-width: auto por default, entao ele se recusa a encolher abaixo do conteudo, e o container "estoura" em vez de caber.
| Sintoma | Causa | Fix |
|---|---|---|
| Filho de flex nao encolhe, empurra layout | min-width: auto implicito no flex item | min-w-0 no filho (CSS: min-width: 0) |
| Coluna de grid estoura o container | Mesma causa, em grid | min-w-0 no item ou grid-template-columns: minmax(0, 1fr) |
| Texto longo sem espaco empurra tudo | Palavra sem quebra (URL, hash, email) | break-words / overflow-wrap: anywhere |
w-full nao surte efeito | Pai tem largura intrinseca (w-fit, inline-block, tabela) | Corrigir o pai, nao o filho |
| Componente com largura correta mas conteudo vaza | overflow nao definido | overflow-hidden no container so depois de confirmar que nao esconde conteudo util |
Regra: min-w-0 no filho de flex/grid resolve a maioria absoluta destes casos. Aplicar antes de tentar qualquer outra coisa.
100vh no mobile nao e a altura visivel — browsers mobile contam a viewport sem descontar a barra de endereco, entao o conteudo fica cortado atras dela.
| Unidade | Comportamento | Quando usar |
|---|---|---|
100vh | Altura maxima (barra recolhida) — corta conteudo | Nunca em mobile sem fallback |
100dvh | Altura dinamica real, acompanha a barra | Default para tela cheia em mobile |
100svh | Altura minima (barra visivel) | Quando o conteudo nunca pode ficar escondido |
100lvh | Altura maxima explicita | Background decorativo que pode passar por baixo |
Fallback para browsers antigos: declarar 100vh primeiro e 100dvh na linha seguinte — quem nao entende dvh ignora a segunda.
.tela-cheia {
height: 100vh;
height: 100dvh;
}Conteudo colado na borda em iPhone fica embaixo do notch (topo) ou da barra de gestos (base). Exige duas coisas juntas — falta uma, nao funciona:
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">.header-fixo { padding-top: env(safe-area-inset-top); }
.barra-inferior { padding-bottom: env(safe-area-inset-bottom); }
/* Somar ao padding proprio em vez de substituir */
.barra-inferior { padding-bottom: calc(1rem + env(safe-area-inset-bottom)); }Afeta: header fixo, bottom navigation, botao flutuante, bottom sheet, modal full-screen.
A pagina inteira desliza pro lado. Debug em ordem — o primeiro hit costuma ser o culpado:
// Cole no console: lista todo elemento mais largo que a tela
document.querySelectorAll('*').forEach(el => {
if (el.offsetWidth > document.documentElement.offsetWidth) console.log(el);
});Causas por frequencia: largura fixa em px maior que a tela → margem negativa sem overflow-hidden no pai → 100vw (ignora a barra de scroll, use 100%) → grid com grid-cols-N fixo → imagem sem max-width: 100% → tabela sem wrapper com scroll.
Nunca "resolver" com overflow-x: hidden no body — isso esconde o sintoma, mantem o bug e quebra position: sticky dentro da pagina.
| Padrao desktop | Conversao mobile | Como |
|---|---|---|
| Grid de N colunas fixas | Colunas por espaco disponivel | grid-cols-[repeat(auto-fit,minmax(280px,1fr))] — sem media query |
| Sidebar + conteudo | Stack vertical ou drawer | flex-col md:flex-row |
| Tabela de dados | Cards empilhados | Repetir o dado como card < md, tabela >= md |
| Toolbar horizontal | Scroll horizontal proprio ou menu "mais" | Wrapper com overflow-x-auto so na toolbar, nunca no body |
| Modal centralizado | Bottom sheet | Ver secao de modais |
| Icone + label lado a lado | So icone com aria-label | Manter hit area de 44px mesmo sem o label |
auto-fit + minmax resolve a maioria dos grids sem escrever uma media query — preferir a media query manual so quando a quebra precisa acontecer em ponto especifico do design.
| Problema | Fix |
|---|---|
| iOS aplica zoom ao focar input | font-size: 16px minimo no input (nao no label) |
| Teclado errado (numerico, email) | inputmode correto: numeric, decimal, email, tel |
| Autofill nao funciona | autocomplete semantico (given-name, cc-number, one-time-code) |
| Teclado cobre o campo focado | scroll-margin-bottom no input ou scroll manual no focus |
| Campos lado a lado ilegiveis | Empilhar sempre em mobile — grid-cols-1 md:grid-cols-2 |
| Botao de submit fora do alcance | Fixar no rodape com env(safe-area-inset-bottom) |
| Erro so no topo do form | Erro inline no campo e foco programatico no primeiro invalido |
| Erro so aparece no submit | Validar no blur de cada campo — no submit, o usuario ja perdeu o contexto do que digitou (ver skill 57) |
| Label vira placeholder e some ao digitar | Label flutuante — placeholder sozinho quebra leitor de tela e apaga a instrucao (ver skill 57) |
| Situacao | Desktop | Mobile | Motivo |
|---|---|---|---|
| Confirmar acao curta | Modal centralizado | Modal centralizado (pequeno) | Precisa de foco total, conteudo cabe |
| Formulario medio/longo | Modal centralizado | Bottom sheet ou tela cheia | Modal com scroll interno em tela pequena e hostil |
| Navegacao secundaria | Sidebar / dropdown | Drawer lateral | Preserva contexto da tela |
| Selecao de opcao em lista | Dropdown / popover | Bottom sheet | Alcance do polegar |
| Conteudo imersivo (imagem, leitura) | Modal grande | Tela cheia (rota propria) | Modal full-screen sem URL quebra o botao voltar |
Regra de ouro: se o conteudo do modal exige scroll em mobile, provavelmente deveria ser bottom sheet ou uma rota propria — nao um modal menor.
Falta qualquer um destes e o modal esta quebrado, independente da aparencia:
overflow: hidden no body perde a posicao de scroll no iOS; salvar e restaurar scrollY)role="dialog" + aria-modal="true" + aria-labelledby apontando para o titulopadding-bottom: env(safe-area-inset-bottom)Preferir primitiva acessivel pronta (Radix Dialog, Headless UI, <dialog> nativo) a implementar focus trap na mao — implementacao propria erra em detalhe de teclado quase sempre.
max-height: 85dvh como teto)100dvh nem esconder conteudo atras da barra de gestosO erro mais comum e tratar tudo igual: ou confirma tudo (fricção que treina o usuario a clicar "sim" sem ler), ou nao confirma nada (perda de dado real).
| Tipo de acao | Padrao correto | Nunca fazer |
|---|---|---|
| Reversivel e barata (arquivar, marcar lido, remover item do carrinho) | Executar direto + toast com Desfazer (5-10s) | Modal de confirmacao — fricção sem beneficio |
| Irreversivel comum (excluir registro, cancelar pedido) | Modal de confirmacao com consequencia explicita | Botao destrutivo sem nenhuma confirmacao |
| Irreversivel catastrofica (excluir conta, apagar workspace, deletar em massa) | Confirmacao com digitacao do nome do recurso | Modal simples de "Tem certeza?" |
| Envio que gera efeito externo (enviar email, publicar, cobrar cartao) | Revisao antes + estado de loading bloqueante + confirmacao de sucesso | Permitir duplo clique (submit duplo) |
| Cadastro/formulario longo | Autosave de rascunho + aviso ao sair com dado nao salvo | Perder tudo em navegacao acidental |
Preferir Desfazer a Confirmar sempre que a acao for tecnicamente reversivel — undo respeita mais o tempo do usuario e produz menos erro que um modal que ele aprendeu a dispensar.
Titulo: nomeia a acao e o alvo especifico
"Excluir o projeto Vendas Q4?"
NAO: "Tem certeza?" / "Confirmar acao"
Corpo: consequencia concreta e verificavel
"Os 128 registros e 3 integracoes serao removidos. Nao da pra desfazer."
NAO: "Esta acao nao pode ser desfeita." (generico, ninguem le)
Botao 1: verbo da acao, nao "OK" — visual destrutivo
"Excluir projeto"
NAO: "Sim" / "Confirmar" / "OK"
Botao 2: saida segura, e o default do foco
"Cancelar"
Foco: inicia no botao seguro, nunca no destrutivo
Escape: cancela
Backdrop: NAO fecha (evita dispensar sem querer)Para acao catastrofica, exigir digitacao literal do nome do recurso e manter o botao desabilitado ate bater exatamente — atrito proposital e desejavel aqui.
Toda acao que chama API precisa dos quatro:
Nunca fechar o modal antes da resposta chegar: fechar otimista em acao destrutiva esconde o erro do usuario.
overflow-x: hidden no body para "resolver" scroll horizontal — esconde o bug e quebra position: sticky100vh em tela cheia mobile sem fallback dvhmin-w-0, auto-fit/minmax, flex-wrap, clamp()hidden md:block) como solucao de layout — mover ou reorganizar, nao amputartouch-action: none global para "resolver" scroll — mata gesto legitimoLayout:
min-w-0 onde encolhemdvh em vez de vh em tela cheia (com fallback)viewport-fit=cover + env(safe-area-inset-*) em elementos de bordaauto-fit/minmax ou colapsam por breakpointmax-width: 100% e aspect-ratio definidoInteracao:
font-size >= 16px, inputmode e autocomplete corretosConfirmacao:
Comentario so quando o valor nao e obvio — min-w-0 e 100dvh merecem uma linha explicando o porque, ja que parecem arbitrarios para quem nunca caiu no bug. Classe utilitaria autoexplicativa nao precisa de comentario.
felvieira/claude-skills-fv
449fb53
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.