CSS Houdini

Breaking out from the CSS straitjacket

W3C
TASK
FORCE

FLEXBOX

First Public Draft: 2009

Candidate Recommendation: 2012

GRID

FIRST PUBLIC DRAFT: 2011

CANDIDATE RECOMMENDATION: 2017

CSS spec PROCess

ECMASCRIPT spec PROCess

We can't polyfill css

until now...

the problem is

whoami

Developer

Pontus

Worklets

CSS Typed OM + Properties & Values API

Layout API

Paint API

Animation Worklet

https or localhost

CSS RENDERING

pipeline

Parse

DOM

CSSOM

Cascade

Layout

Paint

Composition

Properties &

Values API

Layout API

Paint API

Animation

Worklet

Typed OM

CSS typed om

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

// old way
el.style.opacity = 0.3;
typeof el.style.opacity; // "string"
// new and shiny
el.attributeStyleMap.set('opacity', '0.5');
typeof el.attributeStyleMap.get('opacity').value; // "number"
// Map-like
el.attributeStyleMap.has('opacity'); // true
el.attributeStyleMap.keys(); // Iterator
el.attributeStyleMap.values(); // Iterator
el.attributeStyleMap.entries(); // Iterator
el.attributeStyleMap.delete('opacity');
el.attributeStyleMap.clear();

Worklets

CSS typed om

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

// attributeStyleMap vs computedStyleMap()
el.attributeStyleMap.get('line-height'); // null
el.computedStyleMap().get('line-height'); // {32, 'px'}
el.attributeStyleMap.set('opacity', 3);
el.attributeStyleMap.get('opacity').value; // 3
el.computedStyleMap().get('opacity').value; // 1
el.attributeStyleMap.set('opacity', 'coral'); // TypeError
const transform = new CSSTransformValue([
  new CSSRotate(CSS.deg(0))
]);
el.attributeStyleMap.set('transform', transform);
(function draw() {
  requestAnimationFrame(draw);
  transform[0].angle.value += 5;
  el.attributeStyleMap.set('transform', transform);
})();

Worklets

CSS typed om

Properties &

Values API

Worklets

Paint API

Animation

Worklet

Typed OM

if (window.CSS && CSS.number) {
  // Supports CSS Typed Om
}
// types
CSS.px(10);
CSS.em(1.5);
CSS.rem('2');
CSS.deg(180);
CSS.rad(2);
CSS.number('100');
CSS.ms(300);
CSS.vw('10');
CSS.percent(50);
CSS.deg(90).to('rad').value;
// 1.5707963267948966

new CSSMathSum(CSS.vw(100), CSS.px(-10));
// calc(100vw - 10px);

CSS.px(1).add(CSS.px(2));
// {value: 3, unit: 'px'}

CSS.px(200).equals(CSS.px(200));
// true

Properties & Values API

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

CSS.registerProperty({
  name: '',
  inherits: true,
  syntax: '*',
  initialValue: ''
});
:root {
  --bg-color: teal;
}

Properties & Values API

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

Properties & Values API

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

Properties & Values API

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

@property --bg-color {
  syntax: '<color>';
  initial-value: coral;
  inherits: true;
}

Worklets

Worklets

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

CSS.paintWorklet

CSS.layoutWorklet

CSS.animationWorklet

AudioWorklet

CSS.paintWorklet.addModule('paint-worklet.js');

Paint API

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

// in JS
if ('paintWorklet' in CSS) {
  CSS.paintWorklet.addModule('tooltip.js');
}

// in CSS
@supports (background: paint(id)) {
  /* ... */
}

Worklets

Paint API

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

// main.js
CSS.paintWorklet.addModule('tooltip-worklet.js');
// styles.css
.tooltip {
  border-image-source: paint(tooltip);
}
// tooltip-worklet.js
registerPaint('tooltip', class {
  static get inputProperties() {
    return [];
  }
  paint(ctx, geometry, styleMap) {
    // paint stuff
  }
});

Worklets

Paint API

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

Paint API

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

Paint API

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

Paint API

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

Animation Worklet

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

Listen for user input, like scroll events!

Animate elements based on that user input

Do it all of the main thread!

Make Parallax Perform

Animation Worklet

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

Animation Worklet

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

Layout API

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

if ('layoutWorklet' in CSS) {
  await CSS.layoutWorklet.addModule('my-layout-script.js');
  console.log('layout script installed!');
}
// my-layout-script.js
registerLayout('masonry', class {
  static get inputProperties() { return ['--foo']; }
  static get childrenInputProperties() { return ['--bar']; }
  static get childDisplay() { return 'normal'; }

  *intrinsicSizes(children, styleMap) {
    // Intrinsic sizes code goes here.
  }

  *layout(space, children, styleMap, edges, breakToken) {
    // Layout code goes here.
  }
});
/* main.css */
body {
  display: layout('masonry');
}

Layout API

Layout API

Properties &

Values API

Paint API

Animation

Worklet

Typed OM

Worklets

Layout API

Future proofing the web

Better performance

Higher fidelity

Links

Examples

Articles

VIDEOS

Thank You! 🤓

houdini-css

By Pontus Lundin

houdini-css

A run through of what CSS Houdini is, why it's important and how it fits into the ecosystem

  • 767