CSS at scale

CSS at scale

A little reminder about how CSS let's you do shit and how you should embrace the BEM methodology to make your code easy to read and write. (sorry for the crappy PDF export ūüė¨)

37500337ba5d2aebc962959ed83928e5?s=128

Matthias Le Brun

June 24, 2015
Tweet

Transcript

  1. 3.

    Les problèmes de CSS 1. Les selecteurs sont des variables

    globales .selector { font-size: 1rem; } = window.selector = { fontSize: "1rem", }
  2. 4.

    Les problèmes de CSS 2. La cascade .nav { font-size:

    0; } .nav .item { display: inline-block; /* font-size is 0 */ }
  3. 5.

    Les problèmes de CSS 3. La spécificité * {} /*

    specificity = 0,0,0,0 */ li {} /* specificity = 0,0,0,1 */ li:first-line {} /* specificity = 0,0,0,2 */ ul li {} /* specificity = 0,0,0,2 */ ul ol+li {} /* specificity = 0,0,0,3 */ h1 + *[rel=up]{} /* specificity = 0,0,1,1 */ ul ol li.red {} /* specificity = 0,0,1,3 */ li.red.level {} /* specificity = 0,0,2,1 */ #x34y {} /* specificity = 0,1,0,0 */ style="" /* specificity = 1,0,0,0 */ !important /* specificity = P,T,D,R */
  4. 7.

    Les problèmes de CSS 4. L'annulation de propriétés .item {

    display: block; font-size: 1rem; color: blue; /* un dev vient de rajouter la propriété `border` */ border: 1px solid red; } .some-context .item { display: inline-block; color: red; /* regression dans .some-context */ }
  5. 8.

    Les problèmes de CSS 5. La priorisation .blue { color:

    blue; } .red { color: red; } <!-- aucun contr√īle au niveau du markup --> <div class="blue red">text</div> <div class="red blue">text</div>
  6. 9.

    Les problèmes de CSS En résumé Un langage sans scope

    qui transmet automatiquement toute propri√©t√© d'un s√©lecteur √† ses descendants qui priorise les s√©lecteurs comme un ivrogne qui est r√©gression-friendly‚ĄĘ qui rend impossible la pr√©dictabilit√© de priorisation √† grande √©chelle
  7. 10.

    Ce qui n'aide pas non plus 1. @extend .blue {

    color: blue; } .red { color: red; } .my-selector { @extend .red; @extend .blue; }
  8. 11.

    Ce qui n'aide pas non plus 2. Les ¬ęCSS atomiques¬Ľ

    .block { display: block; } .inline-block { display: inline-block; } .relative { position: relative; } .absolute { position: absolute; } .static { position: static; } .padding-10 { padding: 10px; }
  9. 12.

    Ce qui n'aide pas non plus 2. OOCSS, SMACSS …

    Approches compliquées à apprendre à une équipe junior Différents niveaux non adaptés à un découpage en composants (layout, module, theme …)
  10. 13.

    BEM Block Element Modifier <div class="Header"> <div class="Header-nav"> <div class="Nav">

    <a href="/" class="Nav-item Nav-item--active"> Home </a> <a href="/about" class="Nav-item"> About </a> </div> </div> </div>
  11. 14.

    BEM Block le Block représente un composant Il peut être

    utilis√© sans contexte particulier Il peut avoir son private tree Il peut avoir un √©tat local (e.g. .Button--small) Cet √©tat est appliqu√© par un ¬ęModifier¬Ľ
  12. 15.

    BEM Element L'Element est un bloc appartenant au private tree

    de son ancêtre Block Il peut avoir un état local (e.g. .Nav-item--active)
  13. 17.

    BEM Block Element Modifier Une façon de structurer sainement son

    app/site Des r√®gles minimales Un nŇďud pouvant exister sans d√©pendre d'un anc√™tre est un Block .Block Un nŇďud pouvant n'exister qu'en tant que descendant d'un anc√™tre N est un element du Block N .Block-element Un √©tat local pour un Block ou un Element est d√©fini par un modifier de ce Block ou Element.Block--modifier ou .Block-element--modifier
  14. 18.
  15. 19.

    BEM Block Element Modifier: aller plus loin Dans le cas

    o√Ļ un block est enfant d'un autre block, pr√©f√©rer le wrapping √† la composition <!-- bad --> <div class="Header"> <div class="Header-nav Nav"><!-- ... --></div> </div> <!-- good --> <div class="Header"> <div class="Header-nav"> <div class="Nav"><!-- ... --></div> </div> </div>
  16. 20.
  17. 21.

    BEM Block Element Modifier: aller plus loin Prefixer les classNames

    par le nom de l'organisation, afin de prévenir les conflits avec le third-party <div class="org-Header"> <div class="org-Header-nav"> <div class="org-Nav"><!-- ... --></div> </div> </div>
  18. 22.

    BEM Block Element Modifier: aller plus loin √Čviter les side

    effects de la cascade en définissant les propriétés au niveau le plus bas possible /* bad */ .Nav { font-size: 2rem; } .Nav-item { padding: .5rem; } /* good */ .Nav {} .Nav-item { font-size: 2rem; padding: .5rem; }
  19. 23.

    BEM Block Element Modifier: aller plus loin Si votre stack

    vous impose des selecteurs pour les actions JS, utilisez des classNames uniquement prévus à cet effet <button class="org-Button org-Button--small org-js-OpenLoginModal"> Login </button>
  20. 24.

    BEM Block Element Modifier: aller plus loin Ne groupez jamais

    les media queries, gardez les toujours près des déclarations qu'elles complètent/override .Nav {} .Nav-item { font-size: 2rem; } @media(--maxM) { .Nav-item { font-size: 1.5rem; } }
  21. 25.

    BEM Block Element Modifier: les avantages Rend triviale la compréhension

    du markup et du style Crée rapidement des automatismes Apporte naturellement l'isolation des styles Permet d'éliminer facilement le code legacy Permet de repérer les différents niveaux de legacy en changeant de préfixe
  22. 26.

    Next steps Inline styles BEM résoud beaucoup de soucis, mais

    pas le contr√īle de la priorisation JavaScript + la propri√©t√© style nous le permettent + variables, conditions, modules ‚Ķ
  23. 27.

    Next steps Inline styles import React, {Component} from "react" import

    {lighten, darken} from "color" import styleVariables from "stylesVariables" const styles = { button: { display: "block", font-weight: 700, }, buttonDefault: { backgroundColor: styleVariables.colorBlue, }, buttonHover: { backgroundColor: lighten(styleVariables.colorBlue, .1), }, buttonPressed: { backgroundColor: darken(styleVariables.colorBlue, .1),
  24. 28.

    backgroundColor: darken(styleVariables.colorBlue, .1), }, } export class extends Component {

    state = { hover: false, pressed: false, } render() { const {text} = this.props const {hover, pressed} = this.state return ( <div style={{ ...styles.button, ...styles.buttonDefault, ...hover && styles.buttonHover, ...pressed && styles.buttonPressed, }}> {text} </div>
  25. 30.

    Next steps Inline styles: events import React, {Component} from "react"

    import {lighten, darken} from "color" import styleVariables from "stylesVariables" const styles = { button: { display: "block", font-weight: 700, }, buttonDefault: { backgroundColor: styleVariables.colorBlue, }, buttonHover: { backgroundColor: lighten(styleVariables.colorBlue, .1), }, buttonPressed: { backgroundColor: darken(styleVariables.colorBlue, .1),
  26. 31.

    backgroundColor: darken(styleVariables.colorBlue, .1), }, } export class extends Component {

    state = { hover: false, pressed: false, } handleMouseEnter() { this.setState({ hover: true, }) } handleMouseLeave() { this.setState({ hover: false, }) } handleMouseDown() {
  27. 32.

    handleMouseDown() { this.setState({ pressed: true, }) } handleMouseUp() { this.setState({

    pressed: false, }) } render() { const {text} = this.props const {hover, pressed} = this.state return ( <div onMouseEnter={() => this.handleMouseEnter()} onMouseLeave={() => this.handleMouseLeave()} onMouseDown={() => this.handleMouseDown()} onMouseUp={() => this.handleMouseUp()} style={{ ...styles.button,
  28. 34.

    Next steps Inline styles: bénéfices Permet de prioriser les styles

    Poss√®de naturellement des fonctions comme first class citizen JavaScript dispose d√©j√† d'un outillage int√©ressant pour l'analyse de code Rend possible la cohabitation de style & markup dans le m√™me fichier (tout comme avec des WebComponents) Abolit la sp√©cificit√© des selecteurs √Čvite au browser de parser la page pour dresser la correspondance selector/element