Makina Blog

Le blog Makina-corpus

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

Toulouse Du 18 au 20 juin 2024

Voir la formation

Actualités en lien

Image
Capture d'une partie de carte montrant un réseau de voies sur un fond de carte sombre. Au centre, une popup affiche les information de l'un des tronçons du réseau.
28/02/2024

Géné­rer un fichier PMTiles avec Tippe­ca­noe

Exemple de géné­ra­tion et d’af­fi­chage d’un jeu de tuiles vecto­rielles en PMTiles à partir de données publiques.

Voir l'article
Image
Read The Docs
01/02/2024

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.

Voir l'article
Image
Widget
04/04/2023

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.

Voir l'article

Inscription à la newsletter

Nous vous avons convaincus