Una panoramica pratica di CSS Houdini

Pubblicato: 2022-03-10
Riassunto veloce ↬ Houdini, un termine generico per la raccolta di API del browser, mira a apportare miglioramenti significativi al processo di sviluppo web e allo sviluppo degli standard CSS in generale. Gli sviluppatori frontend saranno in grado di estendere il CSS con nuove funzionalità utilizzando JavaScript, agganciarsi al motore di rendering CSS e dire al browser come applicare CSS durante un processo di rendering. Il supporto del browser di Houdini sta migliorando e alcune API sono disponibili per l'uso oggi, quindi è un buon momento per familiarizzare con loro e sperimentare. Daremo un'occhiata a ciascuna parte di Houdini, al suo attuale supporto per il browser e vedremo come possono essere utilizzati oggi utilizzando il miglioramento progressivo.

Ci vuole molto tempo prima che una nuova funzionalità CSS o miglioramento passi da una bozza iniziale a una funzionalità CSS completamente supportata e stabile che gli sviluppatori possono utilizzare. I polyfill basati su JavaScript possono essere utilizzati come sostituti della mancanza di supporto del browser per utilizzare le nuove funzionalità CSS prima che vengano implementate ufficialmente. Ma nella maggior parte dei casi sono difettosi. Ad esempio, scrollsnap-polyfill è uno dei numerosi polyfill che possono essere utilizzati per correggere le incongruenze del supporto del browser per la specifica CSS Scroll Snap. Ma anche quella soluzione presenta alcune limitazioni, bug e incongruenze.

Il potenziale svantaggio dell'utilizzo dei polyfill è che possono avere un impatto negativo sulle prestazioni e sono difficili da implementare correttamente. Questo aspetto negativo è correlato al DOM e al CSSOM del browser. Browser crea un DOM (Document Object Model) dal markup HTML e, allo stesso modo, crea CSSOM (CSS Object Model) dal markup CSS. Questi due alberi di oggetti sono indipendenti l'uno dall'altro. JavaScript funziona su DOM e ha un accesso molto limitato a CSSOM.

Le soluzioni JavaScript Polyfill vengono eseguite solo dopo che il ciclo di rendering iniziale è stato completato, ovvero quando sono stati creati sia DOM che CSSOM e il documento ha terminato il caricamento. Dopo che Polyfill ha apportato modifiche agli stili nel DOM (integrandoli), il processo di rendering viene eseguito nuovamente e l'intera pagina viene riprodotta. L'impatto negativo sulle prestazioni diventa ancora più evidente se si basano sul metodo requestAnimationFrame o dipendono dalle interazioni dell'utente come gli eventi di scorrimento.

Un altro ostacolo nello sviluppo web sono i vari vincoli imposti dagli standard CSS . Ad esempio, esiste solo un numero limitato di proprietà CSS che possono essere animate in modo nativo. CSS sa come animare i colori in modo nativo, ma non sa come animare i gradienti. C'è sempre stata la necessità di innovare e creare esperienze web impressionanti spingendo i confini nonostante i limiti tecnologici. Questo è il motivo per cui gli sviluppatori spesso tendono a gravitare verso l'utilizzo di soluzioni alternative non ideali o JavaScript per implementare stili ed effetti più avanzati che attualmente non sono supportati dai CSS come layout in muratura, effetti 3D avanzati, animazione avanzata, tipografia fluida, gradienti animati, elementi select con stile, ecc.

Sembra impossibile che le specifiche CSS tengano il passo con le varie richieste di funzionalità del settore, come un maggiore controllo sulle animazioni, un migliore troncamento del testo, una migliore opzione di stile per gli elementi di input e di select , più opzioni di display , più opzioni di filter , ecc.

Quale potrebbe essere la potenziale soluzione? Offri agli sviluppatori un modo nativo per estendere i CSS utilizzando varie API . In questo articolo, daremo un'occhiata a come gli sviluppatori frontend possono farlo utilizzando le API Houdini, JavaScript e CSS. In ogni sezione, esamineremo ciascuna API individualmente, verificheremo il supporto del browser e lo stato delle specifiche correnti e vedremo come possono essere implementate oggi utilizzando il miglioramento progressivo.

Altro dopo il salto! Continua a leggere sotto ↓

Cos'è Houdini?

Houdini, un termine generico per la raccolta di API del browser, mira a apportare miglioramenti significativi al processo di sviluppo web e allo sviluppo degli standard CSS in generale. Gli sviluppatori potranno estendere il CSS con nuove funzionalità utilizzando JavaScript, agganciarsi al motore di rendering CSS e dire al browser come applicare CSS durante un processo di rendering. Ciò si tradurrà in prestazioni e stabilità significativamente migliori rispetto all'utilizzo di normali polyfill.

La specifica Houdini è composta da due gruppi di API: API di alto livello e API di basso livello .

Le API di alto livello sono strettamente correlate al processo di rendering del browser (stile → layout → pittura → composito). Ciò comprende:

  • API di pittura
    Un punto di estensione per la fase di rendering della vernice del browser in cui vengono determinate le proprietà visive (colore, sfondo, bordo, ecc.).
  • API di layout
    Un punto di estensione per la fase di rendering del layout del browser in cui vengono determinate le dimensioni, la posizione e l'allineamento degli elementi.
  • API di animazione
    Un punto di estensione per la fase di rendering composito del browser in cui i livelli vengono disegnati sullo schermo e animati.

Le API di basso livello costituiscono una base per le API di alto livello. Ciò comprende:

  • API del modello a oggetti tipizzato
  • API di proprietà e valori personalizzati
  • API delle metriche dei caratteri
  • Worklets

Alcune API Houdini sono già disponibili per l'uso in alcuni browser con altre API per seguire l'esempio quando sono pronte per il rilascio.

Il futuro dei CSS

A differenza delle normali specifiche delle funzionalità CSS che sono state introdotte finora, Houdini si distingue perché consente agli sviluppatori di estendere il CSS in un modo più nativo. Ciò significa che le specifiche CSS smetteranno di evolversi e non verranno rilasciate nuove implementazioni ufficiali delle funzionalità CSS? Ebbene, non è così. L'obiettivo di Houdini è aiutare il processo di sviluppo delle funzionalità CSS consentendo agli sviluppatori di creare prototipi funzionanti che possono essere facilmente standardizzati.

Inoltre, gli sviluppatori saranno in grado di condividere i CSS Worklet open source più facilmente e con meno necessità di correzioni di bug specifiche del browser.

API del modello a oggetti tipizzato

Prima dell'introduzione di Houdini, l'unico modo per JavaScript di interagire con i CSS era analizzare i CSS rappresentati come valori di stringa e modificarli. L'analisi e l'override degli stili manualmente possono essere difficili e soggetti a errori a causa del tipo di valore che deve essere modificato avanti e indietro e dell'unità di valore che deve essere aggiunta manualmente quando si assegna un nuovo valore.

 selectedElement.style.fontSize = newFontSize + "px"; // newFontSize = 20 console.log(selectedElement.style.fontSize); // "20px"

L'API Typed Object Model (Typed OM) aggiunge più significato semantico ai valori CSS esponendoli come oggetti JavaScript tipizzati. Migliora notevolmente il relativo codice e lo rende più performante, stabile e manutenibile. I valori CSS sono rappresentati dall'interfaccia CSSUnitValue che consiste in un valore e una proprietà unit.

 { value: 20, unit: "px" }

Questa nuova interfaccia può essere utilizzata con le seguenti nuove proprietà:

  • computedStyleMap() : per l'analisi di stili calcolati (non in linea). Questo è un metodo dell'elemento selezionato che deve essere invocato prima di analizzare o utilizzare altri metodi.
  • attributeStyleMap : per analizzare e modificare gli stili inline. Questa è una proprietà disponibile su un elemento selezionato.
 // Get computed styles from stylesheet (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Set inline styles selectedElement.attributeStyleMap.set("font-size", CSS.em(2)); // Sets inline style selectedElement.attributeStyleMap.set("color", "blue"); // Sets inline style // Computed style remains the same (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Get new inline style selectedElement.attributeStyleMap.get("font-size"); // { value: 2, unit: "em"}

Nota come vengono utilizzati tipi CSS specifici quando si imposta un nuovo valore numerico. Utilizzando questa sintassi, è possibile evitare molti potenziali problemi relativi ai tipi e il codice risultante è più affidabile e privo di bug.

I metodi get e set sono solo un piccolo sottoinsieme di tutti i metodi disponibili definiti dall'API Typed OM. Alcuni di essi includono:

  • clear : rimuove tutti gli stili inline
  • delete : rimuove una proprietà CSS specificata e il relativo valore dagli stili inline
  • has : restituisce un valore booleano se è impostata una proprietà CSS specificata
  • append : aggiunge un valore aggiuntivo a una proprietà che supporta più valori
  • eccetera.

Rilevamento delle caratteristiche

 var selectedElement = document.getElementById("example"); if(selectedElement.attributeStyleMap) { /* ... */ } if(selectedElement.computedStyleMap) { /* ... */ }

Stato delle specifiche W3C

  • Bozza di lavoro: pubblicata per la revisione da parte della comunità

Supporto del browser

Google Chrome Microsoft Edge Browser Opera Firefox Safari
Supportato Supportato Supportato Non supportato Sostegno parziale (*)

* supportato con "Caratteristiche della piattaforma Web sperimentale" o altro flag di funzionalità abilitato.

Fonte dati: Houdini è ancora pronto?

API di proprietà e valori personalizzati

L'API CSS Properties And Values ​​consente agli sviluppatori di estendere le variabili CSS aggiungendo un tipo, un valore iniziale e definendo l'ereditarietà. Gli sviluppatori possono definire proprietà personalizzate CSS registrandole utilizzando il metodo registerProperty che indica ai browser come eseguire la transizione e gestire il fallback in caso di errore.

 CSS.registerProperty({ name: "--colorPrimary", syntax: "<color>", inherits: false, initialValue: "blue", });

Questo metodo accetta un argomento di input che è un oggetto con le seguenti proprietà:

  • name : il nome della proprietà personalizzata
  • syntax : indica al browser come analizzare una proprietà personalizzata. Questi sono valori predefiniti come <color> , <integer> , <number> , <length> , <percentage> , ecc.
  • inherits : indica al browser se la proprietà personalizzata eredita il valore del suo genitore.
  • initialValue : indica il valore iniziale che viene utilizzato fino a quando non viene sovrascritto e questo viene utilizzato come fallback in caso di errore.

Nell'esempio seguente viene impostata la proprietà personalizzata del tipo <color> . Questa proprietà personalizzata verrà utilizzata nella transizione del gradiente. Potresti pensare che l'attuale CSS non supporti le transizioni per i gradienti di sfondo e avresti ragione. Si noti come la proprietà personalizzata stessa venga utilizzata in transition , invece di una proprietà background che verrebbe utilizzata per le normali transizioni background-color .

 .gradientBox { background: linear-gradient(45deg, rgba(255,255,255,1) 0%, var(--colorPrimary) 60%); transition: --colorPrimary 0.5s ease; /* ... */ } .gradientBox:hover { --colorPrimary: red /* ... */ }

Il browser non sa come gestire la transizione del gradiente, ma sa come gestire le transizioni di colore perché la proprietà personalizzata è specificata come tipo <color> . Su un browser che supporta Houdini, si verificherà una transizione del gradiente quando l'elemento viene posizionato con il mouse. La percentuale di posizione del gradiente può anche essere sostituita con la proprietà personalizzata CSS (registrata come tipo <percentage> ) e aggiunta a una transizione come nell'esempio.

Se registerProperty viene rimosso e una normale proprietà personalizzata CSS viene registrata in un selettore :root , la transizione del gradiente non funzionerà. È necessario che registerProperty venga utilizzato in modo che il browser sappia che dovrebbe trattarlo come colore.

Nella futura implementazione di questa API, sarebbe possibile registrare una proprietà personalizzata direttamente in CSS.

 @property --colorPrimary { syntax: "<color>"; inherits: false; initial-value: blue; }

Esempio

Questo semplice esempio mostra il colore del gradiente e la transizione di posizione sull'evento al passaggio del mouse utilizzando le proprietà personalizzate CSS registrate rispettivamente per colore e posizione. Il codice sorgente completo è disponibile nel repository di esempio.

Colore e posizione del gradiente animati utilizzando l'API di proprietà e valori personalizzati. Ritardo per ogni proprietà aggiunta per effetto nella proprietà di transizione CSS. (Grande anteprima)

Rilevamento delle caratteristiche

 if (CSS.registerProperty) { /* ... */ }

Stato delle specifiche W3C

  • Bozza di lavoro: pubblicata per la revisione da parte della comunità

Supporto del browser

Google Chrome Microsoft Edge Browser Opera Firefox Safari
Supportato Supportato Supportato Non supportato Non supportato

Fonte dati: Houdini è ancora pronto?

API delle metriche dei caratteri

L'API Font Metrics è ancora in una fase iniziale di sviluppo, quindi le sue specifiche potrebbero cambiare in futuro. Nella sua bozza attuale, l' API Font Metrics fornirà metodi per misurare le dimensioni degli elementi di testo che vengono visualizzati sullo schermo al fine di consentire agli sviluppatori di influenzare il modo in cui gli elementi di testo vengono visualizzati sullo schermo. Questi valori sono difficili o impossibili da misurare con le funzionalità attuali, quindi questa API consentirà agli sviluppatori di creare più facilmente funzionalità CSS relative al testo e ai caratteri. Il troncamento dinamico del testo su più righe è un esempio di una di queste funzionalità.

Stato delle specifiche W3C

  • Raccolta di idee: nessuna bozza di specifica presentata al momento

Supporto del browser

Google Chrome Microsoft Edge Browser Opera Firefox Safari
Non supportato Non supportato Non supportato Non supportato Non supportato

Fonte dati: Houdini è ancora pronto?

Worklets

Prima di passare alle altre API, è importante spiegare il concetto di Worklets. I worklet sono script che vengono eseguiti durante il rendering e sono indipendenti dall'ambiente JavaScript principale. Sono un punto di estensione per i motori di rendering. Sono progettati per il parallelismo (con 2 o più istanze) e indipendenti dai thread, hanno un accesso ridotto all'ambito globale e vengono richiamati dal motore di rendering quando necessario. I worklet possono essere eseguiti solo su HTTPS (nell'ambiente di produzione) o su localhost (per scopi di sviluppo).

Houdini introduce i seguenti Worklet per estendere il motore di rendering del browser:

  • Paint Worklet - API Paint
  • Worklet di animazione - API di animazione
  • Worklet di layout - API di layout

API di pittura

L'API Paint consente agli sviluppatori di utilizzare le funzioni JavaScript per disegnare direttamente sullo sfondo, sul bordo o sul contenuto di un elemento utilizzando il contesto di rendering 2D, che è un sottoinsieme dell'API Canvas HTML5. L'API Paint utilizza Paint Worklet per disegnare un'immagine che risponde dinamicamente alle modifiche nei CSS (modifiche alle variabili CSS, ad esempio). Chiunque abbia familiarità con l'API Canvas si sentirà come a casa con l'API Paint di Houdini.

Sono necessari diversi passaggi per definire un Paint Worklet:

  1. Scrivere e registrare un Paint Worklet utilizzando la funzione registerPaint
  2. Richiamare il file Worklet nel file HTML o il file JavaScript principale utilizzando la funzione CSS.paintWorklet.addModule
  3. Utilizzare la funzione paint() in CSS con un nome Worklet e argomenti di input opzionali.

Diamo un'occhiata alla funzione registerPaint che viene utilizzata per registrare un Paint Worklet e definirne la funzionalità.

 registerPaint("paintWorketExample", class { static get inputProperties() { return ["--myVariable"]; } static get inputArguments() { return ["<color>"]; } static get contextOptions() { return {alpha: true}; } paint(ctx, size, properties, args) { /* ... */ } });

La funzione registerPaint è composta da diverse parti:

  • inputProperties :
    Un array di proprietà personalizzate CSS di cui il Worklet terrà traccia. Questa matrice rappresenta le dipendenze di un worklet di disegno.
  • inputArguments :
    Un array di argomenti di input che possono essere passati dalla funzione paint dall'interno del CSS.
  • contextOptions : consente o meno l'opacità per i colori. Se impostato su false , tutti i colori verranno visualizzati con opacità completa.
  • paint : la funzione principale che fornisce i seguenti argomenti:
    • ctx : contesto di disegno 2D, quasi identico al contesto di disegno 2D di Canvas API.
    • size : un oggetto contenente la larghezza e l'altezza dell'elemento. I valori sono determinati dal processo di rendering del layout. La dimensione della tela è la stessa della dimensione effettiva dell'elemento.
    • properties : variabili di input definite in inputProperties
    • args : un array di argomenti di input passati nella funzione paint in CSS

Dopo che il Worklet è stato registrato, deve essere richiamato nel file HTML fornendo semplicemente un percorso al file.

 CSS.paintWorklet.addModule("path/to/worklet/file.js");

Qualsiasi Worklet può anche essere aggiunto da un URL esterno (da una Content Delivery Network, per esempio) che li rende modulari e riutilizzabili.

 CSS.paintWorklet.addModule("https://url/to/worklet/file.js");

Dopo che il Worklet è stato chiamato, può essere utilizzato all'interno dei CSS usando la funzione paint . Questa funzione accetta il nome registrato del Worklet come primo argomento di input e ogni argomento di input che lo segue è un argomento personalizzato che può essere passato a un Worklet (definito all'interno di inputArguments del inputArguments ). Da quel momento, il browser determina quando chiamare il Worklet e a quali azioni utente e valore delle proprietà personalizzate CSS cambiano a cui rispondere.

 .exampleElement { /* paintWorkletExample - name of the worklet blue - argument passed to a Worklet */ background-image: paint(paintWorketExample, blue); }

Esempio

L'esempio seguente mostra l'API Paint e la riutilizzabilità e la modularità generali di Worklet. Utilizza il ripple Worklet direttamente dal repository di Google Chrome Labs e viene eseguito su un elemento diverso con stili diversi. Il codice sorgente completo è disponibile nel repository di esempio.

Esempio di effetto Ripple (usa Ripple Worklet di Google Chrome Labs) (Anteprima grande)

Rilevamento delle caratteristiche

 if ("paintWorklet" in CSS) { /* ... */ } @supports(background:paint(paintWorketExample)){ /* ... */ }

Stato delle specifiche W3C

  • Raccomandazione del candidato: progetto di lavoro stabile pronto per l'attuazione

Supporto del browser

Google Chrome Microsoft Edge Browser Opera Firefox Safari
Supportato Supportato Supportato Non supportato Non supportato

Fonte dati: Houdini è ancora pronto?

API di animazione

L'API Animation estende le animazioni Web con opzioni per ascoltare vari eventi (scorrimento, passaggio del mouse, clic, ecc.) e migliora le prestazioni eseguendo le animazioni sul proprio thread dedicato utilizzando un Animation Worklet. Consente all'azione dell'utente di controllare il flusso dell'animazione che viene eseguito in modo efficiente e non bloccante.

Come ogni Worklet, Animation Worklet deve essere prima registrato.

 registerAnimator("animationWorkletExample", class { constructor(options) { /* ... */ } animate(currentTime, effect) { /* ... */ } });

Questa classe è composta da due funzioni:

  • constructor : chiamato quando viene creata una nuova istanza. Usato per la configurazione generale.
  • animate : la funzione principale che contiene la logica di animazione. Fornisce i seguenti argomenti di input:
    • currentTime : il valore dell'ora corrente dalla timeline definita
    • effect : una serie di effetti utilizzati da questa animazione

Dopo che il Worklet di animazione è stato registrato, è necessario includerlo nel file JavaScript principale , definire l'animazione (elemento, fotogrammi chiave, opzioni) e creare un'istanza dell'animazione con la sequenza temporale selezionata. I concetti della sequenza temporale e le basi dell'animazione Web verranno spiegati nella sezione successiva.

 /* Include Animation Worklet */ await CSS.animationWorklet.addModule("path/to/worklet/file.js");; /* Select element that's going to be animated */ const elementExample = document.getElementById("elementExample"); /* Define animation (effect) */ const effectExample = new KeyframeEffect( elementExample, /* Selected element that's going to be animated */ [ /* ... */ ], /* Animation keyframes */ { /* ... */ }, /* Animation options - duration, delay, iterations, etc. */ ); /* Create new WorkletAnimation instance and run it */ new WorkletAnimation( "animationWorkletExample" /* Worklet name */ effectExample, /* Animation (effect) timeline */ document.timeline, /* Input timeline */ {}, /* Options passed to constructor */ ).play(); /* Play animation */

Mappatura della sequenza temporale

L'animazione Web si basa su linee temporali e sulla mappatura dell'ora corrente su una linea temporale dell'ora locale di un effetto . Ad esempio, diamo un'occhiata a un'animazione lineare ripetuta con 3 fotogrammi chiave (inizio, metà, ultimo) che viene eseguita 1 secondo dopo il caricamento di una pagina (ritardo) e con una durata di 4 secondi.

La sequenza temporale degli effetti dell'esempio sarebbe simile a questa (con la durata di 4 secondi senza ritardo):

Timeline degli effetti (durata 4s) Fotogramma chiave
0 ms Primo fotogramma chiave: inizia l'animazione
2000 ms Fotogramma chiave centrale - animazione in corso
4000 ms Ultimo fotogramma chiave: l'animazione termina o viene ripristinata al primo fotogramma chiave

Per comprendere meglio effect.localTime , impostando il suo valore su 3000 ms (tenendo conto di 1000 ms di ritardo), l'animazione risultante sarà bloccata su un fotogramma chiave centrale nella timeline effettiva (ritardo di 1000 ms + 2000 ms per un fotogramma chiave centrale). Lo stesso effetto si verificherà impostando il valore su 7000 ms e 11000 ms perché l'animazione si ripete a intervalli di 4000 ms (durata dell'animazione).

 animate(currentTime, effect) { effect.localTime = 3000; // 1000ms delay + 2000ms middle keyframe }

Non si verifica alcuna animazione quando si ha un valore effect.localTime costante perché l'animazione è bloccata in un fotogramma chiave specifico. Per animare correttamente un elemento, il suo effect.localTime deve essere dinamico. È necessario che il valore sia una funzione che dipende dall'argomento di input currentTime o da qualche altra variabile.

Il codice seguente mostra una rappresentazione funzionale della mappatura 1:1 (funzione lineare) di una sequenza temporale per l'effetto dell'ora locale.

 animate(currentTime, effect) { effect.localTime = currentTime; // y = x linear function }
Sequenza temporale ( document.timeline ) Ora locale dell'effetto mappato Fotogramma chiave
startTime + 0ms (tempo trascorso) startTime + 0ms Primo
startTime + 1000ms (tempo trascorso) startTime + 1000 ms (ritardo) + 0 ms Primo
startTime + 3000ms (tempo trascorso) startTime + 1000 ms (ritardo) + 2000 ms Mezzo
startTime + 5000ms (tempo trascorso) startTime + 1000 ms (ritardo) + 4000 ms Ultimo / Primo
startTime + 7000ms (tempo trascorso) startTime + 1000 ms (ritardo) + 6000 ms Mezzo
startTime + 9000ms (tempo trascorso) startTime + 1000 ms (ritardo) + 8000 ms Ultimo / Primo

La sequenza temporale non è limitata alla mappatura 1:1 per l'ora locale dell'effetto. L'API di animazione consente agli sviluppatori di manipolare la mappatura della sequenza temporale nella funzione animate utilizzando le funzioni JavaScript standard per creare linee temporali complesse. Anche l'animazione non deve comportarsi allo stesso modo in ogni iterazione (se l'animazione viene ripetuta).

L'animazione non deve dipendere dalla sequenza temporale del documento che inizia a contare solo i millisecondi dal momento in cui viene caricato. Le azioni dell'utente come gli eventi di scorrimento possono essere utilizzate come sequenza temporale per l'animazione utilizzando un oggetto ScrollTimeline . Ad esempio, un'animazione può iniziare quando un utente è passato a 200 pixel e può terminare quando un utente è passato a 800 pixel su uno schermo.

 const scrollTimelineExample = new ScrollTimeline({ scrollSource: scrollElement, /* DOM element whose scrolling action is being tracked */ orientation: "vertical", /* Scroll direction */ startScrollOffset: "200px", /* Beginning of the scroll timeline */ endScrollOffset: "800px", /* Ending of the scroll timeline */ timeRange: 1200, /* Time duration to be mapped to scroll values*/ fill: "forwards" /* Animation fill mode */ }); ...

L'animazione si adatterà automaticamente alla velocità di scorrimento dell'utente e rimarrà fluida e reattiva. Poiché i worklet di animazione escono dal thread principale e sono collegati al motore di rendering di un browser, l'animazione che dipende dallo scorrimento dell'utente può essere eseguita senza problemi ed essere molto performante.

Esempio

L'esempio seguente mostra come un'implementazione di una sequenza temporale non lineare. Utilizza la funzione gaussiana modificata e applica l'animazione di traslazione e rotazione con la stessa sequenza temporale. Il codice sorgente completo è disponibile nel repository di esempio.

Animazione creata con l'API di animazione che utilizza la mappatura temporale della funzione gaussiana modificata (anteprima grande)

Rilevamento delle caratteristiche

 if (CSS.animationWorklet) { /* ... */ }

Stato delle specifiche W3C

  • Prima bozza di lavoro pubblica: pronta per la revisione della comunità, soggetta a modifiche delle specifiche

Supporto del browser

Google Chrome Microsoft Edge Browser Opera Firefox Safari
Sostegno parziale (*) Sostegno parziale (*) Sostegno parziale (*) Non supportato Non supportato

* supportato con il flag "Caratteristiche della piattaforma Web sperimentale" abilitato.

Fonte dati: Houdini è ancora pronto?

API di layout

L'API Layout consente agli sviluppatori di estendere il processo di rendering del layout del browser definendo nuove modalità di layout che possono essere utilizzate nella proprietà CSS di display . Layout API introduce nuovi concetti, è molto complesso e offre molte opzioni per lo sviluppo di algoritmi di layout personalizzati.

Analogamente ad altri Worklet, è necessario prima registrare e definire il Worklet di layout.

 registerLayout('exampleLayout', class { static get inputProperties() { return ['--exampleVariable']; } static get childrenInputProperties() { return ['--exampleChildVariable']; } static get layoutOptions() { return { childDisplay: 'normal', sizing: 'block-like' }; } intrinsicSizes(children, edges, styleMap) { /* ... */ } layout(children, edges, constraints, styleMap, breakToken) { /* ... */ } });

Il registro del worklet contiene i seguenti metodi:

  • inputProperties :
    Un array di proprietà personalizzate CSS di cui il Worklet terrà traccia e che appartiene a un elemento Parent Layout, cioè l'elemento che chiama questo layout. Questa matrice rappresenta le dipendenze di un Worklet di layout.
  • childrenInputProperties :
    Un array di proprietà personalizzate CSS di cui il Worklet terrà traccia e che appartengono agli elementi figlio di un elemento Parent Layout, cioè i figli degli elementi che impostano questo layout.
  • layoutOptions : definisce le seguenti proprietà del layout:
    • childDisplay : può avere un valore predefinito di block o normal . Determina se le caselle verranno visualizzate come blocchi o in linea.
    • sizing : può avere un valore predefinito di block-like o manual . Indica al browser di pre-calcolare la dimensione o di non pre-calcolare (a meno che una dimensione non sia impostata esplicitamente), rispettivamente.
  • intrinsicSizes : definisce come una scatola o il suo contenuto si inserisce in un contesto di layout.
    • children : elementi figlio di un elemento Parent Layout, ovvero i figli dell'elemento che chiama questo layout.
    • edges : Layout Bordi di una scatola
    • styleMap : stili OM digitati di una casella
  • layout : la funzione principale che esegue un layout.
    • children : elementi figlio di un elemento Parent Layout, ovvero i figli dell'elemento che chiama questo layout.
    • edges : Layout Bordi di una scatola
    • constraints : vincoli di un Layout Genitore
    • styleMap : stili OM digitati di una casella
    • breakToken : token di interruzione utilizzato per riprendere un layout in caso di impaginazione o stampa.

Come nel caso di un'API Paint, il motore di rendering del browser determina quando viene chiamato il worklet paint. Deve solo essere aggiunto a un file HTML o JavaScript principale.

 CSS.layoutWorklet.addModule('path/to/worklet/file.js');

E, infine, deve essere referenziato in un file CSS

 .exampleElement { display: layout(exampleLayout); }

Come l'API Layout esegue il layout

Nell'esempio precedente, exampleLayout è stato definito utilizzando l'API Layout.

 .exampleElement { display: layout(exampleLayout); }

Questo elemento è chiamato layout padre che è racchiuso con bordi layout che consiste di spazi interni, bordi e barre di scorrimento. Il layout padre è costituito da elementi figlio chiamati Layout correnti . I layout attuali sono gli elementi di destinazione effettivi il cui layout può essere personalizzato utilizzando l'API Layout. Ad esempio, quando si utilizza display: flex; su un elemento, i suoi figli vengono riposizionati per formare il layout flessibile. Questo è simile a quello che viene fatto con l'API Layout.

Ogni layout corrente è costituito da layout figlio che è un algoritmo di layout per LayoutChild (elemento, ::before e ::after pseudo-elementi) e LayoutChild è una casella generata da CSS che contiene solo dati di stile (nessun dato di layout). Gli elementi LayoutChild vengono creati automaticamente dal motore di rendering del browser in fase di stile. Layout Child può generare un frammento che esegue effettivamente le azioni di rendering del layout.

Esempio

Analogamente all'esempio dell'API Paint, questo esempio importa un Worklet di layout in muratura direttamente dal repository di Google Chrome Labs, ma in questo esempio viene utilizzato con il contenuto dell'immagine anziché il testo. Il codice sorgente completo è disponibile nel repository di esempio.

Esempio di layout in muratura (utilizza Masonry Worklet di Google Chrome Labs (anteprima grande)

Rilevamento delle caratteristiche

 if (CSS.layoutWorklet) { /* ... */ }

Stato delle specifiche W3C

  • Prima bozza di lavoro pubblica: pronta per la revisione della comunità, soggetta a modifiche delle specifiche

Supporto del browser

Google Chrome Microsoft Edge Browser Opera Firefox Safari
Sostegno parziale (*) Sostegno parziale (*) Sostegno parziale (*) Non supportato Non supportato

* supportato con il flag "Caratteristiche della piattaforma Web sperimentale" abilitato.

Fonte dati: Houdini è ancora pronto?

Houdini e il miglioramento progressivo

Anche se CSS Houdini non ha ancora un supporto ottimale per il browser, può essere utilizzato oggi pensando a un miglioramento progressivo. Se non hai familiarità con il miglioramento progressivo, varrebbe la pena dare un'occhiata a questo pratico articolo che lo spiega davvero bene. Se decidi di implementare Houdini nel tuo progetto oggi, ci sono alcune cose da tenere a mente:

  • Utilizzare il rilevamento delle funzionalità per evitare errori.
    Ogni API e Worklet Houdini offre un modo semplice per verificare se è disponibile nel browser. Utilizza il rilevamento delle funzionalità per applicare i miglioramenti Houdini solo ai browser che lo supportano ed evitare errori.
  • Usalo solo per la presentazione e il miglioramento visivo.
    Gli utenti che stanno navigando in un sito Web su un browser che non supporta ancora Houdini dovrebbero avere accesso al contenuto e alle funzionalità principali del sito Web. L'esperienza utente e la presentazione dei contenuti non dovrebbero dipendere dalle funzionalità di Houdini e dovrebbero avere un affidabile fallback.
  • Utilizza un CSS di riserva standard.
    Ad esempio, le normali proprietà personalizzate CSS possono essere utilizzate come fallback per gli stili definiti utilizzando l'API di proprietà e valori personalizzati.

Concentrati prima sullo sviluppo di un'esperienza utente del sito Web affidabile e performante, quindi utilizza le funzionalità di Houdini per scopi decorativi come miglioramento progressivo.

Conclusione

Le API Houdini consentiranno finalmente agli sviluppatori di mantenere il codice JavaScript utilizzato per la manipolazione e la decorazione dello stile più vicino alla pipeline di rendering del browser, ottenendo prestazioni e stabilità migliori. Consentendo agli sviluppatori di collegarsi al processo di rendering del browser, saranno in grado di sviluppare vari polyfill CSS che possono essere facilmente condivisi, implementati e, potenzialmente, aggiunti alle specifiche CSS stesse. Houdini renderà anche sviluppatori e designer meno vincolati dalle limitazioni CSS quando lavorano su stili, layout e animazioni, dando vita a nuove deliziose esperienze web.

Le funzionalità CSS Houdini possono essere aggiunte ai progetti oggi, ma rigorosamente tenendo conto del progressivo miglioramento. Ciò consentirà ai browser che non supportano le funzionalità di Houdini di visualizzare il sito Web senza errori e offrire un'esperienza utente ottimale.

Sarà emozionante vedere cosa verrà in mente la comunità di sviluppatori man mano che Houdini guadagna terreno e un migliore supporto del browser. Ecco alcuni fantastici esempi di esperimenti API Houdini dalla community:

  • Esperimenti CSS Houdini
  • Introduzione interattiva ai CSS Houdini
  • Esempi Houdini di Google Chrome Labs

Riferimenti

  • Bozze delle specifiche del W3C Houdini
  • Stato di Houdini (Chrome Dev Summit 2018)
  • Worklet di animazione di Houdini - Sviluppatori Google
  • Introduzione interattiva ai CSS Houdini