Houdini – CSS entmystifizieren

Haben Sie schon einmal darüber nachgedacht, wie viel Arbeit CSS macht? Sie ändern einen einzelnen und Ihre gesamte Website erscheint plötzlich in einem anderen Layout. Es ist eine Art Magie. Bisher haben wir – die Community der Webentwickler – nur die Magie miterleben und beobachten konnten. Wie gehen wir vor, wenn wir unsere eigene Magie? Was ist, wenn wir Magier werden wollen?

Also, Houdini!

Die Houdini-Taskforce besteht aus Ingenieuren von Mozilla, Apple, Opera Microsoft, HP, Intel und Google arbeiten zusammen, um bestimmte Bereiche des über die CSS-Engine. Die Taskforce arbeitet an einer Sammlung von Entwürfe mit dem Ziel, sie vom W3C zu akzeptieren, damit sie zu echten Websites werden. zu entwickeln. Sie setzten sich einige übergeordnete Ziele, machten sie Spezifikationsentwürfe erstellt, die wiederum unterstützende, und untergeordnete Spezifikationsentwürfe.

Die Sammlung dieser Entwürfe ist in der Regel dann gemeint, wenn jemand über „Houdini“. Zum Zeitpunkt der Entstehung dieses Artikels war die Liste der Entwürfe unvollständig sein und einige Entwürfe sind reine Platzhalter.

Spezifikationen

Worklets (Spezifikation)

Worklets an sich sind nicht sehr nützlich. Sie sind ein Konzept, die später viele Entwürfe ermöglichen. Wenn Sie an Web Worker gedacht haben, „Worklet“ gelesen haben, liegen Sie nicht falsch. Es gibt viele konzeptionelle Überschneidungen. Warum? etwas Neues, wenn wir bereits Arbeiter haben?

Houdini möchte neue APIs damit Webentwickler ihren eigenen Code in die CSS-Engine und die Umgebungssysteme. Die Annahme, dass einige davon müssen Codefragmente jeden Tag ausgeführt werden. Single. Frame dargestellt wird. Einige müssen durch Definition. Zitieren Sie die Web Worker-Spezifikation:

<ph type="x-smartling-placeholder">

Das bedeutet, dass Web Worker für die von Houdini geplanten Aufgaben nicht geeignet sind. Aus diesem Grund wurden Worklets erfunden. Worklets nutzen ES2015-Klassen, um zu definieren, eine Sammlung von Methoden, deren Signaturen vordefiniert werden, den Typ des Worklets. Sie sind leicht und kurzlebig.

CSS Paint API (Spezifikation)

Die Paint API ist in Chrome 65 standardmäßig aktiviert. Lesen Sie die ausführliche Einführung.

Compositor-Worklet

Die hier beschriebene API ist veraltet. Compositor-Worklet enthält wurde umgestaltet und wird jetzt als "Animation Worklet" vorgeschlagen. Weitere Informationen finden Sie auf der aktuelle Version der API

Obwohl die Compositor-Worklet-Spezifikation in die WICG verschoben wurde, die mich am meisten begeistern. Einige Vorgänge werden vom CSS für die Grafikkarte Ihres Computers ausgelagert. Das hängt jedoch sowohl von Ihrer Grafikkarte als auch Ihrem Gerät ab, allgemein.

Ein Browser verwendet in der Regel den DOM-Baum und anhand bestimmter Kriterien beschließt, einigen Zweigen und Unterbäumen eine eigene Ebene zu geben. Diese Unterbäume streichen sich selbst darauf an (vielleicht mit einem Farb-Worklet im in der Zukunft. Als letzten Schritt werden alle diese einzelnen, jetzt gemalten Schichten, übereinander und übereinander positioniert, wobei Z-Indizes, 3D-Transformationen und um das endgültige Bild zu erhalten, das auf Ihrem Bildschirm sichtbar ist. Dieser Prozess ist wird als Compositing bezeichnet und vom Compositor ausgeführt.

Der Vorteil des Compositing-Prozesses besteht darin, dass Sie nicht alle werden die Elemente selbst aktualisiert, wenn auf der Seite ein kleines bisschen gescrollt wird. Stattdessen müssen Sie kann die Layers aus dem vorherigen Frame wiederverwenden und den Compositor einfach erneut ausführen mit die aktualisierte Scrollposition. Das macht alles schnell. Dadurch erreichen wir 60 fps.

Compositor-Worklet.

Wie der Name schon sagt, können Sie mit dem Compositor-Worklet eine Verknüpfung mit dem Compositor herstellen. und beeinflussen, wie die Ebene eines Elements, die bereits gezeichnet wurde, die über die anderen Ebenen gelegt werden.

Um mehr Informationen zu erhalten, können Sie dem Browser mitteilen, dass Sie mit dem für einen bestimmten DOM-Knoten und kann Zugriff auf bestimmte Attribute anfordern, Scrollposition, transform oder opacity. Dadurch wird dieses Element auf seine und in jedem Frame wird Ihr Code aufgerufen. Sie können die Ebene verschieben durch Bearbeiten der Layers transformieren und ihre Attribute ändern (z. B. opacity) mit beeindruckenden 60 fps.

Hier ist eine vollständige Implementierung für das Parallaxe-Scrollen mithilfe des Compositors. Worklet zu erstellen.

// 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 hat einen Polyfill für den Compositor-Worklet, damit Sie es ausprobieren können – natürlich mit einer Auswirkungen auf die Leistung.

Layout-Worklet (Spezifikation)

Der erste echte Spezifikationsentwurf wurde vorgeschlagen. Implementierung einen schönen Moment entfernt.

Auch hier ist die Spezifikation praktisch leer, aber das Konzept ist Ihr eigenes Layout zu schreiben! Das Layout-Worklet soll Ihnen dabei helfen, um display: layout('myLayout') und führen Sie Ihren JavaScript-Code aus, um untergeordnete Elemente im Feld des Knotens.

Natürlich führt das Ausführen einer vollständigen JavaScript-Implementierung des flex-box-Layouts von CSS langsamer ist als eine gleichwertige native Implementierung, aber es ist einfach, Stellen Sie sich ein Szenario vor, in dem das Abschneiden zu einer Leistungssteigerung führen kann. Stellen Sie sich vor, die ausschließlich aus Kacheln besteht, wie zum Beispiel Windows 10 oder ein Layout. Sowohl die absolute als auch die feste Positionierung wird weder verwendet noch z-index Elemente überlappen sich nie oder haben irgendeine Art von Rahmen oder Überlauf. Das Überspringen all diese Prüfungen des Layouts zu einer Leistungssteigerung führen.

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
        };
    }
});

Typisiertes CSSOM (spec)

<ph type="x-smartling-placeholder">

Ein typisiertes CSSOM (CSS Object Model oder Cascading Style Sheets Object Model) die wir alle kennen und die wir gerade einfach lösen müssen. Im Folgenden wird das mit einer Zeile von JavaScript veranschaulicht:

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

Wir rechnen eine Zahl in eine Zeichenfolge um und hängen eine Einheit an, parst der Browser diesen String und wandelt ihn wieder in eine Zahl für die CSS-Engine um. Dies wird noch größer, wenn Sie Transformationen mit JavaScript bearbeiten. Nichts mehr! und CSS steht kurz davor, etwas zu tippen.

Dieser Entwurf ist einer der ausgereifteren. Ein Polyfill ist in der wir bereits gearbeitet haben. (Haftungsausschluss: Die Verwendung von Polyfill noch mehr Rechenaufwand verursachen. Es geht darum zu zeigen, wie praktisch die API ist.)

Anstelle von Strings arbeiten Sie am StylePropertyMap eines Elements, wobei Jedes CSS-Attribut hat einen eigenen Schlüssel und einen entsprechenden Werttyp. Attribute width haben LengthValue als Werttyp. Ein LengthValue ist eine -Wörterbuch aller CSS-Einheiten wie em, rem, px, percent und so weiter. Einstellung height: calc(5px + 5%) ergibt LengthValue{px: 5, percent: 5}. Einige Properties wie box-sizing akzeptieren nur bestimmte Keywords und haben daher eine KeywordValue. Die Gültigkeit dieser Attribute könnte dann während der Laufzeit.

<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}

Attribute und Werte

(Spezifikation)

Kennen Sie benutzerdefinierte CSS-Eigenschaften (oder deren inoffizielles Alias "CSS-Variablen")? Das sind sie, nur mit Typen! Bisher konnten Variablen nur Zeichenfolgenwerte und nach einem einfachen Suchen-und-Ersetzen-Ansatz gesucht. Bei diesem Entwurf ist es nicht möglich, nur einen Typ für die Variablen angeben, sondern auch einen Standardwert und das Vererbungsverhalten mithilfe einer JavaScript API beeinflussen. Technisch gesehen Erlaubt es auch, benutzerdefinierte Eigenschaften mit standardmäßigen CSS-Übergängen animiert zu werden und Animationen, die ebenfalls berücksichtigt werden.

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

Messwerte für Schriftarten

Schriftartmesswerte sind genau das, wonach es sich anhört. Was ist der Begrenzungsrahmen (oder der Begrenzungsrahmen), wenn ich die Zeichenfolge X mit der Schriftart Y in der Größe Z wiedergebe? Was passiert, wenn ich Ruby-Annotationen? Dies wurde viel verlangt und Houdini sollte endlich diese Wünsche wahr werden lassen.

Halt – das war noch nicht alles!

Houdini enthält noch mehr Spezifikationen, doch in Zukunft werden diese eher unsicher und nicht viel mehr als Platzhalter für Ideen. Beispiele hierfür sind benutzerdefiniertes Überlaufverhalten, CSS-Syntax Extension API, Erweiterungen nativem Scrollverhalten und ebenso ambitionierten Funktionen die auf der Webplattform nicht möglich waren.

Demos

Ich habe den Code für die Demo als Open Source zur Verfügung gestellt. (Live-Demo mit Polyfill).