Architecture/Méthodologie CSS
"Margin breaks component encapsulation. A well-built component should not affect anything outside itself." (Max Stoiber)
- Séparer l'espacement du composant !
- l'espacement devrait être gérer au niveau du parent (composant de layout, classes utilitaires d'espacement,...)
- Utiliser des margins dans une seule direction (être consistent avec toute la base de code, soit mettre la marge en haut soit en bas par exemple)
Ma structure idéale
- Pour le CSS réutilisable (components et skeleton) : suivre la convention de nommage BEM
- Pour gérer le layout, une approche "Atomic CSS" : soit composant de layout soit une classe utilitaire (exemple
p-1
pour le padding). - Pour la structure des dossiers, l'approche ITCSS
/scss/
├── 0-vendors // = code css des librairies externes si on ne passe pas par npm.
Ne pas modifier directement le fichier source !! Faire un fichier à part pour les surcouches css.
│ └── _my-lib1.scss
│ └── _my-lib1-override.scss
│ ├── ...
├── 1-settings // ou "design-tokens"
│ └── _global.scss // Variables globales
│ ├── _colors.scss
│ ├── _fonts.scss
│ ├── _media-queries.scss
│ ├── _shadows.scss
│ ├── _spacing.scss
│ └── _typography.scss
│ ├── ...
├── 2-tools // Tous les mixins & fonctions sass
│ ├── _aspect-ratio.scss
│ ├── _blend-modes.scss
│ ├── ...
├── 3-generic
│ ├── _box-sizing.scss
│ ├── _font-face.scss
│ ├── _normalize.scss // CSS Reset
│ └── _print.scss
│ ├── ...
├── 4-elements // Style des éléments HTML classiques (h1, a, p,...)
│ ├── _forms.scss
│ ├── _headings.scss
│ ├── _images.scss
│ └── ...
├── 5-skeleton // tout ce qui sert de wrapper, container, grid, layouts, etc
│ ├── _grid.scss
│ ├── _layouts.scss
│ └── ...
├── 6-components
│ ├── _accordion.scss
│ ├── _card.scss
│ └── ...
├── 7-utilities // ou "helpers" : classes utilitaires
│ ├── _modifiers.scss
│ └── _states.scss
├── _shame.scss // Liste des hacks avec leurs documentations (voir point plus bas)
└── main.scss // Ne fait que importer tous les fichiers
Shame.scss
- Idée de https://csswizardry.com/2013/04/shame-css/
- Si c'est un hack, le css va dans ce fichier
- Documenter le hack : quelle partie du code est ciblée, pourquoi, comment le fixer
- Fixer le fichier au fur et à mesure
Architecture CSS
ITCSS
- = Inverted Triangle CSS
- Séparer la base de code CSS en différentes couches, qui vont du moins au plus spécifique
- Exemple de structure de code : settings, tools, generic, elements, objects, components, utilities
- A noter que les couches "settings" et "tools" ne produisent aucun css, ce sont juste des variables/mixins utilisées par le préprocesseur
- Un fichier par composant
Conventions de nommage
BEM
- = Block Element Modifier
- Convention de nommage
- Exemple :
- Block :
.btn
- Element :
.btn__price
(élément prix qui dépend du bloc) - Modifier :
.btn--orange
(modificateur qui change le style du bloc)
- Block :
- Avec l'utilisation des trois :
.nomDuBloc__element--modifier
- Pour le "modifier" il vaut mieux avoir deux classes block et modifier (
btn btn--secondary
) que juste la classe de modifier seule (btn--secondary
) - Utiliser seulement des classes, et pas de parent si l'enfant suffit
OOCSS
- = Object oriented CSS (POO)
- Deux types de classes :
- Pour la structure d'un composant
- Pour l'esthétique variable, qui viennent étendre les premières
- Réutilisation des objets donc indépendances, différence conteneurs vs contenants
CSS Fonctionnel
- Atomic CSS / Classes utilitaires (ex : border--transparent, border, cursor-pointer, round-bold)
- Pourquoi une classe utilitaire est mieux qu'un style inline ?
- On vient rajouter une abstraction et une contrainte (ex:
padding-1
= 0.5rem, c’est une valeur qui peut être changé à un seul endroit de l’application) => utilisation possible de variables (design tokens) => le développeur ne peut pas faire ce qu’il veut ! - Le style inline est appliqué uniquement sur l’élément déclaré vs la classe utilitaire est réutilisée
- Vu que c’est une classe, la classe utilitaire peut avoir un style au hover, être utilisée dans une media query,...
- Le cache fonctionne mal avec les styles inline
- On peut avoir une classe utilitaire qui contient plusieurs propriétés (exemple : pour avoir une ellipsis sur son texte, ou pour afficher un élément uniquement pour le screen reader)
- On vient rajouter une abstraction et une contrainte (ex:
Sources
- How to handle spacing at scale (2022)
- ITCSS: Scalable and Maintainable CSS Architecture (2021)
- How I Structure My CSS (2020)
- Creating the “Perfect” CSS System (2018)
- Sur les classes utilitaires