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

ember-css-modules

 ember-css-modules

A look at the ember-css-modules addon, the the problems that motivate it and how it attempts to solve them.

https://youtu.be/tgLHPSOmpWQ?t=1h3m17s

Avatar for Dan Freeman

Dan Freeman

May 12, 2016
Tweet

More Decks by Dan Freeman

Other Decks in Programming

Transcript

  1. CSS is great. It’s… overflow: hidden; /* hide extra content

    */ overflow: hidden; /* clear child floats */ overflow: hidden; /* introduce a new BFC */ Clear white-space: nowrap; background-repeat: no-repeat; border-color: currentColor; Consistent word-break: break-all; word-wrap: break-word; Coherent I’m sure you remember the difference, right? wowsuch easy-to-remember namingConventions Obviously.
  2. {{! nav-item/template.hbs }} <div class={{if active 'active'}}> {{! ... }}

    </div> // nav-item/component.js export default Component.extend({ active: false, // ... }); /* some css file */ .active { background-color: #e7e7e7; } {{! dropdown-menu/template.hbs }} <div class="trigger">{{! ... }}</div> <div class="content {{if active 'active'}}"> {{! ... }} </div> // dropdown-menu/component.js export default Component.extend({ active: false, // ... }); /* some css file */ .content.active { display: block; } Navigation Bar Dropdown
  3. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ active: false, // ... }); /* some css file */ .active { background-color: #e7e7e7; } // dropdown-menu/component.js export default Component.extend({ active: false, // ... }); Dropdown {{! dropdown-menu/template.hbs }} <div class="trigger">{{! ... }}</div> <div class="content {{if active 'active'}}"> {{! ... }} </div> /* some css file */ .content.active { display: block; }
  4. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ active: false, // ... }); /* some css file */ .active { background-color: #e7e7e7; } Dropdown {{! dropdown-menu/template.hbs }} <div class="trigger">{{! ... }}</div> <div class="content {{if active 'active'}}"> {{! ... }} </div> // dropdown-menu/component.js export default Component.extend({ active: false, // ... }); /* some css file */ .content.active { display: block; }
  5. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ active: false, // ... }); /* some css file */ .active { background-color: #e7e7e7; } // dropdown-menu/component.js export default Component.extend({ active: false, // ... }); Dropdown {{! dropdown-menu/template.hbs }} <div class="trigger">{{! ... }}</div> <div class="content {{if active 'active'}}"> {{! ... }} </div> /* some css file */ .content.active { display: block; }
  6. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* some css file */ .nav-item .active { background-color: #e7e7e7; } Dropdown {{! dropdown-menu/template.hbs }} <div class="trigger">{{! ... }}</div> <div class="content {{if active 'active'}}"> {{! ... }} </div> // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* some css file */ .dropdown-menu .content.active { display: block; }
  7. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* some css file */ .nav-item .active { background-color: #e7e7e7; } Dropdown {{! dropdown-menu/template.hbs }} <div class="trigger">{{! ... }}</div> <div class="content {{if active 'active'}}"> {{! ... }} </div> // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* some css file */ .dropdown-menu .content.active { display: block; }
  8. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* some css file */ .nav-item .active { background-color: #e7e7e7; } Dropdown {{! dropdown-menu/template.hbs }} <div class="trigger">{{! ... }}</div> <div class="content {{if active 'active'}}"> {{! ... }} </div> // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* some css file */ .dropdown-menu .content.active { display: block; }
  9. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* some css file */ .nav-item .active { background-color: #e7e7e7; } Dropdown {{! dropdown-menu/template.hbs }} <div class="trigger">{{! ... }}</div> <div class="content {{if active 'active'}}"> {{! ... }} </div> // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* some css file */ .dropdown-menu .content.active { display: block; } appletoncreative.com BEM SMACSS SUIT OOCSS
  10. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* some css file */ .nav-item .active { background-color: #e7e7e7; } Dropdown {{! dropdown-menu/template.hbs }} <div class="trigger">{{! ... }}</div> <div class="content {{if active 'active'}}"> {{! ... }} </div> // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* some css file */ .dropdown-menu .content.active { display: block; }
  11. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'nav-item--active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* some css file */ .nav-item--active { background-color: #e7e7e7; } Dropdown {{! dropdown-menu/template.hbs }} <div class="dropdown-menu__trigger">{{! ... }} <div class="dropdown-menu__content {{if active 'dropdown-menu__content--active'}}"> {{! ... }} </div> // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* some css file */ .dropdown-menu__content--active { display: block; }
  12. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'nav-item--active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* some css file */ .nav-item--active { background-color: #e7e7e7; } Dropdown // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* some css file */ .dropdown-menu__content--active { display: block; } {{! dropdown-menu/template.hbs }} <div class="dropdown-menu__trigger">{{! ... }} <div class="dropdown-menu__content {{if active 'dropdown-menu__content--active'}}"> {{! ... }} </div>
  13. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'nav-item--active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* some css file */ .nav-item--active { background-color: #e7e7e7; } Dropdown // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* some css file */ .dropdown-menu__content--active { display: block; } {{! dropdown-menu/template.hbs }} <div class="dropdown-menu__trigger">{{! ... }} <div class="dropdown-menu__content {{if active 'dropdown-menu__content--active'}}"> {{! ... }} </div>
  14. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'nav-item--active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* some css file */ .nav-item--active { background-color: #e7e7e7; } Dropdown // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* some css file */ .dropdown-menu__content--active { display: block; } {{! dropdown-menu/template.hbs }} <div class="dropdown-menu__trigger">{{! ... }} <div class="dropdown-menu__content {{if active 'dropdown-menu__content--active'}}"> {{! ... }} </div>
  15. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active 'nav-item--active'}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* some css file */ .nav-item--active { background-color: #e7e7e7; } Dropdown // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* some css file */ .dropdown-menu__content--active { display: block; } {{! dropdown-menu/template.hbs }} <div class="dropdown-menu__trigger">{{! ... }} <div class="dropdown-menu__content {{if active 'dropdown-menu__content--active'}}"> {{! ... }} </div>
  16. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active ??active??}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* nav-item/styles.css */ .active { background-color: #e7e7e7; } Dropdown // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* dropdown-menu/styles.css */ .active { display: block; } {{! dropdown-menu/template.hbs }} <div class="??trigger??">{{! ... }}</div> <div class="??content?? {{if active ??active??}}"> {{! ... }} </div>
  17. /* nav-item/styles.css */ .active { background-color: #e7e7e7; } /* nav-item/styles.css

    */ .active-a8537e6 { background-color: #e7e7e7; } // nav-item/styles.js export default { active: 'active-a8537e6' }; +
  18. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active ??active??}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* nav-item/styles.css */ .active { background-color: #e7e7e7; } Dropdown // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* dropdown-menu/styles.css */ .active { display: block; } {{! dropdown-menu/template.hbs }} <div class="??trigger??">{{!...}}</div> <div class="??content?? {{if active ??active??}}"> {{! ... }} </div>
  19. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active styles.active}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* nav-item/styles.css */ .active { background-color: #e7e7e7; } Dropdown // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* dropdown-menu/styles.css */ .active { display: block; } {{! dropdown-menu/template.hbs }} <div class={{styles.trigger}}>{{!...}}</div> <div class="{{styles.content}} {{if active styles.active}}”> {{! ... }} </div>
  20. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active styles.active}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* nav-item/styles.css */ .active { background-color: #e7e7e7; } Dropdown // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); {{! dropdown-menu/template.hbs }} <div class={{styles.trigger}}>{{!...}}</div> <div class="{{styles.content}} {{if active styles.active}}”> {{! ... }} </div> /* dropdown-menu/styles.css */ .active { display: block; }
  21. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active styles.active}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* nav-item/styles.css */ .active { background-color: #e7e7e7; } Dropdown // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* dropdown-menu/styles.css */ .active { display: block; } {{! dropdown-menu/template.hbs }} <div class={{styles.trigger}}>{{!...}}</div> <div class="{{styles.content}} {{if active styles.active}}”> {{! ... }} </div>
  22. Navigation Bar {{! nav-item/template.hbs }} <div class={{if active styles.active}}> {{!

    ... }} </div> // nav-item/component.js export default Component.extend({ classNames: 'nav-item', active: false, // ... }); /* nav-item/styles.css */ .active { background-color: #e7e7e7; } Dropdown // dropdown-menu/component.js export default Component.extend({ classNames: 'dropdown-menu', active: false, // ... }); /* dropdown-menu/styles.css */ .active { display: block; } {{! dropdown-menu/template.hbs }} <div class={{styles.trigger}}>{{!...}}</div> <div class="{{styles.content}} {{if active styles.active}}”> {{! ... }} </div>
  23. <!-- some-component/template.hbs --> <div class="{{styles.details}} vbox small"> <!-- ... -->

    </div> /* layout.css */ .vbox { display: flex; flex-flow: column; } /* typography.css */ .small { font-size: 10px; } /* some-component/styles.css */ .details { /* ... */ }
  24. <!-- live DOM --> <div class="details-a12d598 vbox small"> <!-- ...

    --> </div> /* my-app.css */ .vbox-bf35ff9 { display: flex; flex-flow: column; } .small-24cd534 { font-size: 10px; } .details-a12d598 { /* ... */ } ? ?
  25. <!-- some-component/template.hbs --> <div class="{{styles.details}} vbox small"> <!-- ... -->

    </div> /* layout.css */ .vbox { display: flex; flex-flow: column; } /* typography.css */ .small { font-size: 10px; } /* some-component/styles.css */ .details { /* ... */ }
  26. <!-- some-component/template.hbs --> <div class="{{styles.details}} vbox small"> <!-- ... -->

    </div> /* layout.css */ :global(.vbox) { display: flex; flex-flow: column; } /* typography.css */ :global(.small) { font-size: 10px; } /* some-component/styles.css */ .details { /* ... */ }
  27. <!-- live DOM --> <div class="details-a12d598 vbox small"> <!-- ...

    --> </div> /* my-app.css */ .vbox { display: flex; flex-flow: column; } .small { font-size: 10px; } .details-a12d598 { /* ... */ }
  28. <!-- some-component/template.hbs --> <div class="{{styles.details}} vbox small"> <!-- ... -->

    </div> /* layout.css */ .vbox { display: flex; flex-flow: column; } /* typography.css */ .small { font-size: 10px; } /* some-component/styles.css */ .details { /* ... */ }
  29. <!-- some-component/template.hbs --> <div class="{{styles.details}}"> <!-- ... --> </div> /*

    layout.css */ .vbox { display: flex; flex-flow: column; } /* typography.css */ .small { font-size: 10px; } /* my-component/styles.css */ .details { composes: vbox from 'layout'; composes: small from 'typography'; /* ... */ }
  30. <!-- live DOM --> <div class="details-a12d598 vbox-bf35ff9 small-24cd534"> <!-- ...

    --> </div> /* my-app.css */ .vbox-bf35ff9 { display: flex; flex-flow: column; } .small-24cd534 { font-size: 10px; } .details-a12d598 { /* ... */ }
  31. <!-- live DOM --> <div class="details-a12d598 vbox-bf35ff9 small-24cd534"> <!-- ...

    --> </div> /* my-app.css */ .vbox-bf35ff9 { display: flex; flex-flow: column; } .small-24cd534 { font-size: 10px; } .details-a12d598 { /* ... */ }
  32. <!-- live DOM --> <div class="details-a12d598 vbox-bf35ff9 small-24cd534"> <!-- ...

    --> </div> /* my-app.css */ .vbox-bf35ff9 { display: flex; flex-flow: column; } .small-24cd534 { font-size: 10px; } .details-a12d598 { /* ... */ }
  33. /* colors.css */ @value --grass-green: #5b5; /* progress-bar/styles.css */ @value

    --grass-green from 'colors'; .complete { background-color: --grass-green; } /* alert-message/styles.css */ @value --grass-green from 'colors'; .success { color: --grass-green; border: 1px solid --grass-green; }
  34. /* colors.css */ @value --grass-green: #5b5; /* progress-bar/styles.css */ @value

    --grass-green from 'colors'; .complete { background-color: --grass-green; } /* alert-message/styles.css */ @value --grass-green from 'colors'; .success { color: --grass-green; border: 1px solid --grass-green; }
  35. /* colors.css */ @value --grass-green: #5b5; /* progress-bar/styles.css */ @value

    --grass-green from 'colors'; .complete { background-color: --grass-green; } /* alert-message/styles.css */ @value --grass-green from 'colors'; .success { color: --grass-green; border: 1px solid --grass-green; }
  36. What about all my {Sass,Less,Stylus} syntax? What about those custom

    color functions I use? What about autoprefixer? What about feature X, Y and Z I can’t live without?
  37. Roadmap • Better support for custom syntax in PostCSS •

    Source map support • Live documentation • Better caching for warm builds and rebuilds • The template preprocessing question <div local-class="nav-item {{if active 'active'}}"> <!-- ... --> </div>
  38. We’d love your help! File bugs! Fix bugs! Try it

    out! Make it better! Help get to 1.0!