Вы когда-нибудь задумывались о том, какой объем работы выполняет 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 кадров в секунду.
![Работа композитора.](https://developer.chrome.google.cn/static/docs/css-ui/houdini/image/compositor-worklet-a5eb4330b62ac.png?authuser=8&hl=ru)
Как следует из названия, ворлет наборщика позволяет вам подключиться к наборщику и влиять на то, как слой уже нарисованного элемента позиционируется и накладывается поверх других слоев.
Чтобы быть более конкретным, вы можете сообщить браузеру, что хотите подключиться к процессу компоновки для определенного узла 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, расширение встроенного поведения прокрутки и аналогичные амбициозные вещи, все из которых позволяют реализовать на веб-платформе вещи, которые раньше были невозможны.
Демо
Я открыл исходный код для демо-версии ( живая демо-версия с использованием полифилла).