Houdini - Demistificazione dei CSS

Hai mai pensato alla quantità di lavoro svolto dal CSS? Modifichi un singolo e all'improvviso il tuo intero sito web appare in un layout diverso. È un po' magico. Finora noi, la community di sviluppatori web, abbiamo solo potuto osservare e osservare la magia. E se volessimo trovare la nostra magia? E se volessimo diventare il mago?

Entra Houdini!

La task force di Houdini è composta da ingegneri di Mozilla, Apple, Opera, Microsoft, HP, Intel e Google collaborano per esporre determinate parti del il motore CSS agli sviluppatori web. La task force sta lavorando a una raccolta di bozze con l'obiettivo di farle accettare dal W3C in modo che diventino vere e proprie bozze web standard. Si sono posti alcuni obiettivi di alto livello, li hanno trasformati in bozze delle specifiche che a loro volta hanno dato vita a una serie di supporti, e bozze delle specifiche di livello inferiore.

La raccolta di queste bozze è il termine con cui si parla di "Houdini". Al momento della stesura di questo documento, l'elenco delle bozze è incomplete e alcune delle bozze sono semplici segnaposto.

Le specifiche

Worklet (specifiche)

I worklet da soli non sono davvero utili. Sono un concetto introdotto per rendere possibili molte delle bozze successive. Se hai pensato ai web worker quando leggi "worklet", non ti sbagli. Questi concetti presentano molti sovrapposizioni concettuali. E questo perché una cosa nuova quando abbiamo già dei lavoratori?

L'obiettivo di Houdini è esporre nuove API per consentire agli sviluppatori web di collegare il proprio codice al motore CSS e i sistemi circostanti. Probabilmente non è realistico supporre che alcuni di questi i frammenti di codice dovranno essere eseguiti ogni. singolo. frame. Alcuni di loro devono per definizione. Citazione delle specifiche dei worker web:

Ciò significa che i web worker non sono attuabili per le cose che Houdini intende fare. Pertanto, sono stati inventati i worklet. I worklet utilizzano le classi ES2015 per definire un insieme di metodi, le cui firme sono predefinite il tipo di worklet. Sono leggeri e di breve durata.

API CSS Paint (specifiche)

L'API Paint è abilitata per impostazione predefinita in Chrome 65. Leggi un'introduzione dettagliata.

Worklet del compositore

L'API qui descritta è obsoleta. Il worklet del compositore è stata riprogettata e viene ora proposta come "Worklet dell'animazione". Scopri di più sul iterazione attuale dell'API.

Anche se le specifiche del worklet del compositore sono state spostate in WICG è la specifica che mi entusiasma di più. Alcune operazioni sono affidate alla scheda grafica del computer dal CSS di rete, anche se dipende dalla scheda grafica e dal dispositivo in in generale.

In genere un browser prende la struttura DOM e, in base a criteri specifici, decide di assegnare ad alcuni rami e sottoalberi il proprio strato. Questi sottoalberi si dipingono su di essi (forse usando un foglio di lavoro nel futuro). Come ultimo passaggio, tutti questi singoli livelli, ora dipinti, vengono sovrapposti e posizionati uno sopra l'altro, rispettando gli indici z, le trasformazioni 3D e per ottenere l'immagine finale visibile sullo schermo. Questo processo è chiamata compositing e che viene eseguita dal compositore.

Il vantaggio del processo di composizione è che non occorre fare gli elementi si ridipingono quando la pagina scorre un po'. Invece, può riutilizzare i livelli del frame precedente ed eseguire nuovamente il compositore con la posizione di scorrimento aggiornata. In questo modo tutto è veloce. In questo modo possiamo raggiungere i 60 f/s.

Worklet del compositore.

Come suggerisce il nome, il worklet del compositore ti consente di eseguire l'hook e influenzano il modo in cui lo strato di un elemento, che è già stato dipinto, viene posizionate e sovrapponibili agli altri livelli.

Per ottenere qualcosa in più specifiche, puoi indicare al browser che vuoi eseguire l'aggancio al processo per un determinato nodo DOM e può richiedere l'accesso a determinati attributi come posizione di scorrimento: transform o opacity. Questa operazione forza l'attivazione dell'elemento nel suo il tuo livello e su ogni frame viene chiamato il tuo codice. Puoi spostare il livello manipolando gli strati, trasformandoli e cambiandone gli attributi (come opacity) che ti consentono di fare cose stravaganti a 60 fps.

Ecco un'implementazione completa per lo scorrimento con parallasse, utilizzando il compositore un worklet.

// main.js
window.compositorWorklet.import('worklet.js')
    .then(function() {
    var animator = new CompositorAnimator('parallax');
    animator.postMessage([
        new CompositorProxy($('.scroller'), ['scrollTop']),
        new CompositorProxy($('.parallax'), ['transform']),
    ]);
    });

// worklet.js
registerCompositorAnimator('parallax', class {
    tick(timestamp) {
    var t = self.parallax.transform;
    t.m42 = -0.1 * self.scroller.scrollTop;
    self.parallax.transform = t;
    }

    onmessage(e) {
    self.scroller = e.data[0];
    self.parallax = e.data[1];
    };
});

Robert Flack ha scritto un polyfill per i un worklet del compositore in modo da poterlo provare, ovviamente con un un maggiore impatto sulle prestazioni.

Worklet di layout (specifiche)

È stata proposta la prima bozza della specifica reale. Implementazione è un bel po' di assenza.

Anche in questo caso, la specifica è praticamente vuota, ma il concetto è interessante: scrivi il tuo layout. Il worklet di layout dovrebbe consentirti eseguire il comando display: layout('myLayout') ed eseguire JavaScript per organizzare secondari nel riquadro del nodo.

Ovviamente, l'esecuzione di un'implementazione JavaScript completa del layout flex-box di CSS è più lenta rispetto all'esecuzione di un'implementazione nativa equivalente, ma è facile immagina uno scenario in cui tagliare le curve può produrre un miglioramento delle prestazioni. Immagina un costituito da niente che non siano riquadri, come Windows 10 o un layout. Il posizionamento assoluto e fisso non viene utilizzato, così come z-index. che gli elementi si sovrappongano o non presentino alcun tipo di bordo o overflow. Possibilità di ignorare tutti questi controlli sul relayout potrebbero migliorare le prestazioni.

registerLayout('random-layout', class {
    static get inputProperties() {
        return [];
    }
    static get childrenInputProperties() {
        return [];
    }
    layout(children, constraintSpace, styleMap) {
        const width = constraintSpace.width;
        const height = constraintSpace.height;
        for (let child of children) {
            const x = Math.random()*width;
            const y = Math.random()*height;
            const constraintSubSpace = new ConstraintSpace();
            constraintSubSpace.width = width-x;
            constraintSubSpace.height = height-y;
            const childFragment = child.doLayout(constraintSubSpace);
            childFragment.x = x;
            childFragment.y = y;
        }

        return {
            minContent: 0,
            maxContent: 0,
            width: width,
            height: height,
            fragments: [],
            unPositionedChildren: [],
            breakToken: null
        };
    }
});

CSSOM digitato (specifica)

Il CSSOM digitato (CSS Object Model o Cascading Style Sheets Object Model) indirizza a problema che probabilmente tutti abbiamo incontrato e appena imparato a sopportare. Facciamo un'illustrazione con una riga di JavaScript:

    $('#someDiv').style.height = getRandomInt() + 'px';

Stiamo facendo dei calcoli, convertendo un numero in stringa per aggiungere un'unità e avere il browser analizza la stringa e la converte nuovamente in numero per il motore CSS. Questo comportamento diventa ancora più brutto quando manipoli le trasformazioni con JavaScript. Addio, Il CSS sta per iniziare a digitare.

Questa bozza è una delle più mature e un polyfill è sono già in fase di sviluppo. (Disclaimer: l'uso del polyfill consente ovviamente e aggiungere ancora più overhead di calcolo. Lo scopo è dimostrare la praticità dell'API).

Invece delle stringhe, lavorerai sull'elemento StylePropertyMap, dove ogni attributo CSS ha la propria chiave e il tipo di valore corrispondente. Attributi come width hanno LengthValue come tipo di valore. Un LengthValue è un dizionario di tutte le unità CSS, come em, rem, px, percent e così via. Impostazione height: calc(5px + 5%) restituirebbe un LengthValue{px: 5, percent: 5}. Alcune proprietà come box-sizing accettano solo determinate parole chiave e pertanto hanno un Tipo di valore KeywordValue. A questo punto, è stato possibile verificare la validità di questi attributi in fase di runtime.

<div style="width: 200px;" id="div1"></div>
<div style="width: 300px;" id="div2"></div>
<div id="div3"></div>
<div style="margin-left: calc(5em + 50%);" id="div4"></div>
var w1 = $('#div1').styleMap.get('width');
var w2 = $('#div2').styleMap.get('width');
$('#div3').styleMap.set('background-size',
    [new SimpleLength(200, 'px'), w1.add(w2)])
$('#div4')).styleMap.get('margin-left')
    // => {em: 5, percent: 50}

Proprietà e valori

(specifiche)

Conosci le proprietà personalizzate CSS (o il relativo alias non ufficiale "Variabili CSS")? Questi sono loro, ma con i tipi! Finora le variabili potevano avere solo valori di stringa e ha utilizzato un semplice approccio di ricerca e sostituzione. Questa bozza ti consente di non specificare solo un tipo per le variabili, ma anche un valore predefinito influenzare il comportamento dell'ereditarietà mediante un'API JavaScript. Tecnicamente, questo consente inoltre l'animazione delle proprietà personalizzate con transizioni CSS standard e animazioni, che a loro volta vengono prese in considerazione.

["--scale-x", "--scale-y"].forEach(function(name) {
document.registerProperty({
    name: name,
    syntax: "<number>",
    inherits: false,
    initialValue: "1"
    });
});

Metriche relative ai caratteri

Le metriche relative ai caratteri sono esattamente come appaiono. Che cos'è il riquadro di delimitazione (o riquadri di delimitazione) quando eseguo il rendering della stringa X con il carattere Y di dimensione Z? Cosa devo fare se uso annotazioni rubino? Questa è stata molto richiesta e Houdini finalmente dovrebbe e realizzino questi desideri.

Ma non è tutto!

L'elenco delle bozze di Houdini contiene anche altre specifiche, ma il futuro è sono piuttosto incerte e non sono molto altro che segnaposto per idee. Gli esempi includono comportamenti di overflow personalizzati, API dell'estensione della sintassi CSS, estensione del comportamento di scorrimento nativo e altrettanti ambiziosi che consentono cose sulla piattaforma web che prima non erano possibili.

Demo

Ho reso open source il codice per la demo (demo dal vivo con polyfill).