Em seu antológico artigo, Responsive Web Design, Ethan Marcotte definiu que os 3 pilares de web design responsivo são:
- Layout fluido
- Imagens flexíveis
- Media queries
Talvez não tenha sido exatamente com estes termos, mas esses 3 pré-requisitos são, fundamentalmente, o que compõe responsive web design.
Este artigo foca no terceiro pontos, as media queries, mostrando o básico que é preciso saber para construir uma base sólida para a responsividade na Web.
Media types
Antes mesmo dessa história toda de web design responsivo, já existiam media types. Inclusive, tecnicamente, media queries são media types.
Há não mais que 1 década atrás, não era incomum encontrar algo parecido com:
1 |
<link rel="stylesheet" href="print.css" media="print"> |
Quer dizer, este CSS só entra em ação, só modifica os estilos do site, quando se tratar de impressão. print
é um tipo de media
; um media type.
No passado, contávamos com diversos media types, mas, com o tempo, com a evolução dos dispositivos, a distinção clara entre determinados tipos já não era mais possível, fazendo com que a distinção entre os diversos tipos de mídia começasse a ficar insuficiente — por exemplo, a diferença entre screen
and handheld
.
Para o desenvolvimento responsivo moderno, pode-se considerar que os media types disponíveis são:
screen
. Telas ou todos que não são consideradosprint
ouspeech
;print
. Dispositivos de impressão (e visualização de impressão no browser);speech
. Sintetizadores de fala;all
. Todos os dispositivos. Se, em uma media query, o media type for omitido, all é considerado implicitamente.
Lembrando que também é possível, nas próprias definições de estilo em arquivos .css
, especificar media types e fornecer estilo próprio, como em:
1 2 3 4 5 6 7 |
@media print { header, footer, aside { display: none; } } |
Quer dizer, somente no momento da impressão, cabeçalhos, rodapés e asides não aparecerão.
Media features
Media features também servem para testar se uma condição é verdade, mas, ao invés de testarem meios, testam características. Em outras palavras, uma media feature testa uma feature única, específica, de um dado User Agent (UA) ou dispositivo.
E a lista do que se pode testar é grande (e continua crescendo). Para saber de somente alguns exemplos:
width
height
orientation
pixel-density
aspect-ratio
prefers-color-scheme
É possível consultar a lista completa de media features.
Media queries
Agora que você sabe da diferença entre media types e media features, fica mais fácil de deduzir e entender o que são media queries.
Uma media query consiste em uma consulta (query) que testa por medias e features, ou seja, é uma consulta que testa o meio e as características desse meio para, condicionalmente, aplicar determinados estilos.
Em outras palavras, uma media query é um teste que envolve media types e media features.
Uma media query desta natueza:
1 |
@media screen and (min-width: 30em) {} |
Está testando o type screen
e a feature min-width: 30em
. Somente se ambos forem verdadeiros, quer dizer, se o acesso estiver sendo feito por um dispositivo com tela e a largura da viewport tiver, pelo menos, 30em
, os estilos ali especificados entrarão em ação.
Mas e aquele and
ali? Pois é. Existem maneiras de refinar as medias queries através de operadores lógicos.
Operadores lógicos de media queries
Se você tem algum background de programação, operadores lógicos de media queries será um tópico bem fácil de entender. Na verdade, mesmo se você não tiver, não há dificuldade alguma.
Para começar, lembre-se do seguinte: operadores lógicos podem ser usados para compor media queries mais complexas — e, por consequência, mais eficientes.
Basicamente, é possível trabalhar com 4 tipos de operadores lógicos: and
, or
, not
e only
.
and
O operador lógico and
é usado para combinar múltiplas media features e media features com media types.
Talvez seja o mais comum de se encontrar, como no exemplo:
1 |
@media (min-width: 75em) and (orientation: landscape) {} |
No exemplo, and
é usado para testar se há determinada largura mínima e se a orientação da viewport é landscape — “paisagem”, ou seja, sua largura é maior que sua altura.
E, se você está prestando atenção a todas nossas explicações sobre media queries, sabe que algo mais está sendo testado…
Acima, foi dito que o media type all
é implícito quando não há referência a media types. Então, na verdade, o código acima é equivalente a:
1 |
@media all and (min-width: 75em) and (orientation: landscape) {} |
E o desenrolar disso é que você estava usando um media type mesmo sem saber! Mesmo a mais simples das media queries, como:
1 |
@media (min-width: 30em) {} |
Implicitamente, é:
1 |
@media all and (min-width: 30em) {} |
Na prática, você sempre está testando um media type, mesmo que não deixe isso explícito em sua media query.
Lembrando: media queries testam media types e media features. Então, você pode usar qualquer combinação delas para compor uma media querie eficiente, que dê o match exatamente no caso de uso necessário.
1 |
@media (min-width: 37.5em) and (orientation: landscape) {} |
E assim por diante.
or
Não existe uma palavra-chave or
para compor media queries, mas, na prática, seu efeito é conseguido usando ,
(vírgula).
Seu efeito pode ser interpretado como: se qualquer consulta (query) for verdadeira, os estilos serão aplicadas. Perceba que é bem diferente de and
, que entra ação se todas as consultas forem verdadeiras.
Por exemplo:
1 |
@media (min-width: 56.25em), print and (orientation: landscape) {} |
Traduzindo: a media query será válida se a largura mínima da viewport for 56.25em
ou se o media type for print
e sua orientação landscape
.
Como visto, usar and
e or
na mesma media query confere possibilidades interessantes para especificar precisamente quando determinadas regras CSS devem entrar em ação.
not
O operador lógico not
, tal como em linguagens de programação, nega o que está sendo declarado. Se for mais fácil de entender, é como se ele invertesse a assertiva.
Algo importantíssimo a ser lembrado:
Por exemplo:
1 |
@media not all and (monochrome) {} |
Você vai se frustrar se estiver pensando que isso é interpretado como:
1 |
@media (not all) and (monochrome) {} |
Ao invés disso, essa media query é interpretada como:
1 |
@media not (all and (monochrome)) {} |
Ou seja, como informado, negando toda a query; não somente partes dela.
Um cuidado especial é quando estiver usando ,
para compor media queries junto com o not
. Neste tipo de caso, a negação vai até a vírgula.
Esta media query:
1 |
@media not screen and (color), print and (color) {} |
É interpretada da seguinte maneira:
1 |
@media (not (screen and (color))), print and (color) {} |
A princípio, uma sutil diferença, mas que, na maioria dos casos em que not
é usado, gera resultados completamente diferentes.
only
Se você é como a gente e prioriza desenvolvimento web moderno, então não é preciso muita atenção ao operador lógico only
.
Mas, para se saber, ele previne que navegadores antigos, que não suportam media queries com media features, apliquem os estilos do match.
Por exemplo:
1 |
@media only screen and (color) {} |
Atualmente, você pode escrever o mesmo somente retirando o only
e o match vai acontecer para qualquer navegador moderno.
Conclusão
Então, este foi o básico sobre media queries.
Agora você já sabe que uma media query é composta por um media type e uma media feature (mesmo que o type seja implícito).
Também, que é possível usar diferentes operadores lógicos para compor media queries muito mais poderosas e precisas.
Com este básico, você já está apto a escrever media queries bem melhores e, o mais importante, com mais consciência do que está fazendo.
Mas diz aí: qual foi a media query mais complexa que você já teve que usar? Coloca aí nos comentários, explicando porquê teve que usá-la.