Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Super Mario Bros. Principle

The Super Mario Bros. Principle

The release of Super Mario Bros. brought us gameplay like we have never seen before. An experience that still holds up to this day. One of the reasons is the architecture of the game: It allows designers absolute freedom in creating levels without spending any thought on the implementation. Not caring about the technical details, but still design without limitations? Isn't that something we'd love for web development? See how we use CSS custom properties, web components and the power of the Cascade to transcend into creative Nirvana. Just like Miyamoto did 30 years ago.

Stefan Baumgartner

May 11, 2016
Tweet

More Decks by Stefan Baumgartner

Other Decks in Technology

Transcript

  1. The Super Mario Bros. Principle

    View full-size slide

  2. http://goo.gl/h7PnfE
    The long shadow of
    Super Mario Bros.

    View full-size slide

  3. Toshihiko Nakago Shigeru Miyamoto

    View full-size slide

  4. I could insert
    anything into a
    level, Nakago’s
    System would at
    least do
    something with it

    View full-size slide

  5. Toshihiko Nakago Shigeru Miyamoto

    View full-size slide

  6. Toshihiko Nakago Shigeru Miyamoto

    View full-size slide

  7. Provide something
    Robust
    Failsafe
    Flexible
    Easy to use

    View full-size slide

  8. CSS is easy
    selector {
    property: value;
    }

    View full-size slide

  9. CSS is easy
    from-that-thing {
    make-this: look-like-this;
    and-this: look-something-like-this;
    }

    View full-size slide

  10. CSS is easy
    from-that-thing {
    make-this: look-like-this;
    and-this: look-something-like-this;
    }
    This rarely gets complex
    This is always centre of
    debates and problems

    View full-size slide

  11. This can be overwhelming
    Even with all the
    tools and tooling

    View full-size slide

  12. Why can’t it be as easy as
    a {
    color: red;
    }

    View full-size slide

  13. Web components

    I’m Mario


    !
    "
    #

    View full-size slide

  14. Web components
    document
    .querySelector(
    ‘player-character’)
    .addEventListener(
    ‘jump’, () => {
    // do something
    })
    handleClick: function(e) {
    this.fire(‘jump’);
    }

    View full-size slide

  15. Web components
    .player { ... }
    header { ... }
    footer { ... }
    .body { ... }

    View full-size slide

  16. CSS custom properties
    :root {
    --main-color: #00b4ff;
    }
    .box {
    background-color: var(--main-color, blue);
    }
    .headline {
    color: var(--main-color, red);
    border-color: var(--main-color);
    }

    View full-size slide

  17. … follow the cascade
    :root {
    --main-color: #00b4ff;
    }
    .box {
    background-color: var(--main-color, blue);
    }
    .headline {
    color: var(--main-color, red);
    border-color: var(--main-color);
    }
    .theme-red {
    --main-color: #ff5205;
    }

    View full-size slide

  18. … are inheritable













    The whole page
    Just one element
    A special area of the site

    View full-size slide

  19. The possibilities!
    http://codepen.io/ddprrt/pen/KzboRG

    View full-size slide

  20. The possibilities!
    http://codepen.io/ddprrt/pen/NNeYOz
    @keyframes turn-wheel {
    from { transform: rotate(0deg); }
    to {
    transform: rotate(
    calc(15 * 360deg + var(--wheel-deg))
    )
    }
    }
    [class*=number-] {
    animation: turn-wheel 10s ease-out forwards;
    }
    .number-20 {
    --wheel-deg: 290deg;
    }

    View full-size slide

  21. Controllable via JavaScript
    const wheel = document.querySelector(‘roulette-wheel’);
    wheel.style.setProperty('--wheel-deg', ‘100deg’);
    wheel.classList.add(‘number-custom');

    View full-size slide

  22. Compatibility
    And a damn good polyfill in Polymer

    View full-size slide

  23. Cascade and inheritance
    allow us to use
    custom properties as a
    styling interface

    View full-size slide

  24. But it can be tough
    .player {
    display: block
    }
    header {
    color: var(--player-header-color);
    width: var(--player-header-width);
    height: var(--player-header-height);
    ...
    }
    footer {
    color: var(--player-footer-color);
    width: var(--player-footer-width);
    height: var(--player-footer-height);
    ...
    }
    .body { ... }
    player-character {
    --player-header-color: …;
    --player-header-width: …;
    --player-header-height: …;
    --player-footer-color: …;
    --player-footer-width: …;
    --player-footer-height: …;

    }

    View full-size slide

  25. Enter the apply rule
    .player {
    display: block
    }
    header {
    @apply --player-header;
    }
    footer {
    @apply --player-footer;
    }
    .body { ... }
    player-character {
    --player-header: {
    width: ..;
    height: ..;
    color: ..;
    };
    --player-footer: {
    width: ..;
    height: ..;
    color: ..;
    };
    }

    View full-size slide

  26. Think mixins,
    inheritable, cascading
    mixins!

    View full-size slide

  27. Custom Properteception
    .player {
    display: block
    }
    header {
    @apply --player-header;
    background-color: var(--hat-color);
    }
    footer {
    @apply --player-footer;
    color: var(--pants-color);
    }
    .body { ... }
    player-character {
    --player-header: {
    width: ..;
    height: ..;
    --hat-color: ..;
    };
    --player-footer: {
    width: ..;
    height: ..;
    --pants-color: ..;
    };
    }

    View full-size slide

  28. transparent, resilient interface
    .mybemmed__header {
    @apply --player-header;
    background-color: var(--hat-color);
    }
    .mybemmed__footer {
    @apply --player-footer;
    color: var(--pants-color);
    }
    player-character {
    --player-header: {
    width: ..;
    height: ..;
    --hat-color: ..;
    };
    --player-footer: {
    width: ..;
    height: ..;
    --pants-color: ..;
    };
    }




    View full-size slide

  29. transparent, resilient interface
    div:nth-of-type(1) {
    @apply --player-header;
    background-color: var(--hat-color);
    }
    div:not(:nth-of-type(1)) {
    @apply --player-footer;
    color: var(--pants-color);
    }
    player-character {
    --player-header: {
    width: ..;
    height: ..;
    --hat-color: ..;
    };
    --player-footer: {
    width: ..;
    height: ..;
    --pants-color: ..;
    };
    }


    View full-size slide

  30. transparent, resilient interface
    //Access the properties via JavaScript!
    var styles
    = window.getComputedStyle(this);
    styles.getPropertyValue(‘--hat-color');
    player-character {
    --player-header: {
    width: ..;
    height: ..;
    --hat-color: ..;
    };
    --player-footer: {
    width: ..;
    height: ..;
    --pants-color: ..;
    };
    }

    View full-size slide

  31. Don’t avoid the cascade,
    use it to your advantage
    in a tamed way

    View full-size slide

  32. Custom properties
    and the @apply rule
    transfer selector complexity
    to the property level

    View full-size slide

  33. This approach needs some
    documentation

    View full-size slide

  34. The apply rule needs some
    time to land
    (but it’s pretty good
    polyfilled in Polymer)

    View full-size slide

  35. Toshihiko Nakago Shigeru Miyamoto

    View full-size slide

  36. @ddprrt
    See you at JSConf!

    View full-size slide