Pro Yearly is on sale from $80 to $50! »

The Super Mario Bros. Principle - Extended Edition

The Super Mario Bros. Principle - Extended Edition

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.

187d92c9284160ad908885ab096f5209?s=128

Stefan Baumgartner

September 23, 2016
Tweet

Transcript

  1. The Super Mario Bros. Principle

  2. @ddprrt fettblog.eu

  3. manning.com/ baumgartner

  4. None
  5. http://goo.gl/h7PnfE The long shadow of Super Mario Bros.

  6. Super Mario Bros. was about 40 KB in Size That’s

    the same size as today’s Minified Bootstrap JavaScript* * Bootstrap 4, non-gzipped
  7. None
  8. Toshihiko Nakago Shigeru Miyamoto

  9. I could insert anything into a level, Nakago’s System would

    at least do something with it
  10. Toshihiko Nakago Shigeru Miyamoto

  11. Toshihiko Nakago Shigeru Miyamoto

  12. Toshihiko Nakago Shigeru Miyamoto

  13. Provide something Robust Failsafe Flexible Easy to use

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

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

  16. 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
  17. Methodologies .l-fixed .sidebar { … } .logo { … }

  18. Methodologies .search { … } .search__input--disabled { … } .search__input

    { … }
  19. Methodologies <div class="foo Bd C(#0280ae) Ta(c)"> <p class="Op(0) foo:h>Op(1)”> Lorem

    ipsum </p> </div>
  20. None
  21. INLINE STYLES

  22. CSS Methodologies OOCSS SMACSS BEM Atomic CSS

  23. CSS Methodologies Tools Rules Opinions Edge Cases

  24. All Methodologies Agree That it’s all about the specificity

  25. Keeping it low Keeping it high BEM Atomic OOCSS SMACSS

    Inline Styles
  26. Consensus Avoid specificity chaos Don’t use the cascade Stop the

    inheritance
  27. Sledgehammer methods?

  28. Finding the right selectors can be overwhelming Even with all

    the tools and tooling
  29. CSS is easy by design Writing CSS is super hard

  30. CSS is easy by design Writing good CSS is super

    hard
  31. Why can’t it be as easy as a { color:

    red; }
  32. Think back to miyamoto

  33. Interfaces

  34. Web components <player-character> I’m Mario </player-character> <div class=“player”> <header></header> <div

    class=“body”></div> <footer></footer> </div>
  35. Web components document .querySelector( ‘player-character’) .addEventListener( ‘jump’, () => {

    // do something }) handleClick: function(e) { this.fire(‘jump’); }
  36. Web components .player { ... } header { ... }

    footer { ... } .body { ... }
  37. Enter custom properties

  38. Also known as CSS Variables a { --a-property: red; }

  39. 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); }
  40. … 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; }
  41. … are inheritable <body class=“theme-red”> <div class=“box”>…</div> </body> The whole

    page
  42. … are inheritable <body class=“theme-red”> <div class=“box”>…</div> </body> The whole

    page Just one element <body> <div class=“box theme-red”>…</div> </body>
  43. … are inheritable <body class=“theme-red”> <div class=“box”>…</div> </body> The whole

    page Just one element A special area of the site <body> <div class=“theme-red”> <div class=“box”>…</div> <div class=“box”>…</div> </div> <div class=“box”>…</div> </body> <body> <div class=“box theme-red”>…</div> </body>
  44. The possibilities! http://codepen.io/ddprrt/pen/KzboRG

  45. The possibilities! http://codepen.io/ddprrt/pen/NNeYOz

  46. The possibilities! http://codepen.io/ddprrt/pen/NNeYOz

  47. The possibilities! http://codepen.io/ddprrt/pen/NNeYOz @keyframes turn-wheel-to-20 { from { transform: rotate(0deg);

    } to { transform: rotate(5690deg) } } .number-20 { animation: turn-wheel 10s ease-out forwards; }
  48. The possibilities! http://codepen.io/ddprrt/pen/NNeYOz @keyframes turn-wheel-to-20 { from { transform: rotate(0deg);

    } to { transform: rotate(5690deg) } } .number-20 { animation: turn-wheel 10s ease-out forwards; } just for one!
  49. The possibilities! http://codepen.io/ddprrt/pen/NNeYOz

  50. 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; }
  51. 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; } turns 1 turn the actual position
  52. Controllable via JavaScript const wheel = document.querySelector(‘roulette-wheel’); wheel.style.setProperty('--wheel-deg', ‘100deg’); wheel.classList.add(‘number-custom');

  53. But it helps with simple stuff as well a {

    color: #f00; text-decoration: none; } a:active, a:focus, a:hover { color: #e00; } a:visited: { color: #f00; }
  54. But it helps with simple stuff as well a {

    color: #f00; text-decoration: none; } a:active, a:focus, a:hover { color: #e00; } a:visited: { color: #f00; } .btn { color: #fff; background-color: #0f0; } .btn:active, .btn:focus, .btn:hover { background-color: #0e0; } .btn:visited { background-color: #0f0; }
  55. But it helps with simple stuff as well a {

    color: #f00; text-decoration: none; } a:active, a:focus, a:hover { color: #e00; } a:visited: { color: #f00; } .btn { color: #fff; background-color: #0f0; } .btn:active, .btn:focus, .btn:hover { background-color: #0e0; } .btn:visited { background-color: #0f0; }
  56. But it helps with simple stuff as well a {

    color: var(--txt-color, #f00); text-decoration: none; } a:active, a:focus, a:hover { color: var(--foc-color, #e00); } a:visited: { color: var(--txt-color, #f00); } .btn { --txt-color: #fff; --foc-color: #fff; background-color: #0f0; } .btn:active, .btn:focus, .btn:hover, { background-color: #0e0; }
  57. But it helps with simple stuff as well a {

    color: var(--txt-color, #f00); background-color: var(--bg-color, transparent); text-decoration: none; } a:active, a:focus, a:hover { color: var(--foc-color, #e00); background-color: var(--bg-act-color, transparent); } .btn { --txt-color: #fff; --foc-color: #fff; --bg-color: #0f0; --bg-act-color: #0e0; }
  58. That looks like an interface

  59. Compatibility And a damn good polyfill in Polymer

  60. Edge!

  61. Cascade and inheritance allow us to use custom properties as

    a styling interface
  62. 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: …; … }
  63. Well…

  64. Enter level 2

  65. Custom property sets player-character { --player-head: { color: …; width:

    …; height: …; } }
  66. Custom property sets player-character { --player-head: { color: …; width:

    …; height: …; } } header { @apply(--player-head); }
  67. Without @apply .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: …; … }
  68. With @apply .player { display: block } header { @apply

    --player-header; } footer { @apply --player-footer; } .body { ... } player-character { --player-header: { width: ..; height: ..; color: ..; }; --player-footer: { width: ..; height: ..; color: ..; }; }
  69. Think mixins, inheritable, cascading mixins!

  70. 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: ..; }; }
  71. 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: ..; }; } <div class=“mybemmed”> <div class=“mybemmed__footer”></div> <div class=“mybemmed__header”></div> </div>
  72. 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: ..; }; } <div></div> <div></div>
  73. 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: ..; }; } <canvas></canvas>
  74. None
  75. None
  76. The upsides

  77. Custom properties and the @apply rule transfer selector complexity to

    the property level
  78. You design using the same interface regardless of the technology

    underneath
  79. Styling of components becomes even more declarative

  80. You don’t avoid the cascade, You use it to your

    advantage
  81. Keeping it low Keeping it high BEM Atomic OOCSS SMACSS

    Inline Styles
  82. Keeping it low Keeping it high BEM Atomic OOCSS SMACSS

    Inline Styles
  83. The downsides

  84. This approach needs some documentation

  85. You need JS polyfills for now if you want to

    go cross-browser
  86. The apply rule needs some time to land (but it’s

    pretty good polyfilled in Polymer)
  87. This is also not the one solution for your css

    problems
  88. Toshihiko Nakago Shigeru Miyamoto

  89. Toshihiko Nakago Shigeru Miyamoto

  90. @ddprrt