Гудини: демистификация CSS

Вы когда-нибудь задумывались о том, какой объем работы выполняет CSS? Вы меняете один атрибут, и внезапно весь ваш сайт появляется в другом макете. Это своего рода волшебство . До сих пор мы — сообщество веб-разработчиков — могли лишь быть свидетелями и наблюдать это волшебство. Что, если мы захотим придумать свою собственную магию? Что, если мы хотим стать волшебниками ?

Введите Гудини!

Рабочая группа Houdini состоит из инженеров Mozilla, Apple, Opera, Microsoft, HP, Intel и Google, которые вместе работают над предоставлением веб-разработчикам определенных частей движка CSS. Целевая группа работает над набором проектов с целью добиться их принятия W3C и превратить их в настоящие веб-стандарты. Они поставили перед собой несколько целей высокого уровня, превратили их в проекты спецификаций, которые, в свою очередь, породили набор вспомогательных проектов спецификаций более низкого уровня.

Когда говорят о «Гудини», обычно подразумевают сбор этих черновиков. На момент написания список черновиков неполный, а некоторые из них являются лишь заполнителями.

Технические характеристики

Рабочие листы ( спец .)

Сами по себе рабочие листы бесполезны. Это концепция, введенная для того, чтобы сделать возможными многие из более поздних проектов. Если вы подумали о Web Workers, когда читали «worklet», вы не ошибаетесь. У них много концептуальных совпадений. Так зачем обновка, когда у нас уже есть рабочие?

Цель Houdini — предоставить новые API, позволяющие веб-разработчикам подключать свой собственный код к движку CSS и окружающим системам. Вероятно, вполне реально предположить, что некоторые из этих фрагментов кода придется запускать каждый раз. одинокий. рамка . Некоторые из них должны по определению. Цитируем спецификацию Web Worker :

Это означает, что веб-работники не подходят для того, что планирует сделать Гудини. Поэтому были придуманы ворклеты. Ворлеты используют классы ES2015 для определения набора методов, сигнатуры которых предопределены типом ворлета. Они легкие и недолговечные.

CSS Paint API ( спецификация )

Paint API включен по умолчанию в Chrome 65. Прочтите подробное введение .

Работа композитора

Описанный здесь API устарел. Рабочий набор «Композитор» был переработан и теперь предлагается как «Рабочий модуль анимации». Узнайте больше о текущей версии API .

Несмотря на то, что спецификация набора инструментов была перенесена в WICG и будет доработана, именно она меня больше всего волнует. Некоторые операции передаются движком CSS на видеокарту вашего компьютера, хотя это зависит как от вашей видеокарты, так и от вашего устройства в целом.

Браузер обычно берет дерево DOM и на основе определенных критериев решает выделить некоторым ветвям и поддеревьям собственный слой. Эти поддеревья рисуют на нем себя (возможно, в будущем с использованием программы рисования). На последнем этапе все эти отдельные, теперь окрашенные слои складываются и располагаются друг над другом с учетом z-индексов, 3D-преобразований и т. д., чтобы получить окончательное изображение, видимое на вашем экране. Этот процесс называется композитингом и выполняется наборщиком.

Преимущество процесса композиции заключается в том, что вам не нужно перерисовывать все элементы при небольшой прокрутке страницы. Вместо этого вы можете повторно использовать слои из предыдущего кадра и просто перезапустить композитор с обновленной позицией прокрутки. Это ускоряет работу. Это помогает нам достичь 60 кадров в секунду.

Работа композитора.

Как следует из названия, ворлет наборщика позволяет вам подключиться к наборщику и повлиять на то, как слой уже нарисованного элемента позиционируется и накладывается поверх других слоев.

Чтобы быть более конкретным, вы можете сообщить браузеру, что хотите подключиться к процессу компоновки для определенного узла DOM, и можете запросить доступ к определенным атрибутам, таким как положение прокрутки, transform или opacity . Это принудительно помещает этот элемент на отдельный слой, и в каждом кадре вызывается ваш код. Вы можете перемещать свой слой, манипулируя преобразованием слоев и изменяя его атрибуты (например, opacity ), что позволяет вам делать причудливые вещи со скоростью 60 кадров в секунду.

Вот полная реализация параллаксной прокрутки с использованием набора инструментов.

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

Роберт Флэк написал полифилл для ворлета наборщика, так что вы можете попробовать его – очевидно, с гораздо более высоким влиянием на производительность.

Макет макета ( спецификация )

Был предложен первый реальный проект спецификации. Реализация еще далеко.

Опять же, спецификация практически пустая, но идея интригует: напишите свой собственный макет! Предполагается, что ворлет макета позволит вам выполнить display: layout('myLayout') и запустить JavaScript, чтобы расположить дочерние элементы узла в поле узла.

Конечно, запуск полной JavaScript-реализации макета flex-box CSS происходит медленнее, чем запуск эквивалентной встроенной реализации, но легко представить сценарий, в котором срезание углов может привести к увеличению производительности. Представьте себе веб-сайт, состоящий только из плиток, как в Windows 10, или макет в каменном стиле. Абсолютное и фиксированное позиционирование не используется, равно как и z-index , а элементы никогда не перекрываются и не имеют каких-либо границ или переполнений. Возможность пропустить все эти проверки при переразметке может привести к увеличению производительности.

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 ( спецификация )

Типизированный CSSOM (объектная модель CSS или объектная модель каскадных таблиц стилей) решает проблему, с которой мы, вероятно, все сталкивались и с которой только что научились мириться. Позвольте мне проиллюстрировать это строкой JavaScript:

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

Мы занимаемся математикой, преобразуем число в строку, чтобы добавить единицу измерения, чтобы браузер проанализировал эту строку и преобразует ее обратно в число для движка CSS. Это становится еще уродливее, когда вы манипулируете преобразованиями с помощью JavaScript . Больше не надо! CSS вот-вот начнет печатать.

Этот проект является одним из наиболее зрелых, и над ним уже ведется работа над полифилом . (Отказ от ответственности: использование полифила, очевидно, приведет к еще большему увеличению вычислительных затрат. Цель состоит в том, чтобы показать, насколько удобен API.)

Вместо строк вы будете работать с StylePropertyMap элемента, где каждый атрибут CSS имеет свой собственный ключ и соответствующий тип значения. Типом значения таких атрибутов, как width является LengthValue . LengthValue — это словарь всех единиц CSS, таких как em , rem , px , percent и т. д. Установка height: calc(5px + 5%) даст LengthValue{px: 5, percent: 5} . Некоторые свойства, такие как box-sizing просто принимают определенные ключевые слова и поэтому имеют тип значения KeywordValue . Затем достоверность этих атрибутов можно будет проверить во время выполнения.

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

Свойства и значения

( спецификация )

Знаете ли вы пользовательские свойства CSS (или их неофициальный псевдоним «переменные CSS»)? Это они, но с типами! До сих пор переменные могли иметь только строковые значения и использовали простой подход поиска и замены. Этот проект позволит вам не только указать тип ваших переменных, но также определить значение по умолчанию и повлиять на поведение наследования с помощью API JavaScript. Технически это также позволит анимировать пользовательские свойства с помощью стандартных переходов и анимации CSS, что также рассматривается.

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

Метрики шрифта

Метрики шрифтов — это именно то, на что это похоже. Что такое ограничивающая рамка (или ограничивающие рамки), когда я отображаю строку X со шрифтом Y и размером Z? Что, если я воспользуюсь рубиновыми аннотациями ? Об этом много просили, и Гудини должен, наконец, воплотить эти желания в жизнь.

Но подождите, это еще не все!

В списке черновиков Гудини еще больше спецификаций, но их будущее довольно неопределенно, и они не более чем заполнители для идей. Примеры включают в себя настраиваемое поведение переполнения, API расширения синтаксиса CSS, расширение встроенного поведения прокрутки и аналогичные амбициозные вещи, все из которых позволяют реализовать на веб-платформе вещи, которые раньше были невозможны.

Демо

Я открыл код для демо-версии ( живая демо-версия с использованием полифилла).

,

Вы когда-нибудь задумывались о том, какой объем работы выполняет CSS? Вы меняете один атрибут, и внезапно весь ваш сайт появляется в другом макете. Это своего рода волшебство . До сих пор мы — сообщество веб-разработчиков — могли лишь быть свидетелями и наблюдать это волшебство. Что, если мы хотим придумать свою собственную магию? Что, если мы хотим стать волшебниками ?

Введите Гудини!

Рабочая группа Houdini состоит из инженеров Mozilla, Apple, Opera, Microsoft, HP, Intel и Google, которые вместе работают над предоставлением веб-разработчикам определенных частей движка CSS. Целевая группа работает над набором проектов с целью добиться их принятия W3C и превратить их в настоящие веб-стандарты. Они поставили перед собой несколько целей высокого уровня, превратили их в проекты спецификаций, которые, в свою очередь, породили набор вспомогательных проектов спецификаций более низкого уровня.

Когда говорят о «Гудини», обычно подразумевают сбор этих черновиков. На момент написания список черновиков неполный, а некоторые из них являются лишь заполнителями.

Технические характеристики

Рабочие листы ( спец .)

Сами по себе рабочие листы бесполезны. Это концепция, введенная для того, чтобы сделать возможными многие из более поздних проектов. Если вы подумали о Web Workers, когда читали «worklet», вы не ошибаетесь. У них много концептуальных совпадений. Так зачем обновка, когда у нас уже есть рабочие?

Цель Houdini — предоставить новые API, позволяющие веб-разработчикам подключать свой собственный код к движку CSS и окружающим системам. Вероятно, вполне реально предположить, что некоторые из этих фрагментов кода придется запускать каждый раз. одинокий. рамка . Некоторые из них должны по определению. Цитируем спецификацию Web Worker :

Это означает, что веб-работники не подходят для того, что планирует сделать Гудини. Поэтому были придуманы ворклеты. Ворлеты используют классы ES2015 для определения набора методов, сигнатуры которых предопределены типом ворлета. Они легкие и недолговечные.

CSS Paint API ( спецификация )

Paint API включен по умолчанию в Chrome 65. Прочтите подробное введение .

Работа композитора

Описанный здесь API устарел. Рабочий набор «Композитор» был переработан и теперь предлагается как «Рабочий модуль анимации». Узнайте больше о текущей версии API .

Несмотря на то, что спецификация набора инструментов была перенесена в WICG и будет доработана, именно она меня больше всего волнует. Некоторые операции передаются движком CSS на видеокарту вашего компьютера, хотя это зависит как от вашей видеокарты, так и от вашего устройства в целом.

Браузер обычно берет дерево DOM и на основе определенных критериев решает выделить некоторым ветвям и поддеревьям собственный слой. Эти поддеревья рисуют на нем себя (возможно, в будущем с использованием программы рисования). На последнем этапе все эти отдельные, теперь окрашенные слои складываются и располагаются друг над другом с учетом z-индексов, 3D-преобразований и т. д., чтобы получить окончательное изображение, видимое на вашем экране. Этот процесс называется композитингом и выполняется наборщиком.

Преимущество процесса композиции заключается в том, что вам не нужно перерисовывать все элементы при небольшой прокрутке страницы. Вместо этого вы можете повторно использовать слои из предыдущего кадра и просто перезапустить композитор с обновленной позицией прокрутки. Это ускоряет работу. Это помогает нам достичь 60 кадров в секунду.

Работа композитора.

Как следует из названия, ворлет наборщика позволяет вам подключиться к наборщику и повлиять на то, как слой уже нарисованного элемента позиционируется и накладывается поверх других слоев.

Чтобы быть более конкретным, вы можете сообщить браузеру, что хотите подключиться к процессу компоновки для определенного узла DOM, и можете запросить доступ к определенным атрибутам, таким как положение прокрутки, transform или opacity . Это принудительно помещает этот элемент на отдельный слой, и в каждом кадре вызывается ваш код. Вы можете перемещать свой слой, манипулируя преобразованием слоев и изменяя его атрибуты (например, opacity ), что позволяет вам делать причудливые вещи со скоростью 60 кадров в секунду.

Вот полная реализация параллаксной прокрутки с использованием набора инструментов.

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

Роберт Флэк написал полифилл для ворлета наборщика, так что вы можете попробовать его – очевидно, с гораздо более высоким влиянием на производительность.

Макет макета ( спецификация )

Был предложен первый реальный проект спецификации. Реализация еще далеко.

Опять же, спецификация практически пустая, но идея интригует: напишите свой собственный макет! Предполагается, что ворлет макета позволит вам выполнить display: layout('myLayout') и запустить JavaScript, чтобы расположить дочерние элементы узла в поле узла.

Конечно, запуск полной JavaScript-реализации макета flex-box CSS происходит медленнее, чем запуск эквивалентной встроенной реализации, но легко представить сценарий, в котором срезание углов может привести к увеличению производительности. Представьте себе веб-сайт, состоящий только из плиток, как в Windows 10, или макет в каменном стиле. Абсолютное и фиксированное позиционирование не используется, равно как и z-index , а элементы никогда не перекрываются и не имеют каких-либо границ или переполнений. Возможность пропустить все эти проверки при переразметке может привести к увеличению производительности.

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 ( спецификация )

Типизированный CSSOM (объектная модель CSS или объектная модель каскадных таблиц стилей) решает проблему, с которой мы, вероятно, все сталкивались и с которой только что научились мириться. Позвольте мне проиллюстрировать это строкой JavaScript:

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

Мы занимаемся математикой, преобразуем число в строку, чтобы добавить единицу измерения, чтобы браузер проанализировал эту строку и преобразует ее обратно в число для движка CSS. Это становится еще уродливее, когда вы манипулируете преобразованиями с помощью JavaScript . Больше не надо! CSS вот-вот начнет печатать.

Этот проект является одним из наиболее зрелых, и над ним уже ведется работа над полифилом . (Отказ от ответственности: использование полифила, очевидно, приведет к еще большему увеличению вычислительных затрат. Цель состоит в том, чтобы показать, насколько удобен API.)

Вместо строк вы будете работать с StylePropertyMap элемента, где каждый атрибут CSS имеет свой собственный ключ и соответствующий тип значения. Типом значения таких атрибутов, как width является LengthValue . LengthValue — это словарь всех единиц CSS, таких как em , rem , px , percent и т. д. Установка height: calc(5px + 5%) даст LengthValue{px: 5, percent: 5} . Некоторые свойства, такие как box-sizing просто принимают определенные ключевые слова и поэтому имеют тип значения KeywordValue . Затем достоверность этих атрибутов можно будет проверить во время выполнения.

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

Свойства и значения

( спецификация )

Знаете ли вы пользовательские свойства CSS (или их неофициальный псевдоним «переменные CSS»)? Это они, но с типами! До сих пор переменные могли иметь только строковые значения и использовали простой подход поиска и замены. Этот проект позволит вам не только указать тип ваших переменных, но также определить значение по умолчанию и повлиять на поведение наследования с помощью API JavaScript. Технически это также позволит анимировать пользовательские свойства с помощью стандартных переходов и анимации CSS, что также рассматривается.

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

Метрики шрифта

Метрики шрифтов — это именно то, на что это похоже. Что такое ограничивающая рамка (или ограничивающие рамки), когда я отображаю строку X со шрифтом Y и размером Z? Что если я воспользуюсь рубиновыми аннотациями ? Об этом много просили, и Гудини должен, наконец, воплотить эти желания в жизнь.

Но подождите, это еще не все!

В списке черновиков Гудини еще больше спецификаций, но их будущее довольно неопределенно, и они не более чем заполнители для идей. Примеры включают настраиваемое поведение переполнения, API расширения синтаксиса CSS, расширение встроенного поведения прокрутки и аналогичные амбициозные вещи, все из которых позволяют реализовать на веб-платформе то, что раньше было невозможно.

Демо

Я открыл код для демо-версии ( живая демо-версия с использованием полифилла).