Responsive Design avec Bootstrap 3

Présentation

Site mobiles ?

Quelques stats de 2014 :

Il est donc important de proposer aux internautes une expérience optimale sur un site internet adapté aux mobiles.

responsive design quésaco ?

Content is like a water

Le terme responsive web design (RWD) - ou site web adaptatif - est une solution pour créer un seul site site web qui s'adapte à la taille de l'écran des différents supports d'affichages (Smartphone, tablette, TV, ordinateur) pour proposer une navigation confortable sur chaque support.

note: D'autres solutions existent comme la création d'un site dédié aux mobiles séparé du site normal, mais cette solution est réputée moins "agile" car il faut ensuite maintenir 2 sites à jour et cela ne couvre pas la problématique des tablettes et grands smartphones.

CSS3 Media Queries

Le développement repose sur l'utilisation de la technologie CSS3 media queries, une extension de la règle @media pour adapter la mise en page à l'environnement de consultation grâce à une grille fluide dans laquelle se casent les différents contenus de la page.

Exemple d'une règle CSS @media :

    /* css */

    .text {
        font-size: 14px;
    }
    /* affiche le texte en corps 16px lorsque le média dispose d'une largeur d'affichage au minimum de 780px */
    @media (min-width: 780px) {
      .text {
        font-size: 16px;
      }
    }

    /* scss / less */

    .text {
        /* affiche le texte en corps 14px */
        font-size: 14px;

        /* affiche le texte en corps 16px lorsque le média dispose d'une largeur d'affichage au minimum de 780px */
        @media (min-width: 780px) {
            font-size: 16px;
        }
    }

Quelques bases à connaître

Sur mobile, pour une question de compatibilité avec les anciens site non-responsive, le zoom est activé par défaut, il faut donc spécifier manuellement le viewport :

    <!-- le minimum syndical -->
    <meta name="viewport" content="width=device-width" />

    <!-- ce que j'utilise -->
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, user-scalable=no">

Tour d’horizon de Bootstrap 3.0

Bootstrap c'est quoi ?

Bootstrap (de Twitter) est un framework css/html qui facilite la création d'un site web en responsive design. Il est composé de code HTML formalisé, de code Javascript et d'une CSS. Il permet de coder dans un standard et facilite la réutilisation du code.
De plus Bootstrap propose des helper-class pour faciliter la création de sites adaptés aux mobiles et tablettes.

Télécharger et installer bootstrap

rendez-vous sur http://getbootstrap.com/getting-started/ pour choisir une option de déploiement.

Voici la base (CDN) :

    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">

    <!-- Optional theme -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">

    <!-- Latest compiled and minified JavaScript -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>

À placer comme ceci dans un fichier HTML comme celui de base proposé :

<!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">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
    <!-- Optional theme -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <h1>Hello, world!</h1>

    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
  </body>
</html>

Afficher la démo

Mise en place d’une navigation responsive

Dans le document créé ajouter ce code à l'intérieur de la balise body pour obtenir une navbar standard:

    <nav class="navbar navbar-default navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Project name</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
            <li class="active"><a href="#">Home</a></li>
            <li><a href="#about">About</a></li>
            <li><a href="#contact">Contact</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </nav>

Il est possible d'avoir une variation en remplaçant la class navbar-default par navbar-inverse, et de varier la position :

Lorsqu'on utilise une navbar-fixed-* il est important de noter qu'il faut ajouter une marge au body pour éviter le recouvrement du contenu par la barre de navigation.

    body {
        margin-top: 50px;
        /*uniquement dans le cas d'une navbar-fixed-bottom */
        /* margin-bottom: 50px; */ 
    }

Afficher la démo

Le responsive grid : bien contrôler ses colonages en fonction des supports

Illustration

Voyons maintenant les bases de la mise en page : deux systèmes de grille de mise en page à notre disposition:

    <div class="container-fluid">
      <div class="row">
        ...
      </div>
    </div>
    <div class="container">
      <div class="row">
        ...
      </div>
    </div>

Dans ces conteneurs, nous devons utiliser des lignes (.row) pour pouvoir ajouter ensuite des colonnes (.col-sm-*).

Le system de colonnage de Bootstrap est très bien étudié, la grille de base est de 12 colonnes divisible en unités, préfixé d'un identifiant de largeur géré avec des breakpoints définis par des media-queries :

    /* Small devices (tablets, 768px and up) */
    @media (min-width: @screen-sm-min) { }
    /* Medium devices (desktops, 992px and up) */
    @media (min-width: @screen-md-min) { }
    /* Large devices (large desktops, 1200px and up) */
    @media (min-width: @screen-lg-min) { }

Donc pour obtenir deux colonnes, je dois faire un calcul simple : 12/2 = 6, j'aurai donc 2 colonnes de classe 6, je décide que le breakpoint de ces colonnes sera les small devices (sm), mes colonnes ressembleront donc à ce code :

    <div class="col-sm-6">contenu colonne 1</div>
    <div class="col-sm-6">contenu colonne 2</div>

Il faut bien entendu placé de code dans le conteneur et la ligne :

    <div class="container">
      <div class="row">
        <div class="col-sm-6">contenu colonne 1</div>
        <div class="col-sm-6">contenu colonne 2</div>
      </div>
    </div>

On peut également assigner plusieurs class de colonnage pour gérer des colonnages différents à chaque breakpoints :

<!-- Stack the columns on mobile by making one full-width and the other half-width -->
<div class="row">
  <div class="col-xs-12 col-md-8">.col-xs-12 .col-md-8</div>
  <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
</div>

<!-- Columns start at 50% wide on mobile and bump up to 33.3% wide on desktop -->
<div class="row">
  <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
  <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
  <div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
</div>

<!-- Columns are always 50% wide, on mobile and desktop -->
<div class="row">
  <div class="col-xs-6">.col-xs-6</div>
  <div class="col-xs-6">.col-xs-6</div>
</div>

Il est aussi possible d'utiliser des offset pour décaler des colonnes avec des marges :

    <div class="row">
      <div class="col-md-4">.col-md-4</div>
      <div class="col-md-4 col-md-offset-4">.col-md-4 .col-md-offset-4</div>
    </div>
    <div class="row">
      <div class="col-md-3 col-md-offset-3">.col-md-3 .col-md-offset-3</div>
      <div class="col-md-3 col-md-offset-3">.col-md-3 .col-md-offset-3</div>
    </div>
    <div class="row">
      <div class="col-md-6 col-md-offset-3">.col-md-6 .col-md-offset-3</div>
    </div>

Les colonnes sont imbriquables :

<div class="row">
  <div class="col-sm-9">
    Level 1: .col-sm-9
    <div class="row">
      <div class="col-xs-8 col-sm-6">
        Level 2: .col-xs-8 .col-sm-6
      </div>
      <div class="col-xs-4 col-sm-6">
        Level 2: .col-xs-4 .col-sm-6
      </div>
    </div>
  </div>
</div>

Afficher la démo

En utilisant la version Less ou Sass, il est également possible de créer facilement des colonnes personnalisées.

  //less

  .wrapper {
    .make-row();
  }
  .content-main {
    .make-lg-column(8);
  }
  .content-secondary {
    .make-lg-column(3);
    .make-lg-column-offset(1);
  }
<div class="wrapper">
    <div class="content-main">...</div>
    <div class="content-secondary">...</div>
  </div>

BONUS

Astuce pour créer 5 colonnes

  /* bootstrap 5 cols
  // ----------------- */
  .col-xs-5ths,
  .col-sm-5ths,
  .col-md-5ths,
  .col-lg-5ths {
    position: relative;
    min-height: 1px;
    padding-right: 10px;
    padding-left: 10px;
  }

  .col-xs-5ths {
    width: 20%;
    float: left;
  }

  @media (min-width: 768px) {
    .col-sm-5ths {
      width: 20%;
      float: left;
    }
  }

  @media (min-width: 992px) {
    .col-md-5ths {
      width: 20%;
      float: left;
    }
  }

  @media (min-width: 1200px) {
    .col-lg-5ths {
      width: 20%;
      float: left;
    }
  }

Les différents composants de Bootstrap

Illustration

Bootstrap va plus loin que de proposer une feuille de style responsive, nous avons à notre disposition tout un framework de composants HTML/CSS pour créer des mise en pages :

Et des composants qui font appel au javascript :

Tous ces composants sont explicitement documenté sur le site http://www.getbootstrap.com

Afficher la démo

Le cas particulier des tableaux

Il arrive que les tableaux contiennent beaucoup de données, la nature même d'un tableau ne permet pas de varier les colonnes comme avec les balises div.
Toutefois, l'emploi d'un div englobant avec la class .table-responsive permet de palier au problème, en ajoutant une scrollbar horizontale sur tableaux affichés sur les plus petits écrans (moins de 768px) :

<div class="table-responsive">
  <table class="table">
    ...
  </table>
</div>

Afficher la démo

Cependant dans certains cas cette solution ne suffit pas.

Illustration

Mais il existe des solutions :

Les helpers class de Bootstrap

Le but de ce tutorial n'est pas de refaire la doc de Bootstrap, mais de parcourir les éléments essentiels qui peuvent rapidement aider un intégrateur à faire une mise en page responsive.
Les helper-class sont des classes essentielles pour aider à la mise en page.

    <p class="sr-only">Visible uniquement pour les lecteurs d'écran.</p>
    <p class="lead">Paragraphe d'introduction.</p>
    <p class="text-left">Aligné à gauche</p>
    <p class="text-center">Aligné au centre</p>
    <p class="text-right">Aligné à droite</p>
    <p class="text-justify">Justifié : Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla id diam felis. Duis ac viverra erat. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
    <p class="text-nowrap">Sans saut de ligne (nowrap)</p>
    <p class="text-lowercase">Lowercased text.</p>
    <p class="text-uppercase">Uppercased text.</p>
    <p class="text-capitalize">Capitalized text.</p>
    <ul class="list-unstyled">
      <li>element 1</li>
      <li>element 2</li>
    </ul>
    <ul class="list-inline">
      <li>element 1</li>
      <li>element 2</li>
    </ul>
    <ul class="list-inline list-unstyled">
      <li>element 1</li>
      <li>element 2</li>
    </ul>
    <p class="text-muted">texte exemple</p>
    <p class="text-primary">texte couleur primaire</p>
    <p class="text-success">texte couleur success</p>
    <p class="text-info">texte couleur info</p>
    <p class="text-warning">texte couleur warning</p>
    <p class="text-danger">texte couleur danger</p>
    <p class="bg-primary">...</p>
    <p class="bg-success">...</p>
    <p class="bg-info">...</p>
    <p class="bg-warning">...</p>
    <p class="bg-danger">...</p>
    <div class="pull-left">...</div>
    <div class="pull-right">...</div>
    <div class="center-block">...</div>
    <div class="clearfix">...</div>
    <div class="show">...</div>
    <div class="hidden">...</div>
    <h1 class="text-hide">text-hide pour styler une image de remplacement</h1>

Les classes de visibilité :

    /* Visible en fonction du breakpoint */
    .visible-xs-*
    .visible-sm-*
    .visible-md-*
    .visible-lg-*

    /* Chaché en fonction du breakpoint */
    .hidden-xs-*
    .hidden-sm-*
    .hidden-md-*
    .hidden-lg-*

    /* Choisir le style de rendu visible : */
    .visible-*-block /* display: block; */
    .visible-*-inline /* display: inline; */
    .visible-*-inline-block /* display: inline-block; */

Afficher la démo

Personnaliser les styles

Bootstrap existe aussi en version LESS et SASS. Pour plus de souplesse d'utilisation dans vos projets je vous recommande d'utiliser ce type d'intégration.
Bootstrap fourni un grand nombre de variables personnalisables. Elle permetten une personnalisation rapide du thème, sans avoir à aller chercher trop loin dans le code de Bootstrap.

Cela permet de personnaliser très rapidement tous les composants de bootstrap et d'utiliser les mixins fournis.

Quelques exemples de styles pré-existants touvés sur http://bootswatch.com :

Illustration

Créer des règles CSS en MFRD (Mobile First Responsive Design)

Lors de la création des règles CSS, une erreur commune est de vouloir commencer à styler pour les écrans larges en premier. C'est sans doute du fait que nous réalisons l'intégration sur un écran d'ordinateur : il nous parraît logique de commencer ainsi.
Le fait est que le code CSS engendré est souvent beaucoup plus verbeux et difficile à relire avec cette méthode.
Le design MFRD (Mobile First Responsive Design) utilisé par Bootstrap, propose quant à lui de commencer à coder ses CSS en commençant par le plus petit dénominateur commun, à savoir le mobile.

Exemple de CSS Wide Screen First Responsive Design (ce qu'il ne faut pas faire!) :

    .logo {
        float: left;
        margin: 10px 20px;
        width: 600px;
        height: auto;

        @media (max-width: $screen-md-min) {
            width: 400px;
        }

        @media (max-width: $screen-sm-min) {
            width: 300px;
            float: none;
            margin: 5px 10px;
        }

        @media (max-width: $screen-xs-min) {
            width: 200px;
            float: none;
            margin: 5px 10px;
        }

        @media (max-width: $screen-lg-min) {
            width: 600px;
        }
    }

Version Mobile First Responsive Design :

    //less

    .logo {
        margin: 5px 10px;
        width: 200px;
        height: auto;

        @media (max-width: @screen-sm-min) {
            width: 300px;
        }

        @media (max-width: @screen-md-min) {
            width: 400px;
            float: left;
            margin: 10px 20px;
        }

        @media (max-width: @screen-lg-min) {
            width: 600px;
        }
    }

Cette méthode parraît peut de chose, mais croyez-moi, sur de gros projets, elle vous fait gagner en clarté et en ligne de code!

Images Retina, media queries et SRCSET

video

Le Responsive Design, c'est aussi d'adapter les images aux nouvelles résolutions d'écrans HiDPI et Retina. Il est donc important de prendre en compte les formats d'images adaptés.

dans la css :

    .logo {
        background-image: url(/images/logo.png); /* size 80x40px */
    }
    @media only screen and (-webkit-min-device-pixel-ratio:2),
    only screen and (min--moz-device-pixel-ratio:2),
    only screen and (-o-min-device-pixel-ratio:2 / 1),
    only screen and (min-device-pixel-ratio:2),
    only screen and (min-resolution:192dpi),
    only screen and (min-resolution:2dppx) {
        .logo {
            background-image: url(/images/logo@2x.png);
            background-size: 80px 40px;
        }
    }

Mixin scss :

    //scss

    @mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) {
        background-image: image-url("#{$file-1x}");

        @media
        only screen and (-webkit-min-device-pixel-ratio: 2),
        only screen and (   min--moz-device-pixel-ratio: 2),
        only screen and (     -o-min-device-pixel-ratio: 2/1),
        only screen and (        min-device-pixel-ratio: 2),
        only screen and (                min-resolution: 192dpi),
        only screen and (                min-resolution: 2dppx) {
            background-image: image-url("#{$file-2x}");
            background-size: $width-1x $height-1x;
      }
    }

    //usage
    .logo {
        @include img-retina('logo.png', 'logo@2x.png', 80px, 40px);
    }

Cette méthode est avantageuse, mais attention au poid des images en plus ! car le navigateur va charger toutes les images présentes dans la CSS.
Il est donc recommandé des formats d'images scalables, en svg ou d'utiliser lorsque c'est possible l'emploi d'icônes typographiques.

Dans un document HTML, il est également possible de définir différent sets de tailles d'images qui seront utilisés sur les navigateurs supportant la déclaration (les plus récentes versions le supportement):

    <!-- SRCSET Method -->
    <img src="mon-image.jpg"
     srcset="mon-image.jpg 1x,
             mon-image-320.jpg 320w 1x,
             mon-image-640.jpg 320w 2x"
     width="850" height="475" alt="">

La syntaxe de la valeur d'attribut est la suivante :

<adresse-de-l-image> [critère( critère)](, <adresse-de-l-image> [critère( critère)])

Questions diverses et ressources

Quelques ressource externes

Quelques questions souvent posées :

questions