Desenvolvimento web

Desenvolvimento de site por R$150,00/Mês

Desenvolvimento Web responsivo com Melhor Custo-beneficio

Planos de desenvolvimento web com hospedagem Gratís
Arquivo de CSS | LCF HOST

Tag: CSS


CSS Blocks: introdução à API

Veja neste artigo uma introdução à API de CSS Blocks e comece a entender porque este é um dos melhores compiladores CSS da atualidade.

No primeiro artigo sobre CSS Blocks (o primeiro brasuca, aliás!) apresentamos o otimizador de CSS da LinkedIn, explicando um pouco sobre o porquê de sua existência e seus princípios-base. Agora, vamos a mais algumas explicações de código para entender melhor o que CSS Blocks é capaz de fazer.

Como uma breve recapitulação, CSS Blocks é um compilador inspirado em CSS Modules, BEM e Atomic CSS que, usando o OptiCSS, promete entregar estilos bem mais enxutos e performáticos. No momento da publicação deste artigo, é possível usá-lo nas templating languages JSX/React e Glimmer (com WebpackBroccoli ou Ember-CLI) — por se tratar de um projeto open source, a tendência é que mais e mais opções surjam bem rapidamente.

O que é um “Bloco”?

O nome da coisa é CSS Blocks, “Blocos CSS”; mas, segundo a metáfora de desenvolvimento escolhida, o que seria um “Bloco”?

Um Bloco é uma folha de estilo isolada, escrita em seu próprio arquivo, que contém todos os conjuntos de regras para quaisquer elementos e seus vários modos e estados de interação para uma unidade discreta de estilo — como um componente, por exemplo.

Normalmente, um único bloco conterá estilos para um componente ou conceito específico, mas é totalmente natural — e incentivado — um template usar vários Blocos e os compor juntos na marcação.

Um Bloco pode conter:

  • Seletor :scope
  • Seletores de classe
  • Seletores de estado
  • Seletores de sub-estado

Seletor :scope

O conjunto de regras de escopo contém estilos aplicados à raiz da sub-árvore de estilo com escopo. Trocando em miúdos, todos os outros elementos atribuídos a estilos de um Bloco devem estar contidos na sub-árvore do documento de um elemento atribuído ao escopo desse Bloco. Usa-se a pseudo-classe :scope para representar esses estilos.

O seletor :scope pode conter a propriedade especial block-name que torna possível fornecer um nome específico para o Bloco para um debugging mais fácil e respectiva geração de classe BEM. Se nenhum nome de bloco for fornecido, infere-se o nome do bloco a partir do nome do arquivo.

Sim, você leu corretamente: a compilação final de CSS Blocks gera nomes de classes seguindo a metodologia BEM!

Por exemplo:

Seletores de classe

Blocos podem conter outras classes que podem ser aplicadas a elementos dentro da sub-árvore de estilo escopada. São apenas seletores de classe comuns, mas são locais para esse Bloco e isolados de todas as outras classes com nomes iguais em outros Blocos.

Juntos, o seletor :scope e todos os seletores de classe (.class) declarados definem a interface completa dos elementos estilizados disponíveis para quem vai usar um Bloco.

Seletores de Estado

Estados representam um modo ou estado de interação no qual :scope ou uma classe — denominada Elemento Originário do Estado — pode estar. Os Estados são gravados como seletores de atributos com o namespace especial state.

Seletores de sub-estado

Estados no seletor :scope ou um seletor de classe podem conter sub-estados para um estilo mais granular. Os sub-estados de um Estado são mutuamente exclusivos, ou seja, um elemento só pode estar em um sub-estado de um Estado por vez.

Restrições na API de CSS Blocks

CSS Blocks implementa um subconjunto estrito de CSS. Isso significa que alguns dos recursos que normalmente poderiam ser usados em um arquivo em um arquivo de Bloco foram intencionalmente restringidos para garantir que a compilação final possa gerar estilos da maneira mais otimizada possível.

A equipe principal de desenvolvimento do CSS Blocks já planeja melhorias neste sentido; em breve, estas restrições serão bem menores.

Para ficar claro:

  • Permitido:
  • Proibido (por enquanto):
    • !important (você já deveria tê-lo banido, de qualquer maneira)
    • tag[attribute] que não seja de Estado, #id e seletores *
    • Os Combinadores Lógicos :matches():not():something() e :has()
    • Importante: seletores devem se manter rasos (shallow)

No contexto de CSS Blocks, “seletores rasos” significa:

Apenas 1 combinador por seletor

Seletores de Combinadores Hierárquicos (” “ e “>“) devem ser um estado de :scope, sub-estados ou pseudo-classes

Seletores de irmão (“+” e “~“) devem ter como target a mesma classe ou :scope usado no seletor-chave

Como todo o código é analisado e compilado estaticamente (statically) antes de atingir o navegador, obviamente um erro bastante útil será gerado caso alguma dessas restrições de sintaxe seja violada.

Conclusão

É difícil tentar decorar todas essas peculiaridades; com o tempo de uso de CSS Blocks, naturalmente isso vai se internalizar. De qualquer maneira, é bom saber que existe uma tabela bem útil mostrando o que é permitido e proibido na API — que, devido à incipiência de CSS Blocks, deve ser alterada (para melhor) bem rapidinho e com bastante frequência.

Para ficar claro, eis o que acontece na fase de Compilação de CSS Blocks:

O processo de otimização vai além; existem mais passos até que o output final aconteça — ou você achou que CSS Blocks servia só para escrever BEM de maneira mais complicadinha? Mas isso já é assunto para outro artigo…


A maneira 100% correta de fazer breakpoints em CSS

Depois de anos usando breakpoints, será que a maioria dos desenvolvedores front-end realmente já pararam para pensar se estão fazendo do jeito certo?

Para o 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 (320px768px1024px)!

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:

  1. Crie breakpoints do jeito certo
  2. Nomeie breakpoints corretamente
  3. 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:

600px900px1200px 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.

@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; }
}
// usage
.my-box {
padding: 10px;
@include for-desktop-up {
padding: 20px;
}
}

Perceba que é proposital forçar o uso dos sufixos -up/-onlyAmbiguidade 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:

@mixin for-size($size) {
@if $size == phoneonly {
@media (max-width: 599px) { @content; }
} @else if $size == tabletportraitup {
@media (min-width: 600px) { @content; }
} @else if $size == tabletlandscapeup {
@media (min-width: 900px) { @content; }
} @else if $size == desktopup {
@media (min-width: 1200px) { @content; }
} @else if $size == bigdesktopup {
@media (min-width: 1800px) { @content; }
}
}
// usage
.my-box {
padding: 10px;
@include for-size(desktop-up) {
padding: 20px;
}
}

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:

  1. 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.
  2. 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:
@mixin for-size($range) {
$phone-upper-boundary: 600px;
$tablet-portrait-upper-boundary: 900px;
$tablet-landscape-upper-boundary: 1200px;
$desktop-upper-boundary: 1800px;
@if $range == phoneonly {
@media (max-width: #{$phone-upper-boundary – 1}) { @content; }
} @else if $range == tabletportraitup {
@media (min-width: $phone-upper-boundary) { @content; }
} @else if $range == tabletlandscapeup {
@media (min-width: $tablet-portrait-upper-boundary) { @content; }
} @else if $range == desktopup {
@media (min-width: $tablet-landscape-upper-boundary) { @content; }
} @else if $range == bigdesktopup {
@media (min-width: $desktop-upper-boundary) { @content; }
}
}
// usage
.my-box {
padding: 10px;
@include for-size(desktop-up) {
padding: 20px;
}
}

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.