Tailwind responsivo: sm, md, lg e o jeito mobile-first
Por que md:flex significa a partir de 768px, como usar max-lg: para o caminho inverso e quando a container query resolve melhor que o breakpoint.
No Tailwind, uma classe sem prefixo vale em todas as larguras; md:* sobrescreve
ou acrescenta estilo a partir de 48rem. Mobile-first não quer dizer desenhar só
para celular. Quer dizer começar pela restrição comum e adicionar capacidade
quando existe espaço.
O componente desta lição é o resumo de consulta. Ele começa empilhado e vira duas colunas. As duas estratégias foram compiladas no mesmo diretório para medir o custo concreto.
Sem prefixo é a base, não “desktop”
Este cartão é coluna no menor espaço e linha a partir de md:
<article class="flex flex-col gap-4 p-4 md:flex-row md:gap-6 md:p-8">
<div>Dados do paciente</div><div>Resumo financeiro</div>
</article>O compilador agrupa as substituições numa media query de largura mínima:
@media (width >= 48rem) {
.md\:flex-row { flex-direction: row; }
.md\:gap-6 { gap: calc(var(--spacing) * 6); }
.md\:p-8 { padding: calc(var(--spacing) * 8); }
}sm: não significa “tela pequena”. Significa “a partir do breakpoint sm”,
40rem no tema padrão. Para o menor tamanho, escreva a classe sem prefixo.
Cinco breakpoints, nenhum modelo de aparelho
Os padrões são sm 40rem, md 48rem, lg 64rem, xl 80rem e 2xl 96rem.
Eles descrevem faixas de layout, não marcas de telefone ou tablet.
<section class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
...
</section>Escolha o ponto em que o conteúdo deixa de caber. Se o nome de um botão quebra
antes de 48rem, não espere md por tradição. Ajuste a estrutura ou crie um
breakpoint de tema baseado naquele conteúdo.
max-* aplica um teto
Às vezes você precisa corrigir um componente legado escrito desktop-first.
max-md:* vale abaixo de md.
<article class="flex flex-row gap-6 p-8 max-md:flex-col max-md:gap-4 max-md:p-4">
...
</article>No teste controlado, a versão mobile-first compilou para 4.456 bytes e a versão desktop-first para 4.480 bytes. As duas produziram uma media query. A diferença de 24 bytes é pequena; a vantagem principal de mobile-first é raciocínio e cascata, não uma promessa de performance.
wc -c mobile.out.css desktop.out.cssUm intervalo combina mínimo e máximo
Empilhe md:max-lg: para atingir uma faixa. A ordem dos prefixos descreve as
condições que envolvem a utilidade.
<aside class="hidden md:max-lg:block">Resumo compacto</aside>O CSS medido colocou o máximo dentro do mínimo:
@media (width >= 48rem) {
@media (width < 64rem) {
.md\:max-lg\:block { display: block; }
}
}Não escreva md:lg:flex; dois mínimos empilhados só dizem que o maior vence e
escondem intenção. Use lg:flex ou um intervalo explícito.
Breakpoint é token de tema
Você pode criar ou sobrescrever uma fronteira no @theme:
@theme {
--breakpoint-xs: 30rem;
--breakpoint-3xl: 120rem;
}<div class="grid grid-cols-1 xs:grid-cols-2 3xl:grid-cols-6">...</div>Mantenha as unidades consistentes. Misturar px e rem pode produzir ordenação inesperada das variantes. Rem também acompanha melhor preferências de tamanho de texto no navegador.
Container query responde ao lugar onde o componente vive
Um cartão pode aparecer numa sidebar estreita dentro de uma tela enorme. Nesse
caso, a viewport é o sinal errado. Marque um ancestral com @container e use
variantes @md:*.
<aside class="@container">
<article class="flex flex-col @md:grid @md:grid-cols-2">
<div>Paciente</div><div>Horário</div>
</article>
</aside>@container (width >= 28rem) {
.\@md\:grid { display: grid; }
.\@md\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}Use query de container para comportamento interno reutilizável e breakpoint de viewport para a composição da página. A lição de Grid mostra um auto-fit que resolve outro pedaço do mesmo problema sem prefixos.
Estado e largura podem trabalhar juntos
Variantes empilham: md:hover:* significa hover apenas a partir de md.
Pergunte se a condição faz sentido em dispositivos que não oferecem hover.
<a class="underline md:no-underline md:hover:underline" href="#agenda">
Abrir agenda
</a>Para foco, não restrinja o sinal à largura. focus-visible:* deve funcionar em
qualquer viewport. Estados completos estão em
hover e focus no Tailwind.
Erro reproduzido: breakpoint que não foi declarado
O prefixo desktop: não nasce por convenção. Sem um breakpoint com esse nome,
o CLI 4.3.3 rejeitou a variante:
@import "tailwindcss";
.qa { @apply desktop:grid; }printf '@import "tailwindcss"; .qa { @apply desktop:grid; }\n' | npx @tailwindcss/cli@4.3.3 -i - -o /dev/nullO processo encerrou com código 1. Use um breakpoint existente, como lg:, ou
declare --breakpoint-desktop no tema antes de usar o prefixo.
Teste conteúdo, não só três números
Eu uso 320px para pressão extrema, 768px para transição e 1440px para verificar limites máximos, mas também arrasto lentamente entre eles. O bug costuma morar em 873px, onde ninguém tirou screenshot. Aumente o texto para 200%, use um nome longo e abra o teclado virtual.
Se você escolhe breakpoints pelo conteúdo, a interface suporta aparelhos que ainda nem existem. A base de media queries em CSS ajuda a entender o mecanismo que as variantes geram.
Missão com duas implementações
Escreva o resumo da consulta primeiro mobile-first e depois desktop-first com
max-md. Compile os dois em fontes isoladas, compare tamanho e media queries e
escolha qual leitura deixa o estado base mais óbvio. Em seguida, coloque o mesmo
cartão numa sidebar e troque viewport por @container. A missão termina quando
o componente responde ao espaço que realmente recebe.
Registre comportamento, não nomes de aparelho
Uma documentação útil diz “a partir de 48rem, o preço cabe ao lado da descrição sem quebrar a ação”. Dizer “layout de tablet” não informa qual conteúdo motivou a mudança e envelhece quando o componente vai para uma sidebar. Registre estado antes, condição e estado depois.
Faça uma matriz curta com viewport estreita e larga, container estreito e largo, texto normal e ampliado. Um componente com query própria deve reagir ao container mesmo quando a viewport permanece igual. Se a mudança depende das duas dimensões, documente a prioridade em vez de acumular prefixos.
Teste orientação e teclado virtual. A altura disponível cai sem que a largura necessariamente atravesse um breakpoint. Menus fixos, diálogos e formulários precisam lidar com esse espaço sem cortar botões. Use rolagem no conteúdo apropriado e preserve a ação alcançável.
Por fim, compile e leia as media queries na ordem final. Uma variável de breakpoint com unidade inconsistente pode ordenar condições de modo inesperado. O guia da trilha posiciona essa revisão antes de estados e tema porque toda interação precisa funcionar nas mesmas faixas.
Salve a matriz junto do componente e atualize-a quando o conteúdo ou os tokens mudarem. Breakpoint correto hoje pode ficar cedo ou tarde depois de uma troca de fonte.
Dúvidas e comentários
Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.
Entrar para perguntarÉ o mesmo login gratuito dos cursos.
Nenhuma dúvida por aqui ainda — a primeira pode ser a sua.
Todo o código deste artigo foi executado em @tailwindcss/cli 4.3.3 no Node 26.3.0, e as saídas exibidas são as reais — como produzimos este conteúdo.
Fontes consultadas
- Tailwind CSS — Responsive design — tailwindcss.com
- MDN — CSS container queries — developer.mozilla.org


