Primeiro CSS genérico: novo pensamento sobre dispositivos móveis
Publicados: 2022-03-10Acho 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?
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.
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 (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