Menu

Media queries CSS: breakpoints, min-width e max-width

Uma media query aplica CSS só quando uma condição é verdadeira, como uma largura mínima de tela, um esquema de cores escuro ou um ponteiro de mouse. Veja a sintaxe do @media, breakpoints mobile first, a sintaxe de intervalo, prefers-color-scheme, matchMedia no JavaScript e container queries.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Uma media query em um exemplo

Uma media query envolve o CSS em uma condição. As regras dentro de @media (min-width: 600px) só valem enquanto a viewport tem pelo menos 600px de largura:

A prévia é um frame, e uma media query dentro dele mede o frame, não a sua tela. No desktop ele tem mais ou menos a largura desta coluna de artigo, normalmente mais de 600px, então a caixa fica azul. Deixe a janela do navegador estreita o bastante para o frame ficar abaixo de 600px e ela fica âmbar; a linha embaixo da caixa mostra a largura do frame ao vivo. No celular o frame já é estreito, então você vê a versão âmbar.

A sintaxe do @media

@media (min-width: 600px) { ... }                        /* one condition */
@media (min-width: 600px) and (max-width: 899px) { ... } /* both must be true */
@media (max-width: 599px), print { ... }                 /* either one (comma = or) */
@media not print { ... }                                 /* negation */
@media screen and (orientation: landscape) { ... }       /* media type plus a feature */
@media (width >= 600px) { ... }                          /* range syntax */
@media (600px <= width < 900px) { ... }                  /* a range with both ends */

O and precisa de um espaço dos dois lados: (min-width: 600px)and(max-width: 900px) é inválido e a query inteira é ignorada. A sintaxe de intervalo (width >= 600px) é suportada nas versões atuais de Chrome, Firefox e Safari e fica mais clara que min-width, principalmente para "até, mas sem incluir".

As características que você mais vai usar:

CaracterísticaBate quandoExemplo
min-width / width >=a viewport tem pelo menos essa largura(min-width: 768px)
max-width / width <=a viewport tem no máximo essa largura(max-width: 767px)
orientationportrait (mais alta que larga) ou landscape(orientation: landscape)
hovero ponteiro principal consegue fazer hover (hover) ou não (none, a maioria das telas de toque)(hover: hover)
pointero ponteiro principal é fine (mouse) ou coarse (dedo)(pointer: coarse)
prefers-color-schemeo usuário escolheu um tema dark ou light(prefers-color-scheme: dark)
prefers-reduced-motiono usuário pediu ao sistema menos movimento(prefers-reduced-motion: reduce)
print (um tipo de mídia)a página é impressa ou salva como PDF@media print

Mobile first: breakpoints com min-width

Escreva o layout do celular como CSS base e depois acrescente queries min-width que mudam o layout conforme o espaço cresce. Cada query só precisa descrever o que muda:

Em uma janela larga de desktop, a prévia tem mais de 720px, então você vê três colunas; a linha embaixo do grid mostra a largura e a quantidade de colunas. Estreite a janela e ela cai para duas abaixo de 720px e para uma abaixo de 480px. A ordem das duas queries importa: as duas são verdadeiras em uma tela larga, e a posterior vence, então queries min-width vão da menor para a maior. (Com queries max-width é o contrário: a maior primeiro.)

Escolher breakpoints

Não existe lista oficial. Estes são valores comuns e o que eles costumam separar:

BreakpointNormalmente
min-width: 640pxcelulares grandes na horizontal, tablets pequenos
min-width: 768pxtablets na vertical
min-width: 1024pxtablets na horizontal, notebooks pequenos
min-width: 1280pxdesktops

Um método melhor: comece pelo layout estreito, alargue a janela até algo ficar ruim (linhas longas demais, cards largos demais) e ponha um breakpoint ali. Dois ou três breakpoints bastam para a maioria das páginas. Muitas vezes você não precisa de nenhum: repeat(auto-fit, minmax(200px, 1fr)) no grid, flex-wrap e clamp() se adaptam de forma contínua.

Toda página precisa da meta tag viewport

Sem esta tag no <head>, os navegadores de celular montam a página como se a tela tivesse uns 980px de largura e depois dão zoom out, então a sua query min-width: 480px é sempre verdadeira e o layout de celular nunca aparece:

<meta name="viewport" content="width=device-width, initial-scale=1">

A página da meta viewport explica cada valor dela.

Modo escuro com prefers-color-scheme

prefers-color-scheme segue a configuração clara ou escura do sistema operacional. O jeito mais limpo de usá-la é guardar as cores em variáveis CSS e mudar só as variáveis dentro da query:

Nesta prévia, a consulta pode mostrar false mesmo com o sistema no modo escuro: o Chrome não repassa a preferência do sistema para um frame com sandbox como este. O botão troca as mesmas variáveis na mão, que é como funciona o seletor de tema de um site. :root[data-theme] é mais específico que o :root simples dentro da consulta, então a escolha do leitor vence a do sistema. Salve o exemplo como arquivo e abra para ver a consulta seguir o seu sistema.

O script mostra a segunda metade das media queries: matchMedia() roda a mesma query pelo JavaScript, diz se ela bate agora e dispara um evento change quando a resposta muda. Use isso quando o comportamento (e não só o estilo) depende da tela, como abrir um menu de outro jeito em dispositivos de toque.

O movimento funciona do mesmo jeito. Envolva animações grandes ou em loop em uma verificação de prefers-reduced-motion, como mostra a página de animação.

Container queries: quando o componente deve decidir

Uma media query só conhece a viewport. Um card que fica em uma coluna principal larga e em uma barra lateral estreita na mesma página precisa conhecer o próprio espaço. Isso é uma container query: marque o pai com container-type: inline-size e depois use @container com as mesmas condições.

Arraste o canto da caixa cinza para redimensioná-la. O card muda de layout em 360px de largura da caixa, seja qual for o tamanho da janela:

Nos 480px iniciais, a imagem fica ao lado do texto. Arraste a caixa para menos de 376px (360px de conteúdo mais 8px de padding de cada lado) e a imagem passa para cima do texto. Container queries funcionam em todos os principais navegadores atuais.

Estilos para impressão

@media print só vale quando a página é impressa ou salva como PDF. Esconda a navegação e os botões e use texto escuro sobre branco:

@media print {
  nav, .ad, button { display: none; }
  body { color: black; background: white; }
  a::after { content: " (" attr(href) ")"; } /* print the URL after each link */
}

Erros comuns

  • Sem a meta tag viewport. Os celulares informam uma viewport de layout larga e as queries de tela pequena nunca batem.
  • Queries na ordem errada. Duas queries verdadeiras com o mesmo seletor: a posterior vence. Ordene as queries min-width da menor para a maior.
  • Limites que se sobrepõem ou deixam buracos. max-width: 768px e min-width: 768px batem as duas em exatamente 768px. Use 767px em uma delas, ou a sintaxe de intervalo (width < 768px) e (width >= 768px).
  • Sem espaço depois do and. and( é inválido e a query é descartada sem aviso.
  • Testar só redimensionando uma janela de desktop. Confira também em um celular de verdade ou no modo dispositivo do navegador, que aplica a viewport, a densidade de pixels e o toque do celular.
  • Breakpoints demais. Se cada componente precisa dos próprios, experimente grid auto-fit, flex-wrap ou container queries.

Perguntas frequentes

O que é uma media query no CSS?

Uma regra que aplica o CSS de dentro dela só quando uma condição sobre o dispositivo ou a janela é verdadeira. @media (min-width: 600px) { ... } aplica os estilos só quando a viewport tem pelo menos 600px de largura, e é assim que uma página se adapta do celular ao desktop.

Devo usar media queries com min-width ou max-width?

A maioria dos sites é escrita mobile first: o CSS base é para telas pequenas e as queries min-width acrescentam layout conforme a tela cresce. Queries max-width funcionam ao contrário, partindo do layout de desktop. Os dois funcionam; misturar os dois no mesmo elemento gera sobreposições e buracos nos limites.

Quais são os breakpoints padrão de media query?

Não existe um padrão oficial. Escolhas comuns ficam perto de 640px, 768px, 1024px e 1280px, mas a regra melhor é acrescentar um breakpoint onde o seu próprio layout começa a ficar ruim e manter poucos breakpoints.

Por que minha media query não funciona no celular?

A causa mais comum é a falta da meta tag viewport. Sem <meta name="viewport" content="width=device-width, initial-scale=1">, os navegadores móveis fingem que a página tem uns 980px de largura, e as queries de largura pequena nunca batem. Confira também se a query vem depois das regras que ela sobrescreve.

Como escrever uma media query para o modo escuro?

Use @media (prefers-color-scheme: dark) { ... }. Ela bate quando o sistema operacional ou o navegador do usuário está com tema escuro, e dentro dela você pode sobrescrever cores ou variáveis CSS.

Qual a diferença entre media queries e container queries?

Uma media query testa a viewport (a janela inteira). Uma container query, escrita com @container, testa o tamanho de um elemento pai que você marca com container-type: inline-size. Use container queries em um componente que aparece em lugares largos e estreitos na mesma página.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR