Primeiro CSS genérico: novo pensamento sobre dispositivos móveis

Publicados: 2022-03-10
Resumo rápido ↬ Com o advento do web design responsivo e a abordagem mobile-first, já se passaram sete anos maravilhosos desde que novos conceitos nos obrigaram a adaptar a maneira como escrevemos CSS no nível básico. Bem, não tenho nada muito inovador para lhe oferecer, mas tenho uma pequena surpresa. Eis: Primeiro CSS genérico.

Acho que é seguro dizer que o Responsive Web Design de Ethan Marcotte foi uma revelação bem-vinda para desenvolvedores web em todo o mundo. Isso desencadeou uma nova onda de design thinking e novas técnicas maravilhosas de front-end. O reinado dos frequentemente desprezados sites m dot também acabou. Na mesma época e quase tão influente foi a metodologia Mobile First de Luke Wroblewski – uma melhoria sólida que se baseou nos fundamentos impressionantes de Marcotte.

Essas técnicas estão na base da vida da maioria dos desenvolvedores da Web e nos serviram bem, mas, infelizmente, os tempos mudam e os desenvolvedores constantemente iteram. À medida que aumentamos a eficiência de nossos métodos e os requisitos do projeto se tornam mais complexos, surgem novas frustrações.

A jornada para o genérico em primeiro lugar

Não consigo identificar exatamente o que me fez mudar a maneira como escrevo meu CSS porque foi realmente uma progressão natural para mim que aconteceu quase inconscientemente. Olhando para trás, acho que foi mais um subproduto do ambiente de desenvolvimento em que eu estava trabalhando. A equipe com a qual trabalhei tinha um bom fluxo de trabalho SCSS acontecendo com um pequeno mixin bacana para adicionar facilmente pontos de interrupção em nossas declarações CSS. Você provavelmente usa uma técnica semelhante.

Esse pequeno e maravilhoso mixin SCSS de repente tornou fácil escrever consultas de mídia super granulares. Pegue um bloco de biografia hipotético que se parece um pouco com isto:

 .bio { display: block; width: 100%; background-color: #ece9e9; padding: 20px; margin: 20px 0; @include media('>=small') { max-width: 400px; background-color: white; margin: 20px auto; } @include media('>=medium') { max-width: 600px; padding: 30px; margin: 30px auto; } @include media('>=large') { max-width: 800px; padding: 40px; margin: 40px auto; } @include media('>=huge') { max-width: 1000px; padding: 50px; margin: 50px auto; } }

Figura 1. Típico mobile first com consultas de mídia em cascata

Isso funciona muito bem - eu escrevi muito CSS assim no passado. No entanto, um dia me ocorreu que sobrescrever declarações CSS à medida que a largura do dispositivo aumentava simplesmente não fazia sentido. Por que declarar uma propriedade CSS para que ela seja substituída apenas na declaração a seguir?

Mais depois do salto! Continue lendo abaixo ↓

Isso é o que me levou a começar a escrever consultas de mídia compartimentadas em oposição à abordagem mais comum de consultas de mídia que se propagam para cima (ou para baixo) como no exemplo da Fig.1.

Em vez de escrever consultas de mídia que aumentam em cascata com o aumento do tamanho da tela, comecei a criar consultas de mídia direcionadas que encapsulavam estilos nas larguras de tela desejadas. O mixin de consulta de mídia realmente se destacaria aqui. Agora minhas consultas de mídia SCSS estão começando a ficar assim:

 .bio { display: block; width: 100%; padding: 20px; margin: 20px 0; @include media('>=small', ' < medium') { max-width: 400px; margin: 20px auto; } @include media('>=medium', ' < large') { max-width: 600px; padding: 30px; margin: 30px auto; } @include media('>=large', ' < huge') { max-width: 800px; padding: 40px; margin: 40px auto; } @include media('>=huge') { max-width: 1000px; padding: 50px; margin: 50px auto; } }

Figura 2. Um exemplo de consultas de mídia compartimentada

Essa nova abordagem parecia mais intuitiva para mim, reduzia a necessidade de redefinir estilos do ponto de interrupção anterior e tornava o CSS mais fácil de ler. Mais importante, estava tornando as consultas de mídia auto-documentadas de uma maneira mais significativa.

Eu ainda não estava 100% feliz com o que foi dito acima, parecia que ainda havia um grande problema a ser superado.

O problema com o Mobile First

O problema com o mobile first é que, por definição, você provavelmente terá que substituir os estilos mobile-first nas consultas de mídia subsequentes. Isso parece um pouco anti-padrão.

Então — para mim — a resposta era óbvia: vamos levar a ideia de compartimentalização de media query à sua conclusão lógica — também vamos compartimentalizar os estilos específicos móveis em suas próprias media queries. Eu sei, eu sei, isso vai contra a convenção comum que aprendemos ao longo dos anos. “Mobile First” é tão onipresente que geralmente é uma das perguntas de “habilidades” que um gerente de contratação fará. Então, certamente, qualquer alternativa deve estar errada, não é? Esta é geralmente a parte em que as pessoas balançam a cabeça para mim enquanto falam mobile first repetidamente.

Ok, então vamos romper com o primeiro dogma móvel e compartimentar todos os nossos estilos nas consultas de mídia relevantes. O que resta agora são estilos genéricos puros declarados em um seletor CSS, com todos os outros estilos específicos de dispositivo encapsulados em consultas de mídia que se aplicam apenas às dimensões relevantes da tela. Agora temos o primeiro CSS genérico :

 .bio { display: block; width: 100%; @include media('>=0', ' < small') { padding: 20px; margin: 20px 0; } @include media('>=small', ' < medium') { max-width: 400px; margin: 20px auto; } @include media('>=medium', ' < large') { max-width: 600px; padding: 30px; margin: 30px auto; } @include media('>=large', ' < huge') { max-width: 800px; padding: 40px; margin: 40px auto; } @include media('>=huge') { max-width: 1000px; padding: 50px; margin: 50px auto; } }

Fig.3. Um exemplo de primeiro CSS genérico

Sim, há um pouco mais de consultas de mídia, no entanto, vejo isso como um benefício, qualquer desenvolvedor pode agora olhar para este CSS e ver exatamente quais estilos são aplicados em cada tamanho de tela sem a sobrecarga cognitiva de ter que separar a mídia. especificidade da consulta.

Isso pode ser ótimo para pessoas não familiarizadas com a base de código ou até mesmo para o futuro você!

Quando não compartimentalizar

Ainda há momentos em que a compartimentação da consulta de mídia é um fardo e, em alguns casos, uma boa e velha consulta de mídia >= é boa. Lembre-se, tudo o que estamos tentando fazer é evitar sobregravações de propriedade.

Felicidade da ferramenta de desenvolvimento

Uma das principais consequências não intencionais de escrever o Generic First CSS compartimentado é a experiência que você obterá do painel de estilo das ferramentas do desenvolvedor. Sem a cascata de consulta de mídia, agora você terá uma visão geral mais clara de quais estilos são aplicados — Você não terá um painel de estilo cheio de declarações riscadas de regras de consulta de mídia sobrescritas — O ruído acabou! Este — para mim — é um dos maiores benefícios da técnica Generic First CSS. Ele traz um pouco de sanidade extra para a experiência de depuração de CSS, e isso vale seu peso em ouro. Me agradeça mais tarde.

Captura de tela antes e depois de como a primeira abordagem CSS genérica afeta o painel de estilo das ferramentas de desenvolvimento do chrome.
Fig.4. Quão genérico primeiro, o CSS compartimentalizado pode ajudar a trazer alegria e sanidade ao seu console de desenvolvimento. (Visualização grande)

Implicações de desempenho

Portanto, todos esses benefícios do Generic First CSS estão começando a parecer muito bons, mas acho que há uma última questão-chave que acho que precisa ser abordada. É sobre o assunto de otimização de desempenho. Agora, ainda não tenho certeza, mas tenho um pressentimento de que consultas de mídia totalmente compartimentadas podem ter um pequeno benefício de desempenho.

Os navegadores executam uma tarefa de renderização chamada cálculo de estilo computado . É a maneira dos navegadores de calcular quais estilos precisam ser aplicados a um elemento em um determinado momento. Essa tarefa é sempre executada no carregamento inicial da página, mas também pode ser executada se o conteúdo da página for alterado ou se ocorrerem outras ações do navegador. Qualquer impulso que você possa dar à velocidade do processo será ótimo para o carregamento inicial da página e poderá ter um efeito composto no ciclo de vida das páginas do seu site.

Então, voltando ao primeiro CSS genérico: há algum problema de desempenho relacionado ao navegador ter que trabalhar a especificidade CSS de uma infinidade de consultas de mídia em cascata?

Para responder a isso, criei um caso de teste que pode ser usado para medir quaisquer benefícios ou desvantagens de velocidade.

O Caso de Teste

O caso de teste é composto por uma página HTML básica que gera um bloco “bio” 5000 vezes, a marcação é a mesma para cada bloco, mas as classes são ligeiramente diferentes (diferenciador numérico), o CSS para este bloco também é gerado 5000 vezes , com os nomes das classes sendo a única diferença. O CSS de saída é canalizado por meio de uma ferramenta chamada CSS MQPacker, isso ajuda a reduzir drasticamente o tamanho do arquivo CSS que usa muitas consultas de mídia inline combinando todas as instâncias separadas de uma consulta de mídia específica em uma — É uma ótima ferramenta que provavelmente se beneficiará a maioria das bases de código CSS modernas — usei-o como uma ferramenta cli independente por meio de uma tarefa npm nos projetos de teste package.json, você também pode usá-lo como um plugin postcss, o que é bom e conveniente!

O primeiro caso de teste é um exemplo de consultas de mídia em cascata para dispositivos móveis, o segundo caso de teste é uma primeira variante compartimentada genérica do CSS. O CSS para esses casos é um pouco detalhado e provavelmente poderia ser escrito em termos muito mais concisos, mas na verdade serve apenas como um exemplo aproximado para testar o argumento.

O teste foi executado 20 vezes para cada variação de CSS no Google Chrome v70 para desktop, não um conjunto enorme de dados, mas o suficiente para me dar uma ideia aproximada de ganho/perda de desempenho.

As métricas de teste que escolhi para usar são:

  • Tempo total de carregamento da página
    Uma métrica básica para verificar o tempo de carregamento da página usando os marcadores da Performance API no início do <head> e no final do <body>
  • O estilo recalcular
    Tempo de dentro do painel de desempenho das ferramentas de desenvolvimento.
  • A renderização geral da página
    Tempo de dentro do painel de desempenho das ferramentas de desenvolvimento.
Tabela de resultados do criador de perfil de desempenho do Google Chrome
Fig.5. A principal métrica que está sendo medida é “Recalcular Estilo”. (Visualização grande)

Tabela de resultados (todos os tempos em milissegundos)

Primeiro celular Genérico primeiro
Tempo de carregamento Calcular estilos Tempo total de renderização Tempo de carregamento Calcular estilos Tempo total de renderização
1135 565,7 1953 1196 536,9 2012
1176 563,5 1936 1116 506,9 1929
1118 563,1 1863 1148 514,4 1853
1174 568,3 1929 1124 507.1 1868
1204 577,2 1924 1115 518,4 1854
1155 554,7 1991 1177 540,8 1905
1112 554,5 1912 1111 504,3 1886
1110 557,9 1854 1104 505,3 1954
1106 544,5 1895 1148 525,4 1881
1162 559,8 1920 1095 508,9 1941
1146 545,9 1897 1115 504,4 1968
1168 566,3 1882 1112 519,8 1861
1105 542,7 1978 1121 515,7 1905
1123 566,6 1970 1090 510,7 1820
1106 514,5 1956 1127 515,2 1986
1135 575,7 1869 1130 504.2 1882
1164 545,6 2450 1169 525,6 1934
1144 565 1894 1092 516 1822
1115 554,5 1955 1091 508,9 1986
1133 554,8 2572 1001 504,5 1812
AVG 1139,55 557,04 1980 1119.1 514,67 1903.15

Fig.6. 20 execuções de teste medindo as principais métricas de carregamento/renderização do primeiro CSS móvel versus o primeiro CSS genérico.

Do meu conjunto de dados reconhecidamente pequeno, parece que minha suspeita inicial pode estar correta. Em média, vejo que a tarefa de Recálculo de Estilo leva 42 ms a menos, o que representa um aumento de velocidade de 7,6% e, portanto, o tempo de renderização geral também diminui. A diferença não é surpreendente, mas é uma melhoria. Não acho que o conjunto de dados seja grande o suficiente para ser 100% conclusivo e o caso de teste seja um pouco irreal, mas estou muito feliz por não estar vendo uma degradação no desempenho.

Eu estaria muito interessado em ver a primeira metodologia genérica aplicada a uma base de código existente no mundo real que foi escrita da maneira mobile-first - as métricas antes depois seriam muito mais realistas para a prática cotidiana.

E se alguém tiver sugestões sobre como automatizar esse teste em um conjunto mais amplo de iterações, por favor, deixe-me saber nos comentários! Eu imagino que deve haver uma ferramenta que pode fazer isso.

Conclusão

Para recapitular os benefícios desta nova metodologia de desenvolvimento...

  • CSS que faz exatamente como pretendido, sem adivinhação;
  • Consultas de mídia autodocumentadas;
  • Uma melhor experiência de ferramentas de desenvolvimento;
  • Páginas que renderizam mais rápido.

Eu gostaria de pensar que não sou a única pessoa que defende a escrita de CSS neste estilo. Se você já adotou a primeira mentalidade genérica, viva! Mas se não, acho que você vai gostar muito dos benefícios que ela traz. Eu pessoalmente me beneficiei muito da experiência organizada das ferramentas de desenvolvimento, que por si só será um grande positivo para muitos desenvolvedores. a natureza de autodocumentação dessa maneira de escrever suas consultas de mídia também trará benefícios para você e para a equipe mais ampla (se você tiver uma). E, finalmente, esses benefícios não lhe custarão nada em termos de desempenho e, de fato, demonstraram ter ganhos marginais de velocidade!

Palavra final

Como todas as metodologias de desenvolvimento, pode não ser para todos, mas eu caí no Generic First CSS naturalmente, agora vejo isso como uma maneira valiosa de trabalhar que me dá todos os benefícios do mobile first com algumas novas adições positivas que tornam o difícil trabalho de desenvolvimento front-end que pouco seria mais fácil.

Recursos

Repositório de Caso de Teste

Se você quiser iniciar o caso de teste e experimentá-lo, você pode encontrá-lo no GitHub, adoraria ver alguns relatórios de outras pessoas.

Ferramentas

  • CSS MQPacker
  • Incluir mídia