Et si on sortait de l’utilisation surannée de Bootstrap pour regarder un peu ce qu’il se fait en 2021 ? Cette article s’adresse aux personnes ayant quelques bases avec CSS. Il se termine par la présentation de Tailwindcss.
Nous allons discuter de quelques techniques pour mettre en place des feuilles de styles sur une structure d’exemple. Vous verrez d’abord les techniques de bases, puis une discussion et enfin une présentation de différents frameworks à connaître, dès lors que l’on souhaite construire une application ou un site Web.
Pour notre exemple, nous prendrons un extrait de code destiné à afficher une photo et la description d’un hôtel.
<div>
<img src="https://picsum.photos/id/128/400/300" alt="Image from https://picsum.photos/"/>
<div>
<h1>Hotel Balamba <span>*****</span></h1>
<p>
Logé dans le vieux quartier de Scalito, l'hôtel <cite>Balamba</cite> propose un cadre charmant, avec 14 chambres et 2 suites.
Le bâtiment Monad a été construit à la fin du XIX<sup>ème</sup> siècle.
</p>
<p>Les visiteurs :
<q>J'ai adoré ce petit séjour de 3 nuits dans cet écrin de verdure</q>
<q>Plus qu'un voyage, c'est une plongée dans l'univers de l'Italie et de la programmation fonctionnelle.</q>
</p>
<p>Plus d'informations : <a href="#">Voir les disponibilités</a></p>
</div>
</div>
Première approche
Dans un premier temps, sans toucher à la structure de la page HTML, nous allons simplement décrire quelques éléments de la page. Dans un deuxième temps, nous définirons quelques balises CSS. L’idée de départ, qui semble simple, est de décrire uniquement quelques conteneurs, en prenant soin de bien séparer la structure (html) et la mise en page (css).
C’est parti : on débute par l’ajout de 2 classes : « hotel-description » et « hotel-content » dans notre page HTML :
<div class="hotel-description"> <!-- ajout ici //-->
<img src="https://picsum.photos/id/128/400/300" alt="Image from https://picsum.photos/"/>
<div class="hotel-content"> <!-- ajout ici //-->
<h1>Hotel Balamba <span>*****</span></h1>
<p>
Logé dans le vieux quartier de Scalito, l'hôtel <cite>Balamba</cite> propose un cadre charmant, avec 14 chambres et 2 suites.
Le bâtiment Monad a été construit à la fin du XIX<sup>ème</sup> siècle.
</p>
<p>Les visiteurs :
<q>J'ai adoré ce petit séjour de 3 nuits dans cet écrin de verdure</q>
<q>Plus qu'un voyage, c'est une plongée dans l'univers de l'Italie et de la programmation
fonctionnelle.</q>
</p>
<p>Plus d'informations : <a href="#">Voir les disponibilités</a></p>
</div>
</div>
Et le CSS associé va venir en surplus sans toucher la structure de la page :
.hotel-description {
background-color: white;
border-bottom: 1px solid rgb(0,20,20);
overflow: hidden;
padding: 5px 8px;
display: flex;
flex-direction: row;
}
.hotel-description img {
border-radius: 8px;
text-align: left;
order: 1;
}
.hotel-description div {
padding: 1rem;
order: 2;
}
.hotel-content > h1 {
font-size: 1.25rem;
color: rgba(138, 22, 10, 0.8);
}
.hotel-content > p {
font-size: 1rem;
color: rgba(0, 0, 0, 0.75);
line-height: 1.5;
}
.hotel-content > p > q {
font-style: italic ;
color: darkgreen;
display: block;
}
Visuellement le résultat :
Critique de cette première approche : le code CSS est très dépendant de la structure de la page HTML. Dès que vous modifierez la structure HTML, il faudra reprendre le CSS. Bien que cela soit l’approche la plus simple, ce n’est pas la plus efficace. N’importe quelle modification dans la structure va rendre le style caduque. Et si vous commencez à déclarer des styles trop génériques, votre page deviendra fragile, les styles se mélangeront, ce qui donnera un travail de mauvaise qualité.
Nous allons essayer une deuxième approche
Deuxième approche : BEM (Block Element & Modifier)
Nous allons voir une autre façon d’utiliser CSS en se basant sur l’approche B.E.M (Block Element & Modifier). Un bloc ce sera un élément de la page, comme l’entête. Un élément sera un sous-ensemble d’un bloc, et ne pourra pas exister sans le bloc. Par exemple le logo du Touilleur Express ici dans le header, est un élément. Enfin les modifiers seront utilisés pour proposer quelques versions alternatives à des Elements. Par exemple « large » ou « primary » pour un bouton.
Tout d’abord le code HTML. Le principe est d’utiliser une class de départ, ici <strong>hotel</strong>
, puis ensuite de postfixer chaque élément avec son type. Ainsi notre balise H1
sera accompagnée du style hotel_title
.
<div class="hotel">
<img class="hotel__logo" src="https://picsum.photos/id/128/400/300" alt="Image from https://picsum.photos/"/>
<div class="hotel__content">
<h1 class="hotel__title">Hotel Balamba <span>*****</span></h1>
<p class="hotel__desc">
Logé dans le vieux quartier de Scalito, l'hôtel <cite>Balamba</cite> propose un cadre charmant, avec 14
chambres et 2 suites.
Le bâtiment Monad a été construit à la fin du XIX<sup>ème</sup> siècle.
</p>
<p class="hotel__desc">Les visiteurs :
<q class="hotel__quote">J'ai adoré ce petit séjour de 3 nuits dans cet écrin de verdure</q>
<q class="hotel__quote">Plus qu'un voyage, c'est une plongée dans l'univers de l'Italie et de la programmation
fonctionnelle.</q>
</p>
<p class="hotel__desc">Plus d'informations : <a class="hotel__action" href="#">Voir les disponibilités</a></p>
</div>
</div>
L’intérêt est plus tangible lorsque l’on regarde la feuille de style CSS associée :
.hotel {
background-color: white;
border-bottom: 1px solid rgb(0,20,20);
overflow: hidden;
padding: 5px 8px;
display: flex;
flex-direction: row;
}
.hotel__logo {
border-radius: 8px;
text-align: left;
order: 1;
}
.hotel__content {
padding: 1rem;
order: 2;
}
.hotel__title {
font-size: 1.25rem;
color: rgba(138, 22, 10, 0.8);
}
.hotel__desc {
font-size: 1rem;
color: rgba(0, 0, 0, 0.75);
line-height: 1.5;
}
.hotel__quote{
font-style: italic ;
color: darkgreen;
display: block;
}
L’intérêt étant que le code CSS ne reprend pas les sélecteurs HTML. Le style n’est plus dépendant de la structure HTML. Vous pouvez déplacer votre bloc de titre ou revoir la mise en page sans devoir tout ré-écrire. Cela semble une bonne solution, et déjà, si vous utilisez cette approche, votre code sera plus propre.
L’approche BEM entraîne la création de styles très spécifiques en CSS ce qui évite les suprises et la collision de styles avec d’autres feuilles. Un avantage aussi : tout élément ou tout groupe d’élément peut être sélectionné facilement par sa classe unique, sans passer par de l’imbrication de sélecteur. Par contre un inconvénient, comme on le voit ci-dessus, c’est que le code HTML sera moins lisible, et plus chargé.
On va aussi se heurter à une légère limitation dès lors que l’on souhaitera ré-utiliser des blocs similaires. Disons que la décoration de mon titre me plaît bien, et que je souhaite reprendre le style hotel__title
pour une autre partie du site consacré aux restaurants. Est-ce que je vais doubler la déclaration ?
.hotel__title, .restaurant__title {
font-size: 1.25rem;
color: rgba(138, 22, 10, 0.8);
}
Si les classes CSS sont trop liées à vos objets HTML, vous vous heurtez rapidement à la ré-utilisabilité des classes. Disons-le autrement : vous allez devoir maintenir un gros paquet de classes. Certes, un préprocesseur Saas sera utile, mais cela n’empechera pas que vous devrez répeter souvent les mêmes styles dans différents blocs.
Approche 3 : BEM + Semantic
Si je commence à vouloir décrire un restaurant comme un hôtel, j’ai tout intérêt à revoir la sémantique de ma feuille de style. Plutôt que d’utiliser la classe hotel, je peux m’inspirer de ce que fait Bootstrap avec le composant « card« . Après tout, si ma fiche Hotel et ma fiche Restaurant doivent avoir le même aspect, cela semble plus logique.
Reprenons le code HTML et utilisons cette fois-ci une nouvelle class card :
<div class="card">
<img class="card__logo" src="https://picsum.photos/id/128/400/300" alt="Image from https://picsum.photos/"/>
<div class="card__content">
<h1 class="card__title">Hotel Balamba <span>*****</span></h1>
<p class="card__desc">
Logé dans le vieux quartier de Scalito, l'hôtel <cite>Balamba</cite> propose un cadre charmant, avec 14
chambres et 2 suites.
Le bâtiment Monad a été construit à la fin du XIX<sup>ème</sup> siècle.
</p>
<p class="card__desc">Les visiteurs :
<q class="card__quote">J'ai adoré ce petit séjour de 3 nuits dans cet écrin de verdure</q>
<q class="card__quote">Plus qu'un voyage, c'est une plongée dans l'univers de l'Italie et de la programmation
fonctionnelle.</q>
</p>
<p class="card__desc">Plus d'informations : <a class="card__action" href="#">Voir les disponibilités</a></p>
</div>
</div>
<div class="card">
<img class="card__logo" src="https://picsum.photos/id/139/400/300" alt="Image from https://picsum.photos/"/>
<div class="card__content">
<h1 class="card__title">Restaurant Java <span>***</span></h1>
<p class="card__desc">
Découvrez l'injection de dépendance dans votre risotto avec cette très belle table,
agréablement placé à la sortie du village de Springville.
</p>
<p class="card__desc">Les visiteurs :
<q class="card__quote">Le Chef mérite 3 étoiles pour son soufflé de Scalafiste</q>
<q class="card__quote">Une larme d'émotion en goutant au célebre Tiramisu de Jakarta et au chocolat Quarkus
fonctionnelle.</q>
</p>
<p class="card__desc">Plus d'informations : <a class="card__action" href="#">Voir les disponibilités</a></p>
</div>
</div>
La feuille de CSS devient alors un peu plus générique, la notion d’hôtel a disparu au profit de la description d’une card :
.card {
background-color: white;
border-bottom: 1px solid rgb(0,20,20);
overflow: hidden;
padding: 5px 8px;
display: flex;
flex-direction: row;
}
.card__logo {
border-radius: 8px;
text-align: left;
order: 1;
}
.card__content {
padding: 1rem;
order: 2;
}
.card__title, .restaurant__title {
font-size: 1.25rem;
color: rgba(138, 22, 10, 0.8);
}
.card__desc {
font-size: 1rem;
color: rgba(0, 0, 0, 0.75);
line-height: 1.5;
}
.card__quote{
font-style: italic ;
color: darkgreen;
display: block;
}
Le rendu visuel :
L’approche Twitter Bootstrap
Depuis le début, nous voyons que nous essayons de séparer le code HTML de la partie CSS. Il y a plusieurs approches : soit une structure avec très peu de class CSS mais une dépendance forte sur la structure de la page (solution 1). Soit une approche très descriptive, qui surcharge le code HTML mais permet d’isoler les styles. Soit enfin un mix des deux, qui finalement essaye de décrire des types de composants (card, header, media, bloc, etc)
Si vous connaissez Bootstrap, c’est la 3ème approche. Apprendre Bootstrap c’est finalement apprendre la syntaxe de sélecteur et leur imbrication correcte, pour construire un site internet, ou une application. Ce n’est pas bien ou pas bien. C’est l’approche voulue par les créateurs de Bootstrap. Le souci étant que votre code HTML sera définitivement lié à Bootstrap.
Lorsque l’équipe dans laquelle vous travaillez n’a aucunes compétences Webs, Twitter Bootstrap sera un choix tenable. Prenez au moins un peu de temps pour utiliser Themestr.app pour définir votre propre identité graphique. Malgré la mise en place de Bootstrap, j’ai vu que peu de personnes essayent de comprendre le fonctionnement de Bootstrap, et se mélangent les pinceaux. Le pire étant ceux qui re-définissent les styles, sans regarder la palette utilisable avec Twitter, ou des modules complémentaires comme Bootstrap Switch ou Bootstrap Date Picker. Il en existe des dizaines sur le site Awesome Bootstrap.
Si vous devez coder une interface d’administration Web simple, un site privé ou pour une audience limitée : le framework fera l’affaire. J’ai aussi l’habitude d’aller chercher des thèmes complets sur un site comme ThemeForrest. Prenez Metronic par exemple, c’est celui que j’ai utilisé pour le backend des applications Devoxx. Comptez 25 USD, c’est pas très cher payé pour quelque chose qui donnera un look professionnel à votre travail. Mais bon, cela ne vaudra jamais l’oeil d’un vrai expert UX-UI et d’un intégrateur Web. Et cette approche demande un minimum de connaissances CSS/HTML pour être efficace.
Le souci de Bootstrap selon moi, c’est que cela reste assez lourd, et que votre site aura toujours un style « bootstrap ».
Approche 4 à l’aide de classes utilitaire avec Tailwind CSS
La dernière approche est l’utilisation de style agnostique et de classes utilitaires. Apparu à la fin 2017, Tailwind CSS est un framework type Lego, où vous allez devoir assembler différents styles utilitaires pour créer votre interface.
Dans l’approche 3, vous constaterez rapidement une grosse répétition de style. Certes, vous aurez différents composants, mais vous vous retrouverez au final avec beaucoup de code en double. Il est possible d’utiliser un préprocesseur CSS, mais cela reste tangible lorsque vous regarderez le code source d’un site codé avec Bootstrap.
Tailwind CSS n’est pas une boite de Playmobil, c’est une boite de Lego. A vous de combiner des styles génériques, et de construire votre propre « bootstrap » en quelque sorte.
Il n’est pas mieux ou moins bien que Bootstrap, il est orienté utilitaire et très pratique pour construire son propre style « proprement ». Tailwind selon moi ne s’adresse pas aux débutants, et vous devez avoir des bases solides pour comprendre la composition des classes.
Par exemple un bouton « Valider » :
Tailwind CSS utilise la composition de classes utilitaires. Pour apprendre la syntaxe, il faut savoir lire et retenir les descripteurs.
// utilisation de tailwind
<button
class="bg-blue-500 hover:bg-blue-700
text-white font-bold py-2
px-4 rounded">Valider</button>
Ici un button avec un « background bleu 500« , un bleu plus clair lorsque la souris passe sur le bouton (hover), une typo blanche grasse, un padding vertical de 2 et un padding horizontal de 4, avec des bords arrondis.
Bonne nouvelle cependant : si vous utilisez IntelliJ, Webstorm ou Visual Studio, il est possible de bénéficier de la complétion lors de l’écriture des pages.
Reprenons notre exemple, et voici une version possible, facile à créer et qui permet en plus de gérer correctement le responsive :
Le code tout d’abord :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tailwind</title>
<link href="../tailwind.css" rel="stylesheet">
</head>
<body class="bg-gray-100">
<div class="container mx-auto justify-center">
<h1 class="text-xl lg:text-2xl font-bold w-auto fs-10 mt-10">Version BEM</h1>
<div class="md:flex bg-white rounded-xl shadow-xl">
<div class="md:flex-shrink-0">
<img class="w-full p-4" src="https://picsum.photos/id/128/400/300" alt="Image from https://picsum.photos/"/>
</div>
<div class="p-8">
<h1 class="text-2xl font-bold text-teal-600 text-gray-600">Hotel Balamba <span>*****</span></h1>
<p class="text-md lg:text-xl font-light text-gray-800 mb-8">
Logé dans le vieux quartier de Scalito, l'hôtel <cite>Balamba</cite> propose un cadre charmant, avec 14
chambres et 2 suites.
Le bâtiment Monad a été construit à la fin du XIX<sup>ème</sup> siècle.
</p>
<p class="text-md lg:text-xl font-light mb-8">Les visiteurs :
<q class="text-md lg:text-xl font-light text-green-800 mb-8">J'ai adoré ce petit séjour de 3 nuits dans cet écrin de verdure</q>
<q class="text-md lg:text-xl font-light text-green-800 mb-8">Plus qu'un voyage, c'est une plongée dans l'univers de l'Italie et de la programmation fonctionnelle.</q>
</p>
<p class="text-md">Plus d'informations : <a class="block text-center py-2 px-6 bg-teal-500 hover:bg-green-500 rounded-md text-white text-lg bg-green-800" href="#">Voir les disponibilités</a></p>
</div>
</div>
</div>
</body>
</html>
Tailwind CSS n’est pas quelque chose que vous chargez via un CDN. Il faut l’installer, et compiler via npm afin de bénéficier d’une version légère, rapide et ultra-optimisé de votre bibliothèque de style. Plutôt que de charger 4000 briques différentes, le CSS ne contiendra que les différents briques utilisées dans votre projet. En conséquence, le poids de la feuille de style (et donc son chargement) seront beaucoup plus rapide. Sur téléphone mobile, cela a une sacré importance.
Le résultat :
L’intérêt est aussi la facilité de gérer le responsive :
Tailwind évite de re-déclarer les assemblages de style et permet d’aller plus vite. Je pense que l’image des Legos explique bien l’approche de ce framework. Vous devez avoir une bonne compréhension des systèmes de mise en page, des marges, des compositions de styles, mais cela permet sincérement d’aller rapidement à l’essentiel. Par ailleurs Tailwind s’intègre très bien avec React, Vue ou Machin.JS
Alors je sais : je vous avais promis et laissé croire qu’il n’était pas nécessaire d’apprendre à coder et à utiliser CSS. C’est faux, il faudra nécessairement se poser un jour, et suivre une petite formation pour être à l’aise.
Quelques liens pour aller plus loin :
- Installation de Tailwind.css ;
- Un très bon tutorial https://themesberg.com/blog/tailwind-css/tutorial bien que l’installation ne soit pas complètement expliquée ;
- Un espace Playground pour tester Tailwind : https://play.tailwindcss.com/ ;
- Le code de mon exemple : https://play.tailwindcss.com/VoskRFtLBe?layout=preview&size=988×627 ;
- WickedTemplates avec Tailwind.css : collection de blocs prêts à être utilisé pour gagner du temps ;
Très bon article !
Petite précision, il est possible d’utiliser Tailwind avec un fichier CSS dans un CDN.
J’ai d’ailleurs refait mon blog en utilisant Tailwind récemment en utilisant cette approche 🙂
Mouais et quel intéret de Tailwind par rapport à Boostrap ?
Je vois que certains composants sont payants,…
Machin : Non, c’est Tailwind UI qui est payant. Tailwind CSS, a l’instar de Bootstrap est gratuit.
Les deux ont une approche assez différente.
Déjà pour commencer pas d’Ugly-jQuery-Business, on ne parle ici que de style. Ensuite pas de Card our de Hero. Ou tout autre « predefined » content. C’est à toi de construire ce que tu veux.
Enfin. Un poids considérablement réduit grâce à l’utilisation de PurgeCSS (Nicolas a oublié d’en parler, c’est très TRÈS agréable)
Hello,
Débutant en CSS il y a quelque chose que je ne comprends pas dans l\’exemple avec tailwindcss :
on se retrouve avec des instructions de mise en forme directement dans le code html (ex. : class=\ »text-2xl font-bold text-teal-600 text-gray-600\ »).
Je croyais que le but de CSS était de séparer le fond et la forme afin de pouvoir changer la mise en forme sans changer le code html.
Dans le cas de l\’exemple de tailwindcss si je veux changer la couleur du text text-gray-600 dans plusieurs pages HTML, il faut que je modifie le code HTML de chaque page ?
@Franck lorsque tu construis une application Web avec plusieurs pages similaires, tu vas rapidement construire des modèles de page. Or l’idée est que tes pages partagent la même identité graphique. Les titres de niveau 1 auront une certaine configuration. Le texte de tes paragraphes aussi, etc. Tu auras donc une palette de style de base, dont certainement ton text-gray-600 que tu vois. Tu peux alors soit changer la couleur associée à cet alias (auquel cas toutes les balises qui utilisent ce style vont changer) ou alors utiliser un autre style (text-gray-400 par ex.). En fait, imagine que tu as une boite de crayon de couleurs limitées, et que tu ne peux utiliser que les crayons de cette boite. Pense aux Lego sinon. L’approche de tailwind est justement de ne pas te faire déclarer tes styles.
@Clement et @Stemlaur: en effet le gros intérêt de tailwindCss sera de générer des fichiers très léger avec uniquement ce qui est utilisé. Cela va à l’encontre donc de l’importation via CDN où tu vas récupérer l’ensemble de la librairie Tailwind qui pese presque 3Mo. Je préfère que les lecteurs utilisent l’utilitaire via le preprocesseur CSS et npm, et n’utilisent pas la version CDN.
Bonjour,
merci pour cet article fort intéressant. Ce qui est marrant c’est que l’on retrouve des concepts très « backend » dans ces différents frameworks avec notamment la notion de séparation des responsabilités entre structure html et rendu de style.
Tailwind me fait penser à une autre librairie css, Tachyons (https://tachyons.io/), qui j’ai l’impression est très similaire et a comme philosophie le « css fonctionnel ».
Ce que je trouve intéressant dans cette approche est la combinaison actuelle avec les frameworks javascript orienté composants. Cette manière d’appliquer le style permet de se faire une idée très rapide du rendu (sous réserve bien sûr de connaitre un minimum les classes), ce qui facilite la lisibilité du code. Cela force à penser son composant, et donc son style, comme un élément indépendant et donc réutilisable quelque soit le contexte. Si c’est bien utilisé, ça permet aussi d’assurer une cohérence dans toute l’application.
Nous utilisions Tachyons dans ma précédente entreprise et j’en ai un très bon souvenir, c’est quelque chose que je réutiliserais à l’avenir.
De mémoire, l’auteur de Tailwind a écrit quelque part qu’il s’est inspiré de Tachyons, en essayant de faire un peu plus léger. Il y a de bons articles Tailwind vs Tachyons et je pense que c’est intéressant de regarder les deux.