Para os próximos 2 ou 3 minutos, esqueça o que é CSS (e o que são breakpoints em CSS); esqueça o que é desenvolvimento para web; esqueça o que são digital user interfaces. E, ao esquecer estas coisas, permita que sua mente vagueie.
Que volte no tempo, para a sua época de escola — aquele tempo mais simples, quando suas maiores preocupações eram desenhar formas e manter sua incontinência sob controle.
Dê uma olhada nessas bolinhas:
Observe como alguns deles estão agrupados e alguns espalhados. Prosseguindo ao exercícios mental, divida-as em 5 grupos e depois desenhe um círculo em torno de cada um destes grupos.
Provavelmente a solução para a questão terá sido algo como isso:
Claro, o grupamento desses 2 pontos à direita poderia ter sido de outra maneira. Na verdade, toda a demarcação também poderia ter sido diferente do “usual”, resultando em algo mais ou menos como:
Parece que desse jeito não ficou muito bom, foi um “agrupamento bobo”… Certo?
Mas isso é basicamente o que 99% dos desenvolvedores front-end fazem para definir breakpoints que correspondem à largura exata de dispositivos populares (320px
, 768px
, 1024px
)!
Palavras mais ou menos como essas já entraram em seus ouvidos ou saíram de sua boca?
O breakpoint “medium” é até 768px ou inclui 768px? E isso é landscape no iPad ou é o breakpoint “large”? Oh, “large” é 768px para cima. O “small” é 320px, certo? De 0 a 319px.
É curioso que o método acima, o “agrupamento bobo”, esteja tão difundido… Mas, então, qual deveria ser a maneira correta de fazer breakpoints em CSS?
Provavelmente a resposta para este problema, como para tantos outros, se resuma a uma terminologia desalinhada. Neste caso específico, misturas indiscriminadas de termos como “limites” (boundaries) e “intervalos” (ranges) nas discussões e implementações de breakpoints.
Fazendo uma suposição, provavelmente você tem uma variável em Sass $large
com o valor de 768px
. Esse é o limite inferior (lower boundary) ou superior (upper boundary) do intervalo (range) conhecido como “large”?
Se for o inferior, então não deve haver $small
, já que ele teria que ser 0
, certo?
E se for o superior, então como foi definido um breakpoint $large-and-up
? Deve ser uma media query com min-width
de $medium
, confere? E se está se referindo a apenas um limite quando se refere a “large”, então haverá confusão mais tarde, porque uma media query é sempre um intervalo (range).
Essa situação é caótica e estamos perdendo tempo pensando nisso. Então aqui vão 3 sugestões:
- Crie breakpoints do jeito certo
- Nomeie breakpoints corretamente
- Seja declarativo
Crie breakpoints do jeito certo
No final das contas, qual é “o jeito certo” para criar breakpoints?
Lembra da divisão das bolinhas em grupos? Basta fazer a coisa direito que se chegará a algo como:
600px
, 900px
, 1200px
e 1800px (se for preciso servir algo especial a pessoas com monitores gigantes).
Essa divisão representada os 14 tamanhos de tela mais comuns:
A partir daí, torna-se possível idealizar um sistema que permita o fluxo fácil de palavras entre pessoas vestidas com ternos, designers, desenvolvedores e testadores:
Nomeie breakpoints corretamente
Evidentemente, você pode nomear seus breakpoints da maneira que quiser, até como papa-bear e baby-bear. Mas, geralmente, quando pessoas de um time de desenvolvimento se sentam para resolver alguma questão, é interessante que os nomes dados não sejam um empecilho. Se nomear um tamanho para um tablet em orientação de retrato facilitar isso, tudo bem — alguns poderiam até chamar isso de… “iPad portrait”.
Mas alguns podem alegar que “o cenário está mudando”. “Telefones estão ficando maiores e tablets menores”.
Acontece que o CSS dos projetos geralmente têm uma vida-média de uns 3 ou 5 anos (a menos que seja o Gmail). O iPad esteve conosco por 2 vezes durante esse tempo e ainda não foi destronado — e sabemos que a Apple já não fabrica novos produtos; simplesmente remove coisas dos existentes (botões, buracos etc.).
Então, para o bem e para o mal, 1024×768 está aqui para ficar. Não vamos enterrar nossas cabeças na areia.
Conclusão: comunicação é importante! Não dispense propositalmente vocabulário útil.
Seja declarativo
Que se entenda por “declarativo” que o CSS deve definir o que ele quer que aconteça e não como isso deve acontecer. O “como” pode ficar implícito em algum tipo de mixin ou coisa assim.
Como discutido anteriormente, parte da confusão sobre breakpoints é que variáveis que definem um limite de um intervalo (boundary of a range) são usadas como o nome do intervalo. $large: 600px
simplesmente não faz sentido se “large” for um intervalo. É o mesmo que declarar var coordinates = 4;
.
Em função disso, é conveniente esconder esse tipo de detalhe dentro de um mixin ao invés de o expor para ser usado no código. Ou, fazendo melhor, sequer usar variáveis.
No começo, o trecho de código abaixo servia apenas como um exemplo simplificado. Mas realmente ele tem potencial para fazer uma boa cobertura de casos. Para vê-lo em ação, confira este pen — o uso de Sass é opcional; a lógica se aplica a qualquer outro pré-processador ou CSS puro exatamente do mesmo jeito.
Perceba que é proposital forçar o uso dos sufixos -up
/-only
. Ambiguidade gera confusão.
Uma crítica óbvia pode ser que isso não lida com media queries personalizadas. Mas há boas novas: se você quiser uma media query personalizada, escreva uma media query personalizada!
Outra crítica pode ser relativa à quantidade de mixins criados. Certamente, um único mixin com o tamanho necessário sendo passado seria o mais sensato a ser feito. Algo assim:
Claro, isso funciona. Mas você não receberá erros em tempo de compilação (compile-time errors) se passar um nome sem suporte. E passar em uma variável Sass significa expor 8 variáveis apenas para passar para um switch
em um mixin — sem mencionar que a sintaxe @include for-desktop-up {...}
é mais bonita do que @include for-size(desktop-up) {...}
.
Ainda uma outra crítica a esses snippets pode ser a repetição de 900px
e também 899px
. Certamente, deveria-se usar apenas variáveis e subtrair 1 quando necessário.
Se quiser fazer isso, vá em frente, mas há 2 razões principais a serem consideradas:
- Essas não são coisas que mudam com frequência. Estes também não são números que são usados em qualquer outro lugar na base de código. Nenhum problema é causado pelo fato de não serem variáveis — a menos que você queira expor seus breakpoints de Sass a um script que injete um objeto JS com essas variáveis na sua página.
- A sintaxe fica nojenta quando você quer transformar números em strings com Sass. Eis o preço a ser pago por acreditar que repetir um número duas vezes é o pior de todos os males:
Por fim, alguém pode estar pensando “Eu não deveria basear meus breakpoints em conteúdo, não em dispositivos?”. Basicamente, a resposta é: sim… Para sites com um único layout — ou se existirem vários layouts e existem algum prazer mórbido em ter um conjunto diferente de breakpoints para cada um deles.
Para sites complexos, “do mundo real”, a prática sugere escolher alguns breakpoints para serem usados em todo o site.
Conclusão sobre a maneira 100% correta de fazer breakpoints em CSS
Brincadeiras de título à parte, certamente não existe uma maneira “100% correta” para se fazer ou usar breakpoints. Mas é difícil negar que a abordagem apresentada nesse artigo certamente pode trazer interessantes reflexões sobre o tema.
Sendo assim, considere os conteúdos apresentados como sugestões de técnicas a serem seguidas e, depois de as experimentar, julgue se fazem ou não sentido dentro dos projetos que você e/ou sua equipe participam.