Makina Blog
Utiliser Bootstrap avec Sass
Découvrons comment utiliser plus efficacement Bootstrap à l'aide du préprocesseur Sass
Introduction
Démarrer avec le framework CSS de Bootstrap est relativement facile : il suffit d'inclure une feuille de style et d'écrire un balisage HTML avec des classes CSS définies et la magie de Bootstrap opère. Cette approche basique a toutefois des inconvénients :
- on peut se retrouver à inclure beaucoup de code CSS inutile
- les attributs
class
de nos éléments HTML peuvent rapidemment devenir redondants ce qui rend certaines modifications fastidieuses - la feuille de style s'applique à l'ensemble de la page, on ne peut pas l'utiliser de manière ciblée, par exemple pour styler un composant
Pour adresser ces problèmes, au lieu d'inclure la feuille de style par défaut de Bootstrap, on peut partir du code source de Bootstrap pour produire, à l'aide d'un préprocesseur, sa propre feuille de style personalisée. En effet, le code de Bootstrap n'est pas écrit en CSS directement : il est écrit dans un langage qui est une extension du langage CSS et que l'on convertit en CSS ordinaire à l'aide d'un préprocesseur.
La version stable actuelle de Bootstrap est écrite en Less et la version de développement est écrite en Sass. Comme il existe également un portage de la version stable en Sass, c'est ce langage que nous choisirons pour illustrer cet article, puisque c'est le futur de Bootstrap. Les approches présentées ici sont toutefois applicables aussi bien avec Less qu'avec Sass, moyennant de petites différences de syntaxe. Vous pouvez donc continuer la lecture de cet article même si vous avez l'intention d'utiliser Less.
Installer Sass
Historiquement la première implémentation de Sass a été développée avec le langage Ruby, mais depuis d'autres implémentations sont apparues grâce à la bibliothèque libsass. Comme tous les développeurs web ne sont pas forcément familiers avec l'écosystème Ruby mais que la plupart utilisent JavaScript, nous allons opter pour l'implémentation node-sass, un préprocesseur CSS disponible pour l'environement Node.js :
# npm install -g node-sass
On peut maintenant vérifier que le pré-processeur fonctionne en créant un fichier test.scss
:
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}
On exécute alors le pré-processeur comme ceci :
$ node-sass test.scss test.css
Rendering Complete, saving .css file...
Wrote CSS to /home/al/essai/sass/test.css
Et on obtient en résultat le fichier test.css
:
body {
font: 100% Helvetica, sans-serif;
color: #333; }
Lorsque vous développerez, vous mettrez en place un mécanisme pour détecter les changements de votre code Sass et générer le CSS automatiquement, sans intervention manuelle. Pour cela vous pourrez utiliser une fonctionnalité de votre IDE, de votre éditeur ou de votre système de build tel que Grunt ou Gulp. La configuration des éditeurs et des systèmes de build dépassant le cadre de cet article (voir nos autres articles concernant Gulp), nous nous contenterons ici de montrer des exemples d'exécution manuelle de Sass. Signalons toutefois l'existence de l'option --watch
de la commande node-sass
qui détecte les changements et recompile automatiquement :
$ node-sass --watch test.scss test.css
=> changed: /home/al/essai/sass.test.scss
Rendering Complete, saving .css file...
Wrote CSS to /home/al/essai/sass/test.css
Structurer le thème
Dans un CMS comme pour un site statique, il est une règle de base à respecter : les fichiers servant à la mise en forme doivent être séparés de ceux qui fournissent le contenu. L'arborescence de notre thème peut être la suivante :
.
├── bootstrap.css
├── bootstrap-sass/
├── css/
│ └── bootstrap-custom.css
├── fonts/
├── img/
├── index.html
├── js/
└── scss/
├── bootstrap -> ../bootstrap-sass/assets/stylesheets/bootstrap
├── _bootstrap-custom.scss
├── styles.scss
└── _variables-custom.scss
Nous vous montrons comment arriver à cette arborescence pas à pas dans la section suivante.
Personnaliser la feuille de style par défaut
Récupérons le code de bootstrap-sass, soit en faisant un git clone
soit en
téléchargeant une archive.
Les feuilles de styles Sass se trouvent dans le sous-répertoire assets/stylesheets/
.
Pour compiler Bootstrap depuis le code SCSS vers du code CSS, on peut donc procéder ainsi :
$ cd bootstrap-sass
$ node-sass assets/stylesheets/_bootstrap.scss bootstrap.css
Rendering Complete, saving .css file...
Wrote CSS to /home/al/articles/bootstrap-sass-example/bootstrap-sass/bootstrap.css
Le fichier CSS produit précédemment contient la totalité des styles définis par Bootstrap et n'est pas très léger :
$ du -sh bootstrap.css
148K bootstrap.css
Si notre projet n'utilise pas tous les styles de Bootstrap, ce fichier pourrait être plus léger. Le site de Bootstrap propose un outil de personalisation en ligne mais ce type d'outil graphique n'est pas forcément facile à intégrer avec des systèmes de build ou de gestion de versions. Pour différentes raisons on peut préférer une approche basée sur le code et la ligne de commande.
Si on regarde le contenu du fichier source _bootstrap.scss
, on
constate qu'il ne contient pas de style, mais qu'il s'agit d'une série
d'imports servant à inclure les styles définis de manière modulaire dans
des fichiers séparés (des partials selon la terminologie Sass).
Nous allons copier ce fichier dans notre projet et
faire un lien symbolique vers le code source de bootstrap.
$ mkdir scss css fonts img js
$ cd scss
$ cp /chemin/vers/bootstrap-sass/assets/stylesheets/_bootstrap.scss _bootstrap-custom.scss
$ ln -s /chemin/vers/bootstrap-sass/assets/stylesheets/bootstrap .
Nous avons à présent tout loisir d'éditer notre fichier
_bootstrap-custom.scss
pour supprimer les imports inutiles à notre
projet et obtenir une feuille de style plus légère. Par exemple nous pouvons
avoir un fichier _bootstrap-custom.scss
contenant seulement ceci :
// Core variables and mixins
@import "bootstrap/variables";
@import "bootstrap/mixins";
// Reset and dependencies
@import "bootstrap/normalize";
@import "bootstrap/print";
// Core CSS
@import "bootstrap/scaffolding";
@import "bootstrap/type";
@import "bootstrap/grid";
// Utility classes
@import "bootstrap/utilities";
@import "bootstrap/responsive-utilities";
Nous pouvons le compiler de la même manière que précédemment :
$ node-sass scss/_bootstrap-custom.scss css/bootstrap-custom.css
Rendering Complete, saving .css file...
Wrote CSS to /home/al/articles/bootstrap-sass-example/css/bootstrap-custom.css
$ du -sh bootstrap-custom.css
40K bootstrap-custom.css
C'est ce fichier bootstrap-custom.css
que nous allons utiliser par
la suite comme base de notre propre feuille de style.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Votre page avec Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="css/bootstrap-custom.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="starter-template">
<h1>Votre page avec Bootstrap</h1>
<p class="lead">Cette page dérive du
<a href="http://getbootstrap.com/examples/starter-template/">modèle de départ de Bootstrap</a>.</p>
</div>
</div><!-- /.container -->
</body>
</html>
Modifier les variables par défaut
Un autre intérêt de cette façon de procéder est la possibilité de modifier les variables par défaut de Bootstrap, par exemple la couleur du texte ou des titres, l'habillage de la navigation, etc.
Toutes ces variables sont dans le fichier _variables.scss
que nous allons copier dans le dossier scss
pour le surcharger. Pour faciliter une mise à jour ultérieure de Bootstrap il est préférable d'éviter de modifier directement les fichiers pour ne pas perdre ces modifications.
$ cp /chemin/vers/bootstrap-sass/assets/stylesheets/_variables.scss _variables-custom.scss
Et _bootstrap-custom.scss
importe ce fichier :
// Core variables and mixins
@import "variables-custom";
Modifiez par exemple la couleur de fond de la page, et regénérez le fichier bootstrap-custom.css
$body-bg: $gray-lighter;
Ajouter nos styles
Dans un fichier style.scss
, nous ajoutons les styles pour notre thème.
// Import de notre Bootstrap allegé
@import "bootstrap-custom"
// Ajoutons notre style
h2 {
background: url('../img/bee-orange-alveole.png') no-repeat top left;
padding: 30px 0;
padding-left: 64px;
}
on peut le compiler comme ceci :
$ node-sass scss/style.scss css/style.css
En référençant depuis notre code HTML ce fichier css/style.css
plutôt que
le CSS par défaut de Bootstrap, on obtient le résultat attendu mais avec un
code mieux structuré. Nous pouvons même aller plus loin dans la structuration du code.
Découpage en composants
Utiliser un préprocesseur donne la possibilité de découper l'intégration en
plusieurs fichiers correspondant à des composants du thème, et de les réunir tous dans styles.scss
:
// Mixins de bootstrap
@import "bootstrap/mixins";
// Theme specific : layout
@import 'content';
@import 'header';
@import 'footer';
@import 'sidebar';
// Objects : types de contenus, composants
@import 'objects/events';
@import 'objects/breadcrumb';
@import 'objects/forms';
@import 'objects/navigation';
@import 'objects/news';
@import 'objects/search';
@import 'objects/slideshow';
// ... (un fichier par type de contenu)
L'avantage principal est la maintenance de votre thème.
Terminés les ctrl + F
dans votre éditeur de code, le composant sur lequel vous travaillez est localisé dans un fichier dédié.
Utiliser les styles Bootstrap avec nos propres classes
La feuille de style pré-construite fournie par Bootstrap propose un grand nombre de classes CSS que nous pouvons utiliser directement dans notre code HTML. Mais procéder ainsi présente plusieurs inconvénients :
- notre code HTML se retrouve lié aux conventions de nommage de Bootstrap
- les attributs
class
de nos éléments contiennent de nombreuses classes - les nom de classes utilisés sont souvent liés à la présentation plutôt qu'à la structure, ils ne sont pas sémantique
Voici un exemple typique de code HTML souffrant de ces problèmes :
<style>
.row div:nth-child(1) {
background: lightpink;
}
.row div:nth-child(2) {
background: lightyellow;
}
.row div:nth-child(3) {
background: lightgreen;
}
.row div:nth-child(4) {
background: lightblue;
}
</style>
<div class="container">
<!-- Example row of columns -->
<div class="row">
<div class="col-sm-6 col-md-4 col-lg-3">
<h2>Titre 1</h2>
<p>col-sm-6 col-md-4 col-lg-3</p>
</div>
<div class="col-sm-6 col-md-4 col-lg-3">
<h2>Titre 2</h2>
<p>col-sm-6 col-md-4 col-lg-3</p>
</div>
<div class="col-sm-6 col-md-4 col-lg-3">
<h2>Titre 3</h2>
<p>col-sm-6 col-md-4 col-lg-3</p>
</div>
<div class="col-sm-6 col-md-12 col-lg-3">
<h2>Titre 4</h2>
<p>col-sm-6 col-md-12 col-lg-3</p>
</div>
</div>
</div>
Avec ce code qui adopte une approche mobile first, sur de très petits écrans chaque bloc va prendre toute la largeur de l'espace :
bootstrap-preprocesseur-images/rendu-sur-tres-petits-ecrans/image
Sur des petits écrans, chaque bloc occupe la moitié de la largeur du conteneur :
bootstrap-preprocesseur-images/rendu-sur-tres-petits-ecrans/image
Sur des écrans moyens, les trois premiers blocs sont sur la même ligne et le quatrième occupe toute la largeur sur sa propre ligne :
bootstrap-preprocesseur-images/rendu-sur-tres-petits-ecrans/image
Enfin, sur de grands écrans, tous les blocs sont sur la même ligne, occupant chacun un quart de l'espace :
bootstrap-preprocesseur-images/rendu-sur-tres-petits-ecrans/image
On le voit, même si ce code donne le résultat attendu, il n'est pas très lisible, il contient des répétitions et il est potentiellement difficile à maintenir.
À la place, il peut être préférable d'avoir un code qui ressemble à ceci :
<div class="container">
<!-- Example row of columns -->
<div class="row">
<div class="block-slogan">
<h2>Titre 1</h2>
<p>...</p>
</div>
<div class="block-action">
<h2>Titre 2</h2>
<p>...</p>
</div>
<div class="block-contact">
<h2>Titre 3</h2>
<p>...</p>
</div>
<div class="block-testimonials">
<h2>Titre 4</h2>
<p>...</p>
</div>
</div>
</div>
Pour que ce code HTML fonctionne, on écrit dans le fichier styles.scss
que nous avons créé à la section précédente :
// Import de notre Bootstrap allegé
@import "bootstrap-custom";
.row {
div:nth-child(1) {background: lightpink;}
div:nth-child(2) {background: lightyellow;}
div:nth-child(3) {background: lightgreen;}
}
.block-slogan, .block-action, .block-contact {
// Invocation des mixins du système de grille
@include make-sm-column(6);
@include make-md-column(4);
@include make-lg-column(3);
}
.block-testimonials {
// Invocation des mixins du système de grille
@include make-sm-column(6);
@include make-md-column(12);
@include make-lg-column(3);
background: lightblue;
}
Dans ce code, on appelle les mixins définis par le système de grille de Bootstrap. Ces mixins vont générer le code CSS faisant de nos blocs des colonnes de grille.
Appliquer Bootstrap à une partie de la page
En utilisant un préprocesseur, il est également possible de limiter l'impact de Bootstrap à une partie de la page. Cela peut-être utile si on crée un composant ou un widget ayant vocation à être utilisé dans des pages qui n'utilisent pas Bootstrap.
Considérons ce code HTML :
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
<div class="container">
<h1>Le titre</h1>
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. </p>
<button class="btn btn-primary">Bouton bootstrap</button>
</div>
</body>
</html>
Ce code va donner le résultat suivant :
bootstrap-preprocesseur-images/rendu-sur-tres-petits-ecrans/image
On voit que les styles par défaut de Bootstrap sont appliqués aussi bien au
texte du paragraphe qu'au bouton. Imaginons à présent que nous souhaitions
appliquer Bootstrap uniquement au bouton et conserver le texte dans le style
par défaut du navigateur. On emballe le bouton dans un div
avec un attribut
class
de notre choix qui va délimiter la portée de notre composant :
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link rel="stylesheet" href="css/button.css">
</head>
<body>
<div class="container">
<h1>Le titre</h1>
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. </p>
<div class="my-fabulous-widget">
<button class="btn btn-primary">Bouton bootstrap</button>
</div>
</div>
</body>
</html>
Pour que Bootstrap ne s'applique qu'au contenu de .my-fabulous-widget
, on crée un fichier Sass comme celui-ci :
.my-fabulous-widget {
@import "bootstrap";
// Reprise des styles définis pour "html" et "body" dans
// dans _normalize.scss
// Auparavant dans "html {"
// font-family: sans-serif; // Surchargé plus bas
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
// Auparavant dans "body {"
margin: 0;
// Reprise des styles définis pour "html" et "body" dans
// _scaffolding.scss
// Auparavant dans "html {"
// font-size: 10px; // Surchargé plus bas
-webkit-tap-highlight-color: rgba(0,0,0,0);
// Auparavant dans "body {"
font-family: $font-family-base;
font-size: $font-size-base;
line-height: $line-height-base;
color: $text-color;
background-color: $body-bg;
}
Dans le CSS généré à partir de ce code, tous les styles de Bootstrap se
retrouvent précédés du sélecteur de classe .my-fabulous-widget
. On est
simplement obligés de reprendre à la main quelques propriétés que Bootstrap
applique aux éléments html
et body
afin les appliquer à la classe de
notre composant. On constate alors que les styles de Bootstrap s'appliquent
uniquement au contenu du div
ciblé. Le texte se voit appliquer le style par
défaut du navigateur :
bootstrap-preprocesseur-images/rendu-sur-tres-petits-ecrans/image
Conclusion
Les avantages d'un préprocesseur tel que Sass avec le framework Bootstrap sont multiples : adapter Bootstrap à notre thème, utiliser les "mixins" disponibles de Bootstrap, améliorer la maintenabilité du code à l'aide d'une arborescence par composants. Cet article pour bien commencer avec Bootstrap et Sass n'est que le point de départ vers toutes les possibilités offertes par ces deux outils.
Formations associées
Formations Front end
Formation Développement d'applications JavaScript
À distance (FOAD) Du 20 au 22 novembre 2024
Voir la formationActualités en lien
Générer un fichier PMTiles avec Tippecanoe
Exemple de génération et d’affichage d’un jeu de tuiles vectorielles en PMTiles à partir de données publiques.
Publier une documentation VitePress sur Read The Docs
À l'origine, le site de documentation Read The Docs n'acceptait que les documentations Sphinx ou MKDocs. Depuis peu, le site laisse les mains libres pour builder sa documentation avec l'outil de son choix. Voici un exemple avec VitePress.
Créer une application en tant que composant web avec Stencil
Mise en place dans le cadre de Geotrek, cette solution permet de se passer d'une iFrame pour afficher une application dans n'importe quel site.