!important
et inline, on en parle ?Use only imports, variables, and mixins (and only for vender-prefixed features) from CSS preprocessors
Use the .component-descendant-descendant
pattern for components
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
Use the .component-descendant.mod-modifier
pattern for modifier classes
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.
Message de succès
Message d'erreur
.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;
}
}
Use the.component-descendant.is-state
pattern for state.
Manipulate.is-
classes in JavaScript (but not presentation classes).
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
.is-loading
pour le status "en chargement", à toi de jouer !Chaque composant définit ses propres états
Jamais de .is-
sans composant ciblé !
Donc
.is-hidden { display: none; }
=
« Permit denied »
Use media query variables in your component.
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
Pat
Add
// components/member-list.less
.member-list-item-button {
float: right;
padding: 6px 10px;
}
Ce qu'il faut faire :
Gumby
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 !
Separate style and behavior concerns by using .js-
prefixed classes for behavior.
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
Prefix mixins with .m-
and only use them sparingly for shared styles.
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();
}
Prefix utility classes with .u-
.
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