Media Queries

Como fazer com que páginas HTML tenham diferentes comportamentos e formatações, de acordo com as características do dispositivo no qual estão sendo visualizadas.

Um mesmo site é aberto em celulares, tablets, monitores enormes, impressoras e até em aparelhos com o modo escuro ligado. As Media Queries são a ferramenta do CSS para lidar com isso: elas aplicam estilos somente quando o dispositivo atende a determinadas condições, como a largura da tela, a orientação ou as preferências do usuário.

Antes de tudo: a meta viewport

Sem esta tag no <head>, o navegador do celular finge ter uma tela de cerca de 980px de largura e reduz a página inteira, e as media queries de largura simplesmente não funcionam como esperado:

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

Onde usar media queries

A forma mais comum é a regra @media dentro do CSS:

@media (max-width: 767px) {
    .menu {
        display: none;
    }
}

Também é possível carregar um arquivo inteiro somente quando a condição for atendida, usando o atributo media do <link>:

<link rel="stylesheet" media="print" href="impressao.css">

E no JavaScript, com window.matchMedia(), que permite reagir quando a condição muda:

const celular = window.matchMedia('(max-width: 767px)');

celular.addEventListener('change', (evento) => {
    console.log(evento.matches ? 'Layout de celular' : 'Layout de desktop');
});

Anatomia de uma media query

@media screen and (min-width: 768px) and (orientation: landscape) { }
/*     └ tipo ┘     └─── condição ───┘     └──── condição ────┘ */

Ela pode ter um tipo de mídia, uma ou mais condições (media features) e operadores lógicos unindo tudo.

Tipos de mídia

Hoje apenas três tipos de mídia têm uso real. O tipo é opcional: quando omitido, a regra vale para todos.

Tipos antigos como handheld, tv, projection, tty, braille, embossed e speech foram descontinuados: os navegadores os ignoram e eles não devem mais ser usados.

Condições de tamanho

São as mais usadas para criar layouts responsivos. O prefixo min- significa "a partir de" e max- significa "até":

As variações device-width, device-height e device-aspect-ratio mediam a tela física em vez da viewport e também foram descontinuadas. Use sempre width e height.

Preferências do usuário

Essas condições respeitam escolhas que a pessoa fez no sistema operacional e são muito importantes para acessibilidade:

:root {
    --fundo: #FFFFFF;
    --texto: #1E2633;
}

@media (prefers-color-scheme: dark) {
    :root {
        --fundo: #1E2633;
        --texto: #E8ECF2;
    }
}

@media (prefers-reduced-motion: reduce) {
    * {
        animation: none !important;
        transition: none !important;
    }
}

Tipo de interação

Largura de tela não diz se o aparelho tem mouse ou touch: existem tablets com teclado e mouse e notebooks com tela sensível ao toque. Para isso existem:

/* Botões maiores em telas touch */
@media (pointer: coarse) {
    .botao {
        min-height: 44px;
    }
}

/* Efeito de hover só onde existe hover de verdade */
@media (hover: hover) {
    .card:hover {
        transform: translateY(-4px);
    }
}

Operadores lógicos

/* telas com 768px ou mais E em modo paisagem */
@media screen and (min-width: 768px) and (orientation: landscape) { }

/* impressão OU telas muito pequenas */
@media print, (max-width: 359px) { }

Sintaxe moderna com comparações

A especificação Media Queries Level 4 trouxe operadores de comparação (<, <=, > e >=), que tornam intervalos mais fáceis de ler. Ela já é suportada por todos os navegadores modernos:

/* clássica */
@media (min-width: 768px) and (max-width: 1023px) { }

/* moderna */
@media (768px <= width <= 1023px) { }

Uma vantagem extra: com < e > não é preciso descontar 1px para evitar que duas regras valham ao mesmo tempo, como em (width < 768px) e (width >= 768px).

Mobile-first na prática

A abordagem mais recomendada é escrever o CSS base para telas pequenas e ir acrescentando regras com min-width conforme a tela cresce. O código fica mais simples, porque o layout de celular costuma ser o mais básico (uma coluna):

.produtos {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
}

/* tablet */
@media (min-width: 768px) {
    .produtos {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* desktop */
@media (min-width: 1024px) {
    .produtos {
        grid-template-columns: repeat(4, 1fr);
    }
}

Sobre os pontos de quebra (breakpoints): em vez de mirar em aparelhos específicos, escolha os valores onde o seu layout começa a quebrar. Os valores 768px e 1024px acima são apenas pontos de partida comuns.

Estilos para impressão

@media print {
    header, nav, footer, .anuncio {
        display: none;
    }

    body {
        color: #000;
        background: #FFF;
    }

    a[href]::after {
        content: " (" attr(href) ")";
    }
}

E as Container Queries?

As media queries olham para a viewport. Quando um componente precisa se adaptar ao espaço do elemento onde está (um card dentro de uma sidebar estreita, por exemplo), use as Container Queries. As duas ferramentas se complementam: media queries para o layout da página, container queries para os componentes.

Gere suas media queries

Para montar as regras sem decorar a sintaxe e testar na hora se elas valem para a sua tela, use o Gerador de Media Query.

Conclusão

Media queries vão muito além de "celular ou desktop": elas permitem adaptar a página ao tamanho da tela, ao tipo de interação, à impressão e às preferências de cada pessoa. Comece pela meta viewport, escreva o CSS mobile-first com min-width e não esqueça de prefers-reduced-motion e prefers-color-scheme para uma experiência mais acessível.

caniuse

Tecnologia:
html

Deixe seu Comentário!

Dúvida, sugestão ou só um "valeu!" — tudo é bem-vindo por aqui.

Comentário
Nome
Email
lock Seu e-mail não será publicado.