$30 off During Our Annual Pro Sale. View Details »

WebAssembly-driven CSS

WebAssembly-driven CSS

CSS considered as a non-serious language in the tech community. I’m going to show that to make an impressive and performant design you might need to use WebAssembly and Houdini APIs. Houdini provides us a view layer (Paint Worklet) and props for render (Properties and Values API). WebAssembly is a performant state calculator. JavaScript is an orchestrator that requests a new state and handles properties updates. With such MVC-like architecture, you will be able to create rich off-thread visual experiences that could be easily plugged-in in different projects.

Vitalii Bobrov

September 20, 2019
Tweet

More Decks by Vitalii Bobrov

Other Decks in Programming

Transcript

  1. CSS
    W E B A S S E M B LY- D R I V E N

    View Slide

  2. VITALII BOBROV
    • Lead FE Engineer @ EPAM Poland
    • Perf and CSS fan
    • @AngularWroclaw organizer
    @bobrov1989
    https://bobrov.dev

    View Slide

  3. WebAssembly-Driven
    W H AT D O E S I T M E A N ?

    View Slide

  4. https://bobrov.dev/css-paint-demos/game-of-life/

    View Slide

  5. WA S M U S E D F O R T H E S TAT E U P D AT E

    View Slide

  6. View Slide

  7. A N E W F I E L D F O R E X P E R I M E N T S I S O P E N

    View Slide

  8. CONCEPT OVERVIEW
    Paint API
    Worklet
    V I E W

    View Slide

  9. CONCEPT OVERVIEW
    Main-Thread
    JavaScript
    Paint API
    Worklet
    properties
    V I E W
    C O N TA I N E R

    View Slide

  10. CONCEPT OVERVIEW
    Main-Thread
    JavaScript
    Paint API
    Worklet
    WebAssembly
    Module
    properties
    update
    V I E W
    C O N TA I N E R
    S TAT E
    M A N A G E R

    View Slide

  11. CONCEPT OVERVIEW
    Main-Thread
    JavaScript
    Paint API
    Worklet
    WebAssembly
    Module
    properties
    state
    update
    V I E W
    C O N TA I N E R
    S TAT E
    M A N A G E R

    View Slide

  12. I T R E M I N D S S O M E T H I N G …

    View Slide

  13. PAINT API
    H O U D I N I

    View Slide

  14. CSS PROPS ACCEPTING IMAGES
    • background-image
    • border-image
    • list style image
    • custom properties

    View Slide

  15. HOW TO IMPLEMENT
    • Define a paint class in a separate file
    • Load worklet module
    • Use paint() CSS function as a value for image

    View Slide

  16. PAINT WORKLET CLASS
    class Painter {
    paint(ctx, geom, props, args) {}
    }
    registerPaint('my-painter', Painter);

    View Slide

  17. PAINT WORKLET CLASS
    class Painter {
    static get inputProperties() {
    return ['--custom-palette', 'color'];
    }
    paint(ctx, geom, props, args) {}
    }
    registerPaint('my-painter', Painter);

    View Slide

  18. PAINT WORKLET CLASS
    class Painter {
    static get inputProperties() {
    return ['--custom-palette', 'color'];
    }
    static get inputArguments() {
    return ['', ''];
    }
    paint(ctx, geom, props, args) {}
    }
    registerPaint('my-painter', Painter);

    View Slide

  19. LOAD WORKLET MODULE
    if ('paintWorklet' in CSS) {
    CSS.paintWorklet.addModule('paint.js');
    } else {
    // Optionally provide a fallback.
    }

    View Slide

  20. USE PAINT() FUNCTION IN CSS
    .paint-container {
    background: #000;
    background: paint(my-painter);
    }

    View Slide

  21. USE PAINT() FUNCTION IN CSS
    .paint-container {
    --custom-palette: #333;
    color: #fff;
    background: #000;
    background: paint(my-painter);
    }

    View Slide

  22. USE PAINT() FUNCTION IN CSS
    .paint-container {
    --custom-palette: #333;
    color: #fff;
    background: #000;
    background: paint(my-painter, 2, 25%);
    }

    View Slide

  23. https://bobrov.dev/css-paint-demos/star-rating/

    View Slide

  24. https://bobrov.dev/css-paint-demos/qr-code/

    View Slide

  25. BENEFITS
    • Possible to run in a separate thread
    • Draw whatever you want using 2D Canvas
    • Renders only when needed

    View Slide

  26. MATERIAL BACKGROUND
    C S S PA I N T I M A G E
    VS
    https://vitaliy-bobrov.github.io/css-paint-demos/md-bg/

    View Slide

  27. MATERIAL BACKGROUND
    C S S PA I N T I M A G E
    VS
    https://vitaliy-bobrov.github.io/css-paint-demos/md-bg/
    813 B 2.39 KB
    worklet file only
    few bytes of CSS + init JS
    compressed JPEG
    cropped for mobile

    View Slide

  28. JS IN CSS

    View Slide

  29. https://bobrov.dev/css-paint-demos/bar-js-in-css/

    View Slide

  30. J S O N D ATA F O R C H A R T I N C S S

    View Slide

  31. J AVA S C R I P T I N C S S T O R E N D E R C S S

    View Slide

  32. I S C S S A P R O G R A M M I N G L A N G U A G E T H E N ?

    View Slide

  33. CUSTOM
    PROPERTIES & VALUES API
    H O U D I N I

    View Slide

  34. CUSTOM PROPERTY
    .parent {
    --font-color: #fff;
    }
    .child {
    color: var(--font-color);
    }

    View Slide

  35. CUSTOM PROPERTY
    .parent {
    --font-color: #fff;
    }
    .child {
    --font-color: #000;
    color: var(--font-color);
    }

    View Slide

  36. CUSTOM PROPERTY
    .parent {
    --font-color: #fff;
    }
    .child {
    --font-color: #000;
    color: var(--font-color, #333);
    }

    View Slide

  37. H O W T O A N I M AT E A S T R I N G T O A N O T H E R S T R I N G ?

    View Slide

  38. CSS TYPES

    View Slide

  39. REGISTER CUSTOM PROPERTY
    if ('registerProperty' in CSS) {
    CSS.registerProperty({
    name: '--font-color',
    syntax: '',
    inherits: false,
    initialValue: '#cccccc'
    });
    }

    View Slide

  40. B U T S H U N T I T B E D E C L A R E D I N C S S ?

    View Slide

  41. REGISTER CUSTOM PROPERTY
    @property --font-color {
    syntax: '';
    initial-value: #cccccc;
    inherits: false;
    }
    https://github.com/vitaliy-bobrov/postcss-register-custom-props

    View Slide

  42. https://css-houdini.rocks/animating-gradient

    View Slide

  43. UPDATE & RENDER
    REQUEST
    J AVA S C R I P T

    View Slide

  44. UPDATE CUSTOM PROPERTY
    element.style
    .setProperty(‘--font-color', '#fff');

    View Slide

  45. LOAD WASM & REQUEST A NEW STATE
    import { Universe } from 'wasm-game-of-life';
    const renderLoop = (now) => {
    universe.tick();
    const cellsPtr = universe.cells();
    const cells = new Uint8Array(
    memory.buffer,
    cellsPtr,
    width * height
    );
    requestAnimationFrame(renderLoop);
    };

    View Slide

  46. STATE MANAGEMENT
    W E B A S S E M B LY

    View Slide

  47. WASM - BINARY INSTRUCTION
    FORMAT FOR A STACK-BASED VM

    View Slide

  48. AVAILABLE OPTIONS

    View Slide

  49. ONLY NUMBERS

    View Slide

  50. LINEAR MEMORY

    View Slide

  51. View Slide

  52. CONCEPT RECAP
    Main-Thread
    JavaScript
    Paint API
    Worklet
    WebAssembly
    Module
    properties
    state
    update
    V I E W
    C O N TA I N E R
    S TAT E
    M A N A G E R

    View Slide

  53. THANK YOU
    U S E WA S M P O W E R F O R C S S A R T
    @bobrov1989
    https://bobrov.dev
    Illustrations by cdd20 https://pixabay.com/users/cdd20-1193381

    View Slide