Planes, Trains, and CSS Components London CSS

Fc7368fd45560e1e7401bc80684f5867?s=47 Adam Onishi
September 20, 2016

Planes, Trains, and CSS Components London CSS

The way we’re meant to be writing CSS appears to be in constant flux! What’s the safest route? Do we go for just writing vanilla CSS - is this the simplest and thus the safest? What about pre-processors like Sass or LESS? Or, do we look for more adventure with off-road vehicles like JavaScript or Web Components?

Join me as I take you on a journey through these different techniques for creating components. We’ll tackle all the bumps in the road head-on and fly straight into the eye of the storm, as we loop and swerve around development opinions.

The best thing about this journey, is we’ll see what it takes to engineer a component system for a large organisation. Using the best techniques available to us, both old and new. Ensuring styles are reusable, transferable, and easy to use across a variety of teams and products.

Fc7368fd45560e1e7401bc80684f5867?s=128

Adam Onishi

September 20, 2016
Tweet

Transcript

  1. Adam Onishi Financial Times @onishiweb Planes, trains, and CSS components

  2. FINANCIAL TIMES @onishiweb

  3. @onishiweb

  4. 1. Unify front-end styles across the FT 2. Reduce time

    spent repeating work @onishiweb
  5. Components! @onishiweb

  6. http://registry.origami.ft.com/components o-header o-table o-card

  7. http://origami.ft.com/

  8. Building components @onishiweb

  9. @onishiweb

  10. @onishiweb

  11. 1. Automobiles 2. Trains 3. Planes

  12. 1. CSS 2. CSS Modules 3. Web Components

  13. The CSS way…

  14. The current way… @onishiweb

  15. The Sass/LESS way @onishiweb

  16. The BEM way @onishiweb

  17. The SMACSS way @onishiweb

  18. The OOCSS way @onishiweb

  19. The Atomic CSS way @onishiweb

  20. @onishiweb • Naming convention • Namespacing • Reduce specificity •

    Easy to understand • Require discipline
  21. The Origami way… @onishiweb

  22. Specificity must be minimised. Use BEM… Origami spec http://origami.ft.com/docs/syntax/scss/

  23. An example: @onishiweb

  24. @onishiweb

  25. <div class="o-gallery" o-gallery> <ul class="o-gallery__content"> <li class="o-gallery__slide"> <figure class="o-gallery__figure"> <img

    src="#" alt="text" class="o-gallery__image"> <figcaption class="o-gallery__caption"> This is an image caption </figcaption> </figure> </li> </ul> </div>
  26. <div class This is an image caption </div> <div class="o-gallery"

    o-gallery>
  27. o-gallery__figure o-gallery__image o-gallery__caption <div class This is an image caption

    </div>
  28. .o-gallery__figure {} .o-gallery__figure__image {} .o-gallery__figure__caption {}

  29. .o-gallery__figure {} .o-gallery__figure__image {} .o-gallery__figure__caption {} // Better .o-gallery__figure {}

    .o-gallery__image {} .o-gallery__caption {}
  30. .o-gallery__control { position: absolute; top: 50%; width: 30px; height: 70px;

    } .o-gallery__control--left { left: 0; background-image: url(''), none; } .o-gallery__control--right { right: 0; background-image: url(''), none; }
  31. this.controlLeft = document.createElement('button'); this.controlLeft.className = 'o-gallery__control o-gallery__control-- left';

  32. Using Origami components @onishiweb

  33. @import "o-assets/main"; @import "o-colors/main"; @import "o-icons/main"; @import "o-hoverable/main"; @import "o-gallery/main";

  34. require('o-date'); require('o-header'); require('o-gallery');

  35. Alice Bartlett Origami Lead, Financial Times @alicebartlett Can’t you make

    it more like Bootstrap? Considerations for building front end systems
  36. What about HTML? @onishiweb

  37. Customisation @onishiweb

  38. /// General styling for the gallery @mixin oGallery { [...]

    } /// Styling for the gallery title @mixin oGalleryTitle { [...] }
  39. The Cascade @onishiweb

  40. The current Origami way… @onishiweb

  41. 1. CSS 2. CSS Modules 3. Web Components

  42. Remix culture @onishiweb

  43. @onishiweb

  44. The CSS Modules way…

  45. What is CSS Modules? @onishiweb

  46. [CSS where] all class names and animation names are scoped

    locally by default CSS Modules Spec https://github.com/css-modules/css-modules
  47. .gallery { } .wrapper { } .content { } .slide

    { }
  48. ._gallery_1rsuk_1 { } ._wrapper_1rsuk_7 { } ._content_1rsuk_13 { } ._slide_1rsuk_25

    { }
  49. Values and composes @onishiweb

  50. @value primary: red; .btn-primary { background: white; border: 1px solid

    primary; color: primary; }
  51. .btn-primary { background: white; border: 1px solid red; color: red;

    } .btn-secondary { composes: btn-primary; border-color: blue; color: blue; }
  52. <button class="app__btnSecondary___3JL8l app__btnPrimary___1y7r3"></button>

  53. Truly component only CSS @onishiweb

  54. Requires a build step @onishiweb

  55. @onishiweb • Webpack • Browserify • Babel • PostCSS •

    JSPM
  56. An example: @onishiweb

  57. @onishiweb

  58. No more .html @onishiweb

  59. <div class="<%= className('styles', 'gallery') %>" o- gallery> <ul class="<%= className('styles',

    'content') %>"> <li class="<%= className('styles', 'slide') %>"> <figure class="<%= className('styles', 'figure') %>"> <img src="#" alt="#" class="<%= className('styles', 'image') %>"> <figcaption class="<%= className('styles', 'caption') %>"> This is an image caption </figcaption> </figure> </li> </ul> </div>
  60. <div gallery %>" className('styles', 'image') %>" 'caption') %>" This is

    an image caption </div> <%= className('styles', 'gallery') %>
  61. What about the JavaScript? @onishiweb

  62. this.controlLeft = document.createElement('button'); this.controlLeft.className = className('styles', 'control-left');

  63. Great in a JavaScript world @onishiweb

  64. Atomic CSS Modules @onishiweb

  65. We decided to solve the main Atomic CSS-related problems using

    the power of CSS Modules, getting all the benefits of both solutions. Michele Bertoli https://medium.com/yplan-eng/atomic-css-modules-cb44d5993b27#.p7jtpneoh
  66. Is Origami going to use CSS Modules? @onishiweb

  67. No.

  68. First Class Styles - Mark Dalgleish Front Trends 2016 https://www.youtube.com/watch?v=KmtgJ1d4zuY

  69. The alternative way… @onishiweb

  70. Delayed 1. Automobiles 2. Trains 3.

  71. 1. CSS 2. CSS Modules 3. Web Components

  72. The Web Components way…

  73. Create your own elements and encapsulate their CSS

  74. @onishiweb But what does that mean‽

  75. <div class="o-gallery" o-gallery> <ul class="o-gallery__content"> <li class="o-gallery__slide"> <figure class="o-gallery__figure"> <img

    src="#" alt="text" class="o-gallery__image"> <figcaption class="o-gallery__caption"> This is an image caption </figcaption> </figure> </li> </ul> </div>
  76. <o-gallery> <img src="#" alt="text"> <img src="#" alt="text"> <img src="#" alt="text">

    </o-gallery>
  77. Warning! New specifications and lots of code coming up @onishiweb

  78. Custom Elements @onishiweb

  79. <o-gallery></o-gallery>

  80. <span></span>

  81. customElements.define('o-gallery', …);

  82. class OGallery extends HTMLElement { constructor() { super(); [...] }

    [...] } customElements.define('o-gallery', OGallery);
  83. class OGallery extends HTMLElement { connectedCallback() { [...] } }

  84. const oGallery = document.createElement('o-gallery'); // Show the next slide oGallery.nextSlide();

    // Show the previous slide oGallery.previousSlide();
  85. <o-gallery> <img src="#" alt="text"> <img src="#" alt="text"> <img src="#" alt="text">

    </o-gallery>
  86. Shadow DOM @onishiweb

  87. This is where things get spooky and weird! Soledad Penades

    https://www.youtube.com/watch?v=2vWgJ7w3hu0
  88. @onishiweb

  89. Creating a Shadow DOM @onishiweb

  90. constructor() { super(); const shadow = this.attachShadow({ mode: 'open' });

    }
  91. Populating Shadow DOM @onishiweb

  92. <!-- Light DOM --> <o-gallery> <img src="#" alt="text"> <img src="#"

    alt="text"> <img src="#" alt="text"> </o-gallery>
  93. Templates @onishiweb

  94. <template> <!-- Shadow DOM --> <div class="slides"> <div class="slide"></div> </div>

    <button class="control-left"></button> <button class="control-right"></button> </template>
  95. // Attaches a shadow Root to your element const shadowRoot

    = this.attachShadow({mode: 'open'}); // Get the custom template, clone it const template = document.querySelector('#o-gallery'); const clone = this.importNode(template, true); // Insert it into our shadow DOM shadowRoot.appendChild(clone);
  96. Slots @onishiweb

  97. <template> <div class="container"> <slot name="slides"></slot> </div> </template>

  98. <o-gallery> <img src="/assets/img/plane.jpg" alt="Delayed plane" slot="slides"> </o-gallery>

  99. <!-- Composed DOM --> <o-gallery> #shadow-root <div class="slides"> <img src="/assets/img/plane.jpg"

    alt="Delayed plane"> </div> <button class="control-left"></button> <button class="control-right"></button> </o-gallery>
  100. Styling web components @onishiweb

  101. <template> <style> :host { background-color: #333; } #slide { margin:

    0; } img { display: block; } .caption { color: #fff; } </style> </template>
  102. Fully encapsulated styles @onishiweb

  103. Shadow Boundary @onishiweb

  104. ::host @onishiweb

  105. ::host { background-color: #333; } ::host(.theme—light) { background-color: #fff1e0; }

    ::host(:hover) { /* hover styles */ }
  106. ::host-context @onishiweb

  107. ::host-context(.theme-reverse) { background-color: #fff1e0; } ::host-context(.streams) { /* styles */

    }
  108. ::slotted @onishiweb

  109. ::slotted(img) { display: block; margin: 0; } ::slotted(figcaption) { font-style:

    italic; margin: 10px 0; }
  110. @onishiweb Shadow Host Shadow Root Shadow Boundary Slots Light DOM

    Shadow DOM Composed DOM Shadow Tree
  111. Customising Web Components @onishiweb

  112. CSS Custom properties @onishiweb

  113. /* product CSS */ --caption-color: #fff1e0; /* Component styles */

    .caption { color: var(--caption-color, white); }
  114. CSS Mixins @onishiweb

  115. .caption { --caption-styles: { color: red; font-size: 14px; }; }

    .caption { @apply(--caption-styles); }
  116. Do I need to use every one of the specifications?

    @onishiweb
  117. No @onishiweb

  118. What about Progressive Enhancement? @onishiweb

  119. Everything is JavaScript @onishiweb

  120. <o-gallery> <img src="#" alt="text"> <img src="#" alt="text"> <img src="#" alt="text">

    </o-gallery>
  121. ::defined @onishiweb

  122. o-gallery:not(:defined) { display: block; } o-gallery:not(:defined) img { display: none;

    } o-gallery:not(:defined) img:first-child { display: block; width: 100%; height: auto; }
  123. Extending native elements @onishiweb

  124. <!-- Using the is="" attribute --> <button is="o-button">Press me!</button>

  125. Apple objects to extending subclasses of HTMLElement using is= Ryosuke

    Niwa https://github.com/w3c/webcomponents/issues/509#issuecomment-222860736
  126. Let a button be a button! @onishiweb

  127. https://github.com/webcomponents/gold-standard/wiki The Web Components Gold Standard

  128. This will make sure accessibility is better too! @onishiweb

  129. What this means for Origami @onishiweb

  130. A lot more design opinionated @onishiweb

  131. We can offer markup too… @onishiweb

  132. https://github.com/Polymer/vulcanize Bundling HTML imports

  133. HTTP/2? @onishiweb

  134. A lot more work to do @onishiweb

  135. Using Web Components today @onishiweb

  136. The road to v1… @onishiweb

  137. Polyfill @onishiweb

  138. Libraries @onishiweb

  139. @onishiweb • Polymer • x-tag • Bosonic

  140. Beware! Here be dragons…

  141. http://webcomponents.org/

  142. https://developers.google.com/web/fundamentals/primers/customelements/

  143. https://developers.google.com/web/fundamentals/primers/customelements/

  144. Web Components are here!

  145. Almost…

  146. Honestly, like really close…

  147. 1. Automobiles 2. Trains 3. Planes

  148. 1. CSS 2. CSS Modules 3. Web Components

  149. Adam Onishi Financial Times @onishiweb Thank you!