Explorer SMACSS : architecture évolutive et modulaire pour CSS
Publié: 2022-03-11Lorsque nous travaillons sur de gros projets ou avec des groupes de développeurs, nous constatons souvent que notre code est désordonné, difficile à lire et difficile à étendre. Cela est particulièrement vrai après que le temps passe et que nous revenons et le regardons à nouveau - nous devons essayer d'être dans le même état d'esprit où nous étions lorsque nous l'avons écrit.
Donc, ce que beaucoup de gens ont fait, c'est qu'ils ont créé des architectures CSS pour aider à styliser leur code afin que CSS devienne plus lisible. C'est exactement ce que vise SMACSS , c'est-à-dire l'architecture évolutive et modulaire pour CSS . C'est un ensemble particulier de directives d'architecture CSS de Jonathan Snook que j'ai adopté.
Maintenant, l'approche architecturale de SMACSS est un peu différente d'un framework CSS comme Bootstrap ou Foundation. Au lieu de cela, il s'agit d'un ensemble de règles, plus comme un modèle ou un guide. Plongeons-nous donc dans certains modèles de conception CSS pour découvrir comment nous pouvons les utiliser pour rendre notre code meilleur, plus propre, plus facile à lire et plus modulaire.
Chaque structure de projet SMACSS utilise cinq catégories :
- Base
- Mise en page
- Modules
- État
- Thème
Base
Dans SMACSS, les styles de base définissent à quoi un élément doit ressembler n'importe où sur la page. Ce sont les valeurs par défaut. Si vous utilisez une feuille de style de réinitialisation, cela garantit que vos styles résultants sont les mêmes dans tous les navigateurs malgré les différences entre leurs valeurs par défaut CSS de base codées en dur.
Dans un style de base, vous ne devez inclure que des sélecteurs d'éléments nus, ou ceux avec des pseudo-classes, mais pas avec des sélecteurs de classe ou d'ID. (Vous devriez avoir une très bonne raison d'y mettre une classe ou un ID, peut-être seulement si vous stylisez les éléments d'un plugin tiers et que vous devez remplacer le style par défaut pour cet élément particulier.)
Voici un exemple de ce à quoi devrait ressembler une unité de fichier de base :
html { margin: 0; font-family: sans-serif; } a { color: #000; } button { color: #ababab; border: 1px solid #f2f2f2; }
Il doit donc inclure les tailles, les marges, les couleurs, les bordures par défaut et toute autre valeur par défaut que vous prévoyez d'utiliser sur votre site Web. Votre typographie et vos éléments de formulaire doivent avoir des styles unifiés qui apparaissent sur chaque page et donner l'impression qu'ils font partie du même design et du même thème.
SMACSS ou non, je recommande fortement d'éviter autant que possible l'utilisation de !important
, et de ne pas utiliser l'imbrication profonde, mais j'en reparlerai plus tard dans ce post. De plus, si votre pratique consiste à utiliser le CSS de réinitialisation, c'est l'endroit où vous devez l'inclure. (Je préfère utiliser Sass, donc je l'inclus simplement en haut du fichier, plutôt que d'avoir à le copier ou à y faire référence séparément de l'élément <head>
de chaque page.)
Mise en page
Les styles de mise en page diviseront la page en sections principales - pas des sections comme la navigation ou peut-être l'accordéon, par exemple, mais vraiment des divisions de niveau supérieur :
Ces mises en page contiendront plusieurs modules CSS tels que des boîtes, des cartes, des listes non ordonnées, des galeries, etc., mais je parlerai davantage des modules dans la section suivante. Prenons un exemple de page Web pour voir ce que nous pouvons diviser en mises en page :
Ici, nous avons l'en-tête, le principal et le pied de page. Ces mises en page ont des modules comme des liens et un logo sur l'en-tête en haut, des boîtes et des articles sur le principal, et des liens et des droits d'auteur pour le pied de page. Nous donnons généralement aux mises en page un sélecteur d'ID, car elles ne se répètent pas sur la page et elles sont uniques.
Vous devez également préfixer les règles pour les styles de mise en page avec la lettre l
pour les distinguer des styles de module. Habituellement, ici, vous stylisez des éléments spécifiques à la mise en page, comme la bordure, les alignements, les marges, etc. De plus, l'arrière-plan de cette partie de la page peut avoir un sens, même s'il ne semble pas aussi spécifique à la mise en page.
Voici un exemple de ce à quoi cela devrait ressembler :
#header { background: #fcfcfc; } #header .l-right { float: right; } #header .l-align-center { text-align: center; }
Vous pouvez également ajouter ces aides pour les alignements que vous pouvez utiliser pour positionner facilement des éléments en ajoutant simplement la classe appropriée à son enfant ou pour aligner son texte.
Pour un autre exemple, vous pouvez utiliser des marges par défaut sur une boîte de mise en page, comme .l-margin
ayant une marge de 20px
. Ensuite, où que vous souhaitiez un remplissage pour un conteneur, un élément, une carte ou une boîte, il vous suffit d'y ajouter la classe l-margin
. Mais vous voulez quelque chose de réutilisable :
.l-full-width { width: 100%; }
Pas quelque chose de couplé en interne comme celui-ci :
.l-width-25 { width: 25px; }
Je veux prendre un moment pour parler des conventions de nommage dans SMACSS. Si vous n'avez jamais entendu parler du concept d'espacement de noms dans CSS, il s'agit essentiellement d'ajouter le nom au début d'un autre élément pour aider à le distinguer de tout le reste. Mais pourquoi avons-nous besoin de cela ?
Je ne sais pas si vous avez déjà rencontré le problème suivant. Vous écrivez du CSS et vous avez une étiquette sur quelque chose - vous mettez les styles que vous aimez et appelez votre classe .label
. Mais ensuite, vous arrivez à un autre élément plus tard, et vous voulez également qu'il soit .label
, mais stylisez-le différemment. Donc, deux choses différentes ont le même nom - un conflit de noms.
L'espacement des noms vous aide à résoudre ce problème. En fin de compte, ils s'appellent la même chose à un niveau, mais ils ont un espace de noms différent - un préfixe différent - et peuvent donc représenter deux styles différents :
.box--label { color: blue; } .card--label { color: red; }
Module
Comme je l'ai mentionné plus tôt, les modules SMACSS sont de plus petits morceaux de code qui sont réutilisables sur la page, et ils font partie d'une seule mise en page. Ce sont des parties de CSS que nous voulons stocker dans un dossier séparé, car nous en aurons beaucoup sur une seule page. Et au fur et à mesure qu'un projet grandit, nous pouvons le diviser en utilisant les meilleures pratiques de structure de dossiers, c'est-à-dire par modules/pages :

Ainsi, dans l'exemple précédent, nous avions un article, qui peut être un module à lui tout seul. Comment le CSS devrait-il être structuré ici ? Nous devrions avoir une classe .article
qui peut avoir des éléments enfants title
et text
. Donc, pour pouvoir le garder dans le même module, nous devons préfixer les éléments enfants :
.article { background: #f32; } .article--title { font-size: 16px; } .article--text { font-size: 12px; }
Vous remarquerez peut-être que nous utilisons deux traits d'union après le préfixe du module. La raison en est que parfois les noms de module ont deux mots ou leurs propres préfixes comme big-article
. Nous avons besoin de deux traits d'union pour dire quelle partie de celui-ci est l'élément enfant - par exemple comparer big-article-title
à big-article--title
et big-article--text
.
De plus, vous pouvez imbriquer des modules dans des modules si un module particulier occupe une grande partie de la page :
<div class="box"> <div class="box--label">This is box label</div> <ul class="box--list list"> <li class="list--li">Box list element</li> </ul> </div>
Ici, dans cet exemple simple, vous pouvez voir que box
est un module et list
est un autre module à l'intérieur. Donc list--li
est un enfant du module list
et non de box
. L'un des concepts clés ici est d'utiliser deux sélecteurs au maximum pour chaque règle CSS, mais dans la plupart des scénarios, il n'y a qu'un seul sélecteur avec des préfixes.
De cette façon, nous pouvons éviter de dupliquer des règles et également d'avoir des sélecteurs supplémentaires sur des éléments enfants portant les mêmes noms, améliorant ainsi la vitesse. Mais cela nous aide également à éviter d'utiliser les règles de style !important
indésirables, qui sont un signe de projets CSS mal structurés.
Bon (notez le sélecteur unique):
.red--box { background: #fafcfe; } .red-box--list { color: #000; }
Mauvais (notez la répétition dans les sélecteurs et la méthode de référence qui se chevauche):
.red .box { background: #fafcfe; } .red .box .list { color: #000; } .box ul { color: #fafafa; }
État
L'état défini dans SMACSS est une façon de décrire l'apparence de nos modules dans différentes situations dynamiques. Cette partie est donc vraiment destinée à l'interactivité : nous voulons un comportement différent si un élément est considéré comme masqué, développé ou modifié. Par exemple, un accordéon jQuery aura besoin d'aide pour définir quand vous pouvez ou non voir le contenu d'un élément. Cela nous aide à définir le style d'un élément à un moment précis.
Les états sont appliqués au même élément que la mise en page, nous ajoutons donc une règle supplémentaire qui remplacera les précédentes, le cas échéant. La règle d'état est prioritaire, car c'est la dernière dans la chaîne de règles.
Comme pour les styles de mise en page, nous avons tendance à utiliser des préfixes ici. Cela nous aide à les reconnaître et à leur donner la priorité. Ici, nous utilisons le préfixe is
, comme dans is-hidden
ou is-selected
.
<header> <ul class="nav"> <li class="nav--item is-selected">Contact</li> <li class="nav--item">About</li> </ul> </header>
.nav--item.is-selected { color: #fff; }
Ici, !important
peut être utilisé, car l'état est souvent utilisé comme une modification JavaScript et non au moment du rendu. Par exemple, vous avez un élément masqué lors du chargement de la page. Au clic sur le bouton, vous voulez l'afficher. Mais la classe par défaut ressemble à ceci :
.box .element { display: none; }
Donc, si vous ajoutez simplement ceci :
.is-shown { display: block; }
Il restera masqué même après avoir ajouté la classe .is-shown
à l'élément via JavaScript. En effet, la première règle a deux niveaux de profondeur et la remplacera.
Vous pouvez donc à la place définir la classe d'état comme ceci :
.is-shown { display: block !important; }
C'est ainsi que nous distinguons les modificateurs d'état des modificateurs de mise en page, qui ne s'appliquent qu'au chargement initial d'une page. Cela fonctionnera maintenant tout en conservant les avantages des sélecteurs minimaux.
Thème
Celui-ci devrait être le plus évident, car il est utilisé pour contenir les règles des couleurs primaires, des formes, des bordures, des ombres, etc. Ce sont principalement des éléments qui se répètent sur l'ensemble d'un site Web. Nous ne voulons pas les redéfinir à chaque fois que nous les créons. Au lieu de cela, nous voulons définir une classe unique que nous n'ajouterons que plus tard à un élément par défaut.
.button-large { width: 60px; height: 60px; }
<button class="button-large">Like</button>
Ne confondez pas ces règles de thème SMACSS avec celles de base, car les règles de base ne ciblent que l'apparence par défaut et elles ont tendance à ressembler à la réinitialisation des paramètres de navigateur par défaut, alors qu'une unité de thème est plus un type de style où elle donne le look final, unique pour ce jeu de couleurs spécifique.
Les règles de thème peuvent également être utiles si un site a plus d'un style ou peut-être quelques thèmes utilisés dans différents états et peuvent donc être facilement modifiés ou échangés lors de certains événements sur une page, par exemple avec un bouton de changement de thème. À tout le moins, ils conservent tous les styles de thème au même endroit afin que vous puissiez les modifier facilement et les garder bien organisés.
Méthodologies d'organisation CSS
J'ai couvert certains des concepts clés de cette idée d'architecture CSS. Si vous voulez en savoir plus sur ce concept, vous pouvez visiter le site officiel de SMACSS et approfondir.
Oui, vous pouvez probablement utiliser des méthodologies plus avancées comme OOCSS et BEM. Ce dernier couvre presque tout le flux de travail frontal et ses technologies. Les sélecteurs BEM peuvent fonctionner très bien pour certaines personnes, mais certains peuvent les trouver trop longs et accablants, et aussi trop compliqués à utiliser. Si vous avez besoin de quelque chose de plus simple, plus facile à comprendre et à intégrer dans votre flux de travail, et aussi quelque chose qui définit les règles de base pour vous et votre équipe, SMACSS est la solution idéale.
Il sera facile pour les nouveaux membres de l'équipe non seulement de comprendre ce que les développeurs précédents ont fait, mais aussi de commencer à travailler dessus instantanément, sans aucune différence de style de codage. SMACSS n'est qu'une architecture CSS et il fait ce qu'il dit sur l'étain, rien de plus et rien de moins.