Artigo original: The 100% correct way to do CSS breakpoints

Escrito por: David Gilbertson

Pelos próximos minutos, quero que você esqueça o CSS, esqueça o desenvolvimento para a web e esqueça as interfaces digitais de usuário.

À medida que você esquece essas coisas, quero que permita sua mente vagar. Voltar no tempo. De volta à sua juventude. De volta ao seu primeiro dia de escola.

Era um tempo mais simples, quando tudo com o que você precisava se preocupar era com desenhar formas e manter sua incontinência sob controle.

1_XoDgRc5GXaxo7j47ClsIgw

Dê uma olhada nos pontos acima. Percebe como alguns deles estão agrupados e outros estão espalhados? O que eu quero que você faça é dividi-los em cinco grupos para mim, da maneira que achar melhor.

Vá em frente. Após verificar que ninguém está olhando, desenhe um círculo ao redor de cada um dos cinco grupos com seu dedinho infantil.

Você, provavelmente, chegou a algo semelhante ao que está abaixo, certo? Seja o que for que você fizer, não me diga que rolou a página sem fazer o exercício. 😒

1_cZcTR2tVMzYg1U1h3cqdNg

Claro, aqueles dois pontos à direita poderiam ir para qualquer um dos lados. Se você os agrupou juntos, tudo bem, eu acho. Dizem que não há resposta errada, mas eu nunca estive errado, então nunca estive do lado receptor desse ditado específico.

Antes de continuar, você desenhou algo assim?

1_RZryP0xAyOy1_WRpBdPIog

Provavelmente, não, certo?

É basicamente isso que você estaria fazendo se definisse seus breakpoints em posições correspondentes à largura exata dos dispositivos populares (320px, 768px, 1024px).

1_pwC0py16i-sQr1agaP26QQ

Já ouviu ou disse algo do tipo?

"O breakpoint médio vai até 768px, ou inclui 768? Entendi... e isso é o modo paisagem do iPad, ou 'grande'? Ah, grande é de 768px e acima. Entendi. E pequeno é 320px? O que é essa faixa de 0 a 319px? Um breakpoint para formigas?"

Eu poderia seguir em frente e mostrar os breakpoints corretos e deixar por isso mesmo, mas acho muito curioso que o método acima ("agrupamento bobo") seja tão disseminado.

Por que isso acontece?

Acho que a resposta para esse problema, como tantos outros problemas, se resume a terminologia desalinhada.

Acho que confundimos "limites" e "faixas" em nossas discussões e implementações de breakpoints.

Me diga, se você faz breakpoints no Sass, você tem uma variável chamada $large que é, digamos, 768px?

É o limite inferior da faixa que você chama de grande, ou o limite superior? Se for o inferior, então você não deve ter $small porque o valor deste deveria ser 0, certo?

Se for o limite superior, então como você definiria um breakpoint $extra-large? Deve ser uma consulta de mídia com um min-width de $medium, certo?

Se você estiver se referindo apenas a um limite quando diz grande, então teremos confusão mais tarde porque uma consulta de mídia é sempre uma faixa.

Essa situação é uma bagunça e estamos perdendo tempo pensando nisso. Então, tenho três sugestões:

  1. Obtenha seus breakpoints corretamente
  2. Nomeie suas faixas de maneira sensata
  3. Seja declarativo

Dica nº 1: obtenha seus breakpoints corretamente

Então, quais são os breakpoints corretos?

Seu "eu" de jardim de infância já desenhou os círculos. Eu apenas os transformarei em retângulos para você.

1_-ldpo5wcYVnuyRFbO24WPQ
600px, 900px, 1200px e 1800px, se você planeja dar algo especial para as pessoas com monitores gigantes.

Aqueles pontos com os quais seu "eu" jovem se divertiu representam na verdade os 14 tamanhos de tela mais comuns:

1_199KbL2oM2P5d4pFMBXYxQ
Crédito da imagem: http://gs.statcounter.com/#desktop+mobile+tablet-resolution-ww-monthly-201608-201610-bar

Então, podemos fazer uma imagem bonita que permita o fácil fluxo de palavras entre as pessoas vestidas como empresários, designers, desenvolvedores e testadores.

1_7YeOvzoYgUEDJdfQy2ERXg--1-
Estou arrependido de minha escolha de laranja e verde, mas não vou refazer todas essas imagens agora.

Dica nº 2: nomeie suas faixas de maneira sensata

Claro, você poderia nomear seus breakpoints de papai urso e bebê urso, se quiser. Se eu for me sentar com um designer, porém, e discutir como o site deve parecer em dispositivos diferentes, quero que seja o mais rápido possível. Se nomear um tamanho de tablet em retrato facilita isso, então ótimo. Aliás, até perdoaria você por chamar de "iPad em retrato".

O CSS do seu site, porém, tem uma vida útil de cerca de três anos (a menos que seja o Gmail). O iPad está conosco há o dobro desse tempo e ainda não foi destronado. Sabemos que a Apple não faz mais novos produtos, eles apenas removem coisas dos existentes (botões, buracos etc).

Então, o 1024 x 768 veio para ficar, pessoal. Vamos não enterrar nossas cabeças na areia. Fato curioso: avestruzes não vivem em cidades porque não há areia e, portanto, nenhum lugar para se esconder dos predadores.

Conclusão: a comunicação é importante. Não se desligue propositalmente de vocabulário útil.

Dica nº 3: seja declarativo

Eu sei, eu sei, essa palavra "declarativo" de novo. Vou colocar de outra maneira: seu CSS deve definir o que ele quer que aconteça, não como deve acontecer. O "como" deve ficar escondido em algum tipo de mixin.

Como discutido anteriormente, parte da confusão em torno dos breakpoints é que as variáveis que definem um limite de um intervalo são usadas como o nome do intervalo. $large: 600px simplesmente não faz sentido se large é um intervalo. É o mesmo que dizer var coordenadas = 4;.

Podemos esconder esses detalhes dentro de um mixin em vez de expô-los para serem usados no código. Podemos fazer melhor e não usar variáveis de todo.

No início, eu fiz o trecho abaixo como um exemplo simplificado. Eu realmente acho que cobre todos os aspectos. Para vê-lo em ação, veja este pen. Estou usando Sass porque não consigo imaginar construir um site sem ele. A lógica se aplica ao CSS ou Less da mesma maneira.

@mixin for-phone-only {
  @media (max-width: 599px) { @content; }
}
@mixin for-tablet-portrait-up {
  @media (min-width: 600px) { @content; }
}
@mixin for-tablet-landscape-up {
  @media (min-width: 900px) { @content; }
}
@mixin for-desktop-up {
  @media (min-width: 1200px) { @content; }
}
@mixin for-big-desktop-up {
  @media (min-width: 1800px) { @content; }
}

// uso
.my-box {
  padding: 10px;

  @include for-desktop-up {
    padding: 20px;
  }
}
Observe que estou forçando o desenvolvedor a especificar os sufixos -up ou -only.
A ambiguidade gera confusão.

Uma crítica óbvia pode ser que isso não lida com media queries personalizadas. Bem, boas notícias, pessoal. Se você quiser uma media query personalizada, escreva uma media query personalizada. Na prática, se eu precisasse de mais complexidade do que o acima, cortaria minhas perdas e correria para o abraço amoroso do kit de ferramentas Susy.

Outra crítica pode ser que eu tenho oito mixins aqui. Com certeza um único mixin seria a decisão mais sensata, para então passar o tamanho necessário, assim:

@mixin for-size($size) {
  @if $size == phone-only {
    @media (max-width: 599px) { @content; }
  } @else if $size == tablet-portrait-up {
    @media (min-width: 600px) { @content; }
  } @else if $size == tablet-landscape-up {
    @media (min-width: 900px) { @content; }
  } @else if $size == desktop-up {
    @media (min-width: 1200px) { @content; }
  } @else if $size == big-desktop-up {
    @media (min-width: 1800px) { @content; }
  }
}

// uso
.my-box {
  padding: 10px;

  @include for-size(desktop-up) {
    padding: 20px;
  }
}

Claro, funciona. Porém, você não terá erros em tempo de compilação se passar um nome não suportado. Passar uma variável sass significa expor 8 variáveis só para passar para um switch em um mixin.

Sem mencionar que a sintaxe @include for-desktop-up {...} é muito mais bonita do que @include for-size(desktop-up) {...}.

Uma crítica de ambos esses trechos de código pode ser que estou digitando 900px duas vezes, e também 899px. Certamente eu deveria apenas usar variáveis e subtrair 1 quando necessário.

Se você quiser fazer isso, sinta-se à vontade, mas há duas razões pelas quais eu não o faria:

  1. Estas não são coisas que mudam frequentemente. Também não são números que são usados em outro lugar na base de código. Nenhum problema é causado pelo fato de que eles não são variáveis — a menos que você queira expor seus pontos de interrupção Sass para um script que injeta um objeto JS com essas variáveis na sua página.
  2. A sintaxe é horrível quando você quer transformar números em strings com Sass. Abaixo está o preço que você paga por acreditar que repetir um número duas vezes é o pior de todos os males:
@mixin for-size($range) {
  $phone-upper-boundary: 600px;
  $tablet-portrait-upper-boundary: 900px;
  $tablet-landscape-upper-boundary: 1200px;
  $desktop-upper-boundary: 1800px;

  @if $range == phone-only {
    @media (max-width: #{$phone-upper-boundary - 1}) { @content; }
  } @else if $range == tablet-portrait-up {
    @media (min-width: $phone-upper-boundary) { @content; }
  } @else if $range == tablet-landscape-up {
    @media (min-width: $tablet-portrait-upper-boundary) { @content; }
  } @else if $range == desktop-up {
    @media (min-width: $tablet-landscape-upper-boundary) { @content; }
  } @else if $range == big-desktop-up {
    @media (min-width: $desktop-upper-boundary) { @content; }
  }
}

// uso
.my-box {
  padding: 10px;

  @include for-size(desktop-up) {
    padding: 20px;
  }
}

Ah, e já que adotei um tom de desabafo nos últimos parágrafos... eu sinto pena do tolo que faz algo mágico como armazenar breakpoints em uma lista do Sass e iterar sobre eles para gerar consultas de mídia, ou algo igualmente ridículo que futuros desenvolvedores terão dificuldade em decifrar.

Finalmente, você pode estar pensando "eu não deveria estar baseando meus pontos de interrupção no conteúdo, e não nos dispositivos?". Bem, estou maravilhado que você tenha chegado até aqui e a resposta é sim... para sites com um layout único. Ou se você tiver múltiplos layouts e estiver feliz em ter um conjunto diferente de breakpoints para cada layout. Ah, e também se o design do seu site não mudar com frequência, ou se você estiver feliz em atualizar seus breakpoints quando seus designs forem atualizados, já que você vai querer mantê-los baseados no conteúdo, certo?

Para sites complexos, a vida é muito mais fácil se você escolher alguns pontos de interrupção para usar em todo o site.

Terminamos! Este artigo não foi tão cheio de bichinhos quanto eu gostaria que fosse – deixe-me ver se consigo pensar em uma desculpa para incluir alguns...

Ah, já sei!

Dicas bônus para o desenvolvimento de breakpoints

1_ClU6ZZNLtd0ux8nqRPfhng
Sim, até mesmo o Flickr tem pontos de interrupção em 768 e 1400
  1. Se você precisar experimentar com breakpoints de CSS para tamanhos de tela maiores do que o monitor que você está usando, utilize o modo 'responsivo' nas ferramentas de desenvolvedor do Chrome e digite qualquer tamanho gigante que você quiser.
  2. A barra azul mostra media queries com "largura máxima" (max-width), a barra laranja mostra media queries com "largura mínima" (min-width), e a barra verde mostra media queries com tanto uma largura mínima quanto uma máxima.
  3. Clicar em uma media query ajusta a largura da tela para aquela largura. Se você clicar em uma media query verde mais de uma vez, ela alterna entre as larguras máxima e mínima.
  4. Clique com o botão direito em uma media query na barra de media queries para ir à definição dessa regra no CSS.

Ei, agradeço a leitura! Compartilhe o artigo, se acha que eu mereço, ou deixe ele no esquecimento, como ficará minha autoestima se você não o compartilhar. 😳