On Github bastientanesie / presentation-trello-css-guidelines
Pas de "sélecteur déscendant" :
.global-header {} .global-header .logo {} .global-header .logo img {}
Utilisation du namespacing :
.global-header {} .global-header-logo {} .global-header-logo-image {}
Spécificité la plus basse possible,évite les !important et le style inline
Besoin de transformer un élément dans un style particulier.
Exemple: un message en mode "erreur" ou "succès".
La base est commune (un bloc de message), mais change visuellement selon le but :Alerter, valider, informer, etc.
<div class="alert-message mod-succes">Message de succès</div> <div class="alert-message mod-error">Message d'erreur</div>
.alert-message {} .alert-message.mod-success {} .alert-message.mod-error {}
Ne JAMAIS déclarer un modifier seul !
Un modifier est toujours rattaché à un composant.
Permet l'utilisation d'un modifier de même nom sur plusieurs composants.
Exemple : .mod-success sur un message et un bouton
Si besoin d'écraser le style d'un déscendant,utiliser exceptionnelement le nesting.
.global-header-nav-item.mod-sign-up { background: hsl(120, 70%, 40%); color: #fff; .global-header-nav-item-text { font-weight: bold; } }
Gestion des états spécifiques des composants.
Exemple: .is-loading, .is-disabled, .is-hidden, etc.
Séparation des états et de la présentation.
Exemple du logo de Trello en mode "chargement" :
.global-header-logo-image { background: url("logo.png"); height: 40px; width: 200px; } .global-header-logo-image.is-loading { background: url("logo-loading.gif"); }
En BEM : .global-header-logo-image--is-loading
Chaque composant définit ses propres états
Jamais de .is- sans composant ciblé !
Donc.is-hidden { display: none; } =« Permit denied »
Regrouper toutes les Media Queries dans un seul fichier.
Chaque Media Query (ou break-point) est stockée dans une variable.
Déclaration des variables
@highdensity: ~"only screen and (-webkit-min-device-pixel-ratio: 1.5)", ~"only screen and (min--moz-device-pixel-ratio: 1.5)", ~"only screen and (-o-min-device-pixel-ratio: 3/2)", ~"only screen and (min-device-pixel-ratio: 1.5)"; @small: ~"only screen and (max-width: 750px)"; @medium: ~"only screen and (min-width: 751px) and (max-width: 900px)"; @large: ~"only screen and (min-width: 901px) and (max-width: 1280px)"; @extra-large: ~"only screen and (min-width: 1281px)"; @print: ~"print";
Utilisation des Media Queries dans les composants
/* Input */ @media @large { .component-nav {} } /* Output */ @media only screen and (min-width: 901px) and (max-width: 1280px) { .component-nav {} }
On peut améliorer les perfs en regroupant/compressant toutes les Media Queries
avec css-mqpacker par exemple
npm install css-mqpacker --save-dev
Un composant dans un autre : compo-ception !
La règle
Un composant ne doit rien connaître des autres
Exemple : une liste et un bouton
Besoin : modifier la taille et la position du bouton
Ce qu'il ne faut pas faire
<div class="member-list"> <div class="member-list-item"> <p class="member-list-item-name">Pat</p> <a href="#" class="member-list-item-button button">Add</a> </div> </div>
// components/member-list.less .member-list-item-button { float: right; padding: 6px 10px; }
Ce qu'il faut faire :
<div class="member-list"> <div class="member-list-item"> <p class="member-list-item-name">Gumby</p> <div class="member-list-item-action"><!-- conteneur pour la positon --> <a href="#" class="button mod-small">Add</a><!-- modifier pour la taille --> </div> </div> </div>
Beaucoup de composants, c'est normal
Ne pas hésiter à éclater les gros composants en plusieurs plus petits
Beaucoup de modifiers et/ou de déscendants ? Il est temps de splitter !
Séparation de la logique (JS) et de la présentation (CSS).
Rappel : ne jamais utiliser d'ID en JS
Utiliser des noms de classes clairs, qui ont du sens :
.js-open-content-menu au lieu de .js-menu
Ne jamais avoir un .js- dans un fichier CSS
Pour des styles partagés entre plusieurs composants
Pour les vendor-prefixes, on peut utiliser autoprefixer à la place
// mixins.less .m-list-divider () { border-bottom: 1px solid @light-gray-300; } // component.less .component-descendent { .m-list-divider(); }
clearfix, alignement vertical, styles de texte, etc.
.u-truncate-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
Tout ça dans un seul et même fichier.
Pas de .u-float-left, directement dans le composant
@charset "UTF-8" @import "normalize.css" // Variables @import "media-queries.less" @import "colors.less" @import "other-variables-like-fonts.less" // Mixins @import "mixins.less" // Utils @import "utils.less" // Components @import "component-1.less" @import "component-2.less" @import "component-3.less" @import "component-4.less" // and so forth
Si c'est bien fait, pas besoin d'organiser les composants
Comprennez : l'ordre des composants n'a pas d'importance
En sortie : un seul fichier CSS
Facile à compresser avec un task-runner à la mode
L'ordre des classes a son importance
component mod util state js
Comme si j'avais vraiment de l'expérience…
Sources