Novos horizontes em CSS: Houdini e a API Paint

Una Kravets Blocked Unblock Seguir Seguindo 9 de janeiro

A maneira como escrevemos CSS está prestes a mudar. Não, eu não quero dizer que você tem que mudar como você escreve seus estilos, mas nós, como desenvolvedores, estamos prestes a ter muito mais controle.

O que eu estou falando? Essa seria a especificação CSS Houdini e as novas APIs do navegador que estão saindo como parte dela.

Houdini 101

Então, o que é Houdini? Bem, estou feliz que tenha perguntado. Houdini dá aos desenvolvedores acesso ao modelo de objeto CSS (CSSOM) pela primeira vez. Em vez de atualizar estilos em JavaScript, os desenvolvedores podem escrever o código que o navegador entende e pode analisar como CSS!

Dev Doodles

No momento, quando queremos aplicar estilos que não existem como propriedades CSS, precisamos usar o JavaScript para substituir o CSS existente. Isso significa que o navegador percorre todo um processo em cascata, layout, pintura e composto antes de precisar percorrer o layout, a pintura e o processo composto novamente para que a atualização do estilo JavaScript seja renderizada (isso, é claro, depende do que você está atualizando).

Com Houdini, podemos escrever o código que o navegador entende e aplicá-lo ao início do ciclo, onde o CSS está sendo tokenizado e compreendido. Que significa:

  • Tempos de análise mais rápidos para estilos complexos (já que o estilo está acontecendo na etapa CSS)
  • Os desenvolvedores não precisam mais esperar que os fornecedores de navegadores incluam a funcionalidade CSS – eles podem apenas polifilar (isso aconteceria quando todos os navegadores suportam Houdini – cada worklet Houdini poderia funcionar de forma intercambiável entre navegadores, como plugins CSS)
  • Polyfills têm mais desempenho, por isso as páginas serão renderizadas mais rapidamente
  • Melhor separação de lógica e estilo (estilo mantido em CSS, lógica mantida em JS)
  • Mais estilos personalizados e sistemas de design (já que essa abordagem nos permite adicionar estilos que não podemos criar com CSS hoje, além de nos permitir criar valores padrão e fallbacks em sistemas visuais)

Com Houdini, você poderia escrever seus estilos em JavaScript, invocar o arquivo que os registra no navegador e depois aplicar esses estilos em seu CSS.

O processo é assim:

Check Out More Dev Doodles: https://www.instagram.com/dev_doodles/

A especificação completa do Houdini é muito grande, engloba muitos elementos diferentes e é um trabalho em progresso. Para ver uma ótima visão geral, confira ishoudinireadyyet.com . Este é um ótimo recurso com uma visão geral do progresso de cada API do Houdini com links relevantes incluídos.

Para este post eu quero focar em apenas um dos recursos – Ainda no estado de rascunho, o CSS Painting API, é o mais desenvolvido e suportado no momento da redação deste artigo.

A API de pintura

A API do Paint nos permite escrever no processo de pintura do mecanismo de renderização do DOM. Podemos criar estilos exclusivos, como brilhos no texto, cantos exclusivos ou bordas estilizadas. As possibilidades realmente são infinitas, e um ótimo lugar para ver alguns desses exemplos é o site CSS Houdini Rocks, de Vincent de Oliveira . A API do Paint usa uma classe e aceita o contexto (elemento ao qual estamos aplicando o estilo) e o tamanho (o tamanho de delimitação físico desse elemento). Ele também aceita os argumentos de props para propriedades estáticas e args para argumentos de entrada.

 registerPaint('redBackground', class { 
paint(ctx, size) {
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, size.width, size.height);
}
})

Esse código de arquivo de worklet criaria um retângulo vermelho. Se você estiver familiarizado com o HTML Canvas, poderá notar que o código é semelhante ao canvas – e funciona. O contexto (ctx) é a tela aqui e usamos a sintaxe semelhante a tela para aplicar estilos (como larguras e cores) e desenhar esses estilos – nesse caso, usamos fillStyle para definir a cor de preenchimento e fillRect para preencher um retângulo, especificado para iniciar em (0,0) e preencher a largura e a altura do elemento.

Se quiséssemos usar o worklet acima, precisaríamos invocar o exercício em nosso HTML com:

 <script> 
if ('paintWorklet' in CSS) {
CSS .paintWorklet. addModule('./worklet.js');
}
</script>

E em CSS:

 .element { 
background: paint(redBackground);
}

Este exemplo anterior não nos mostra nada que uma simples background-color:red não pudesse fazer, mas o interessante de Houdini é que há muito mais possibilidades aqui!

Vamos pintar

Para trabalhar com a API de pintura, você deve veicular o arquivo em um site seguro (https) ou localmente. Isso ocorre porque os worklets Houdini são semelhantes aos trabalhadores de serviços, pois são uma camada que fica entre o navegador e a rede, funcionando quando necessário e desligando quando precisam.

Portanto, para começar sem configurar um ambiente de desenvolvimento inteiro, sugiro executar um servidor local com um comando como: python -m SimpleHTTPServer 8000 , que inicia e executa um servidor na porta 8000 .

Vamos passar por cima de um exemplo chamado SUPER UNDERLINE: D onde podemos especificar e criar múltiplos sublinhados para nosso documento (é apenas um exemplo simples para começar, mas o mundo é sua ostra com Houdini, especialmente se você conhece a tela HTML !) Se parece com isso:

Neste exemplo, criamos sublinhados aleatoriamente sendo desenhados para cada elemento, enquanto especificamos quantos queremos (o número de sublinhados), a cor do sublinhado, o peso do sublinhado e até onde eles devem ser espalhados (como em ângulo eles serão). Para configurar tudo, precisaremos de três arquivos: um arquivo HTML no qual registramos o treinamento, um arquivo de worklet onde definimos a tinta e o CSS em que usaremos o worklet (conforme mostrado no diagrama anterior ).

O corpo do código HTML se parece com isto:

 <h1>Hello World</h1> 
 <!— check if paint workout is supported in the browser and register a file called `worklet.js` if it is —> 
 <script> 
if ('paintWorklet' in CSS) {
CSS.paintWorklet.addModule('./worklet.js');
}
</script>

Em seguida, queremos começar a criar nosso arquivo de worklet, verificando o suporte no navegador também:

 if (typeof registerPaint !== 'undefined') { 
class SuperUnderline {
paint(ctx, size) {
// paint instructions will go here
}
}
}
 registerPaint('superUnderline', SuperUnderline) 
}

E precisamos garantir que também incluamos isso no CSS, enquanto, novamente, procuramos suporte:

 @supports (background: paint(something)) { 
h1 {
background: paint(superUnderline);
}
}

Agora, nada vai acontecer neste momento, então vamos especificar algo para pintar dentro do nosso worklet. Dentro da classe, podemos usar os parâmetros ctx e size para enganchar em nosso elemento:

 // random function can live outside of the class 
const getRandom = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min
}
 // values to set for the paint 
const numUnderlines = 3
const spread = 20
ctx.lineWidth = 3
ctx.strokeStyle = 'red'
 for (let i = 0; i < numUnderlines; i++) { 
ctx.beginPath()
ctx.moveTo(0, getRandom(0, spread) + size.height/1.4)
ctx.lineTo(size.width, getRandom(0, spread) + size.height/1.4)
ctx.stroke()
}

No código acima, estamos desenhando 3 linhas vermelhas aleatórias em direção à parte inferior da div (1.4 é um número aleatório lá porque não podemos realmente sair da tela ou as linhas não aparecerão, como uma verdadeira sublinhado). O spread é definido como 20 e a largura das linhas é 1.

Nosso exemplo atualmente é assim:

OBSERVAÇÃO: Se você não vir nada nem nenhuma alteração, primeiro verifique se está usando um navegador com suporte para a API do Paint. Em seguida, abra suas ferramentas de desenvolvedor e desative o cache com as ferramentas dev abertas. Neste momento, desenvolver com o Houdini é um pouco complicado: P

Voltando ao nosso exemplo: podemos fazer muito melhor que isso! Devemos tornar esse código um pouco mais flexível para que os usuários possam atualizar a largura, o spread, a cor e o número de sublinhados. E podemos fazer isso com propriedades personalizadas CSS!

Propriedades Customizadas CSS

Se você usou variáveis em CSS, que você definiu na raiz (ou escopo local), elas são propriedades personalizadas. Mas agora você tem uma tonelada de controle em CSS para definir suas próprias propriedades personalizadas, especificar valores padrão e dar a elas uma sintaxe (!)! Eu adicionei exclamações duplas lá porque isso é tão legal! Agora, quando você usa essas propriedades personalizadas e substitui uma delas, é possível fazer algum tratamento de sanidade e erro. Se não corresponder a uma sintaxe definida, por exemplo, ela retornará a um valor predefinido em vez de ignorar totalmente a linha, como acontece atualmente com o CSS.

Eu posso continuar sobre as propriedades customizadas do CSS, mas vou direto ao ponto aqui. Vamos criar um arquivo `properties.js` e configurar algumas novas variáveis que usaremos em nosso exemplo:

 CSS.registerProperty ({ 
nome: '--underlineNumber',
sintaxe: '<number>',
herda: falsa,
initialValue: 3
});
 CSS.registerProperty ({ 
nome: '--underlineColor',
sintaxe: '<cor>',
herda: verdadeiro
initialValue: 'preto'
});
 CSS.registerProperty ({ 
nome: '--underlineSpread',
sintaxe: '<number>',
herda: falsa,
initialValue: 20
});
 CSS.registerProperty ({ 
nome: '--underlineWidth',
sintaxe: '<number>',
herda: falsa,
initialValue: 2
});

Agora precisamos nos lembrar de incluir esse arquivo no JS se ele for separado ou importá-lo para o nosso arquivo de worklet. No exemplo acima, definimos algumas propriedades que herdam da sintaxe numérica ( underlineNumber , underlineSpread e underlineWidth ) e uma propriedade que herda da cor ( underlineColor ). Isso é útil porque agora podemos animar nossos sublinhados se atualizarmos os valores, e o navegador saberá como interpolar esses valores. É por isso que, com Houdini, agora podemos criar gradientes animados.

Em CSS, poderemos definir esses valores da seguinte forma:

 @supports (background: paint (alguma coisa)) { 
h1 {
/ *
Opcionalmente, defina os valores da propriedade.
Isso pode ser feito no escopo raiz ou local
* /
--underlineNumber: 5; / * padrão: 3 * /
--Em seguida, cor: # 8266ff; / * padrão: preto * /
--underlineSpread: 15; / * padrão: 20 * /
--underlineWidth: 1; / * padrão: 2 * /
 fundo: pintar (superUnderline); 
altura da linha: 1,5;
}
}

E agora vamos voltar ao nosso worklet para garantir que estamos passando essas propriedades personalizadas para a função de pintura, para que possamos usá-las. Usaremos static get inputProperties () e incluiremos uma matriz de propriedades que, em seguida, poderemos extrair para nossa função usando properties.get e passando as propriedades. Tudo junto parece assim:

 const getRandom = (min, max) => { 
retornar Math.floor (Math.random () * (max - min + 1)) + min
}
 if (tipo de registerPaint! == 'undefined') { 
classe SuperUnderline {
static get inputProperties () {
return ['--underlineNumber', '--underlineColor', '--underlineSpread', '--underlineWidth']
}
 pintar (ctx, tamanho, propriedades) { 
const numUnderlines = properties.get ('- underlineNumber')
const lineWidth = properties.get ('- underlineWidth')
const color = properties.get ('- underlineColor')
const spread = properties.get ('- underlineSpread')
 ctx.lineWidth = lineWidth 
ctx.strokeStyle = cor
 para (let i = 0; i <numUnderlines; i ++) { 
ctx.beginPath ()
ctx.moveTo (0, getRandom (0, spread) + size.height / 1.4)
ctx.lineTo (size.width, getRandom (0, spread) + size.height / 1.4)
ctx.stroke ()
}
}
}
 registerPaint ('superUnderline', SuperUnderline) 
}

Criamos com sucesso propriedades personalizadas que estamos passando para o nosso worklet Houdini a partir de CSS e usando CSS para extrair instruções visuais do nosso worklet! Como mencionei anteriormente, você pode animar e atualizar as propriedades como desejar. Quando você redimensiona a janela do seu navegador, também esteja ciente de que o elemento pode ser repintado, já que seu tamanho está mudando, e ele ficará bem diferente em cada repinta, já que esse exemplo usa a randomização para fazer a mágica acontecer.

Uma palavra de aviso

É um momento tão empolgante para ser um desenvolvedor web, e Houdini está prestes a dar uma tonelada de poder para pessoas que gostam de projetar e construir visualmente na web. As coisas que nos queixamos com CSS podem ser resolvidas, e podemos definir nossa própria maneira de estilizar as coisas. Embora seja cedo, já houve tantos grandes exemplos e demonstrações de Houdini em ação.

No entanto, tenha em mente que Houdini é uma tecnologia experimental e ainda não está pronta para produção. Você deve sempre verificar o suporte ao navegador antes de implementar qualquer estilo usando essa técnica. Além disso, as vitórias que obtemos no desempenho podem ser facilmente ofuscadas por um desenvolvedor superexcitado, já que essa tecnologia nos dá muito poder. Você ainda tem que ter cuidado para não exagerar, especialmente com efeitos animados. Tenha em mente que esta tecnologia está mudando rapidamente, mas, no entanto, divirta-se experimentando com Houdini!

Outros recursos

Plug: LogRocket , um DVR para aplicativos da web

https://logrocket.com/signup/

LogRocket é uma ferramenta de registro de front-end que permite que você repita problemas como se eles tivessem ocorrido em seu próprio navegador. Em vez de adivinhar por que os erros ocorrem ou solicitar aos usuários capturas de tela e log dumps, o LogRocket permite que você repita a sessão para entender rapidamente o que deu errado. Ele funciona perfeitamente com qualquer aplicativo, independentemente do framework, e possui plugins para registrar o contexto adicional do Redux, Vuex e @ ngrx / store.

Além de registrar as ações e o estado do Redux, o LogRocket registra logs do console, erros de JavaScript, rastreamentos de pilha, solicitações / respostas de rede com cabeçalhos + corpos, metadados do navegador e logs personalizados. Ele também instrumenta o DOM para gravar o HTML e CSS na página, recriando vídeos com pixels perfeitos até mesmo dos aplicativos de página única mais complexos.

Experimente Grátis.