CSS mobile-first: escreva a tela estreita primeiro e deixe o desktop só acrescentar
Reescreva o CSS com a regra base para o celular e media queries min-width para telas maiores, com menos sobrescrita, alvos de toque decentes e um teste que pega o que ficou de fora.
O CSS da loja tem 1.800 linhas e um bloco no fim chamado "celular", com 300 linhas de max-width: 768px desfazendo o que veio antes: float: none, width: auto, display: block, margens zeradas. Cada coisa nova no desktop quebra algo no celular, porque alguém esqueceu de desfazer. A resposta curta: escreva as regras base para a tela estreita, sem media query, e use @media (min-width: ...) só para acrescentar o que a tela larga ganha. A tela pequena deixa de ser uma exceção que desfaz o desktop e passa a ser o ponto de partida.
Na prática, o arquivo encolhe, porque o layout de uma coluna é quase o comportamento natural do HTML, e o desktop só acrescenta colunas e espaço.
Por que começar pelo desktop gera tanta sobrescrita
Elementos de bloco já se empilham e ocupam a largura toda por padrão. O layout de uma coluna, que é o que o celular precisa, é quase o que o navegador faz sem CSS de layout nenhum. Quando você começa pelo desktop, adiciona colunas, larguras fixas e posicionamentos, e depois precisa escrever mais CSS para voltar ao comportamento padrão na tela estreita.
Mobile-first inverte o custo. A base é simples, porque segue o fluxo natural. Cada min-width acrescenta: duas colunas aqui, uma barra lateral ali. Nada precisa ser desfeito, e uma regra nova de desktop fica presa dentro da query dela, sem chance de vazar para o celular.
Há também um efeito na forma de pensar. Com pouco espaço, você precisa decidir o que é essencial na página. O que sobra na tela larga é acréscimo, não o produto. Se você começa pela tela larga, é fácil empilhar coisas que no celular viram três telas de rolagem até o botão de comprar.
A diferença entre este post e o de trocar o layout pela largura da tela é o foco: lá o assunto é tirar a decisão do script e colocar no CSS; aqui é a ordem em que você escreve esse CSS.
Como reescrever uma página em mobile-first
- Confirme a meta tag de viewport com
width=device-widthnohead. - Abra a página com a janela estreita, perto de 360 pixels, e escreva as regras até ela ficar completa e confortável ali.
- Alargue a janela devagar. Quando o conteúdo começar a sobrar ou a linha ficar longa demais, anote a largura.
- Crie uma
@media (min-width: ...)nessa largura e acrescente só o que muda. - Repita para o próximo ponto em que o layout pede mudança. Dois ou três pontos costumam bastar.
- Apague as regras de
max-widthantigas que só desfaziam o desktop.
O exemplo: a listagem de produtos
A listagem da loja tem um cabeçalho com logotipo e menu, filtros e uma grade de cartões de produto. Primeiro, a versão desktop-first que existia, resumida:
/* antes: desktop-first */
.produtos { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.filtros { float: left; width: 240px; }
.conteudo { margin-left: 264px; }
@media (max-width: 768px) {
.produtos { grid-template-columns: 1fr; gap: 16px; }
.filtros { float: none; width: auto; }
.conteudo { margin-left: 0; }
}
Agora a mesma tela em mobile-first:
/* depois: mobile-first */
.produtos {
display: grid;
gap: 1em;
}
.layout {
display: grid;
gap: 1.5em;
}
@media (min-width: 40em) {
.produtos {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 64em) {
.layout {
grid-template-columns: 15em minmax(0, 1fr);
}
.produtos {
grid-template-columns: repeat(3, 1fr);
}
}
A base não tem coluna nenhuma: filtros em cima, produtos embaixo, um por linha. A 40em entram dois cartões por linha. A 64em, a barra de filtros vai para a lateral e a grade ganha a terceira coluna. Nenhuma linha desfaz outra. Os pontos de quebra vieram do conteúdo: abaixo de 40em, dois cartões ficavam com o nome do produto quebrando em quatro linhas; abaixo de 64em, a barra lateral espremia a grade.
Uma grade que nem precisa de media query
Para a grade de cartões, existe uma alternativa que se adapta sozinha à largura disponível, sem pontos de quebra:
.produtos {
display: grid;
gap: 1em;
grid-template-columns: repeat(auto-fill, minmax(min(100%, 15em), 1fr));
}
O navegador cabe quantos cartões de pelo menos 15em couberem, e o min(100%, 15em) impede o cartão de estourar numa tela menor que 15em. É mobile-first por natureza: na tela estreita sobra uma coluna, e cada aumento de espaço acrescenta outra.
O que a base para celular precisa ter
- Alvos de toque confortáveis. As diretrizes de acessibilidade pedem no mínimo 24 por 24 pixels CSS por alvo, e recomendam 44 por 44. Botões e links de menu no celular devem ficar perto do maior valor.
- Texto legível sem zoom. Corpo do texto em torno de
1reme linhas com altura confortável. - Nada com largura fixa maior que a tela. Imagens com
max-width: 100%eheight: auto; tabelas largas tratadas à parte. - A ação principal alcançável. Na página de produto, preço e botão de comprar sem precisar atravessar filtros, banners e avisos.
Lembre que CSS mobile-first não reduz o peso das imagens. Uma foto de 3 MB no HTML continua com 3 MB no celular. Para isso, servir arquivos menores é outro trabalho, descrito no guia de redimensionar imagem no servidor.
Erros comuns
- Misturar
min-widthemax-widthsem critério. As regras se sobrepõem em faixas inesperadas e ninguém sabe qual vale em 800 pixels. - Escrever a base e testar só no desktop. A versão estreita fica com aparência de desktop cortado, e você só descobre pelo cliente.
- Pontos de quebra copiados de um aparelho específico. O layout quebra em larguras que ninguém testou, entre um aparelho e outro.
- Esconder conteúdo importante no celular com
display: none. Quem acessa pelo telefone, muitas vezes a maioria, fica sem a informação. - Largura fixa em pixel na base. Um único elemento de 400 pixels cria rolagem lateral na página inteira em telas de 360.
- Esquecer a meta tag de viewport. O celular renderiza como desktop reduzido e a base mobile nunca aparece.
Checklist
- As regras fora de media query deixam a página completa a 360 pixels de largura.
- As media queries de layout usam
min-width. - Nenhuma regra dentro de media query só desfaz outra.
- Os pontos de quebra foram escolhidos olhando o conteúdo.
- Não há rolagem horizontal em nenhuma largura entre 320 e 1920 pixels.
- Botões e links de navegação têm área de toque perto de 44 por 44 pixels.
- A ação principal da página aparece sem rolar demais no celular.
Alargue a janela devagar, de 320 pixels até a tela cheia, observando a página. Em algum ponto o layout fica estranho antes da próxima query entrar? E abra a página no seu telefone antes do monitor: a ação mais importante dela aparece sem você procurar?
Referência: https://www.todoespacoonline.com/w/2015/03/como-escrever-seu-css-para-projetos-mobile-first/