// BLOG

Le framework TailwindCSS

TailwindCSS est un framework CSS créé par Adam Waham. Ce framework fournit des classes utilitaires de bas niveau c'est à dire des classes prédéfinies qui ne font qu'une seule chose à la fois (une seule propriété:valeur par classe). Il gagne de plus en plus en popularité mais aussi en détracteurs. Personnellement, je l'apprécie beaucoup et l'utilise sur tous mes projets personnels.

Rédigé le 10.04.2020
Par Gilles Vauvarin

CSS Framework

Présentation

TailwindCSS est un framework CSS créé par Adam Waham. Ce framework fournit des classes utilitaires de bas niveau c'est à dire des classes prédéfinies qui ne font qu'une seule chose à la fois (une seule propriété:valeur par classe). Par exemple ajouter une marge à droite de "x" pixels, masquer un élément, mettre en gras etc. Ces classes de bas niveau sont suffisament nombreuses pour vous permettent de construire des designs complètement personnalisés sans jamais quitter votre HTML. En effet les classes s'ajoutent les unes derrière les autres directement dans vos balises HTML.

<!-- Classes utilitaires Tailwind dans une balise div -->
<div class="text-center bg-white my-6">
...
</div>

TailwindCSS gère également les interfaces responsives avec un système de prefixage des classes. sm:class pour les petits écrans, md:class pour les écrans de tailles moyennes, lg:class pour les écrans larges etc. Les points de rupture de ces prefixes peuvent biensure être personnalisés via un fichier de configuration.

<!-- Classes utilitaires Tailwind prefixées pour différentes tailles d'écran -->
<div class="justify-start sm:justify-center md:justify-end lg:justify-between xl:justify-around ...">
...
</div>

A la différence des autres framework CSS comme Bootstrap ou Foundation, TailwindCSS ne propose pas de composants prêt à l'emploi (boite de notification, boutton, modale, breadcrum etc). C'est à vous de les concevoir à partir des classes utilitaires fournit. Cela nécessite un peu plus de temps dans la conception front-end mais vous offre plus de souplesse et de flexibilité pour personnaliser vos interfaces.

Si vous aimez les composants prêt à l'emploi, vous pouvez créer votre propre collection personnalisée à l'aide des classes utilitaires du framework et de son fichier de configuration. Autre option, utiliser Tailwind UI, une bibliothèque de composants HTML payante conçus par Adam Waham et Steve Schoger, orientée marketing (landing page, one page etc) et interface (dashboard etc) qui est de très bonne qualité.

Installation

Depuis un CDN

La manière la plus simple d'installer TailwindCSS est d'importer la feuille de style de TailwindCSS via une balise <style> depuis un CDN dans l'en-tête de votre document HTML.

<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">

Cependant, cette façon de faire n'est pas optimale car vous importez toute la feuille de style qui fait 27 kb compréssé alors que vous n'utiliserez probablement qu'une fraction des classes utilitaires du framework.

De plus, en utilisant cette méthode, vous vous privez de toutes les fonctionnalités de personnalisations du framework (utilisation des directives, des plugins etc).

Réservez donc ce type d'installation pour un test rapide en local mais évitez d'utiliser la feuille de style complète du framework dans vos projets en production.

Via npm ou yarn

Si vous optez pour l'installation nmp, vous pourrez profiter de toutes les potentialités de configuration et de personnalisation du framework.

La première étape consiste à créer un fichier package.json Il va nous permettre d'utiliser le système de gestion de packages de NodeJS (npm) pour gérer nos dépendances.

Installation de la dépendance Tailwind

# positionnez-vous dans votre projet
$ cd my-tailwind-project

# initialisez un fichier package.json si votre projet n'en dispose pas encore
$ npm init -y

# installez la dépendance tailwind via npm
$ npm install tailwindcss

# ... ou via Yarn
$ yarn add tailwindcss

Ajouter Tailwind à votre fichier CSS

Une fois Tailwind installé via npm/Yarn, la directive Tailwind @tailwind permettra d'importer les styles Tailwind dans votre fichier CSS.

/* /my-tailwind-project/css/style.css */

/**
 * This injects Tailwind's base styles and any base styles registered by
 * plugins.
 */
@tailwind base;

/**
 * This injects Tailwind's component classes and any component classes
 * registered by plugins.
 */
@tailwind components;

/**
 * This injects Tailwind's utility classes and any utility classes registered
 * by plugins.
 */
@tailwind utilities;

/**
 * Use this directive to control where Tailwind injects the responsive
 * variations of each utility.
 *
 * If omitted, Tailwind will append these classes to the very end of
 * your stylesheet by default.
 */
 @tailwind screens;

Ces directives seront remplacées par les styles CSS correspondants lors du processus de build de Tailwind.

Créer un fichier de configuration Tailwind

Ce fichier est optionnel mais si vous souhaitez personnaliser votre installation Tailwind, vous pouvez générer un fichier de configuration pour votre projet en utilisant l'utilitaire Tailwind CLI inclus lors de l'installation du paquet npm tailwindcss

$ npx tailwindcss init

Cette commande générera un fichier tailwind.config.js dans sa version minimale à la racine de votre projet.

// version minimale du fichier tailwind.config.js
module.exports = {
  theme: {},
  variants: {},
  plugins: [],
}

Nous verons comment utiliser ce fichier un peu plus tard dans le chapitre "Personnalisation".

Buildez vos styles CSS

Tailwind CSS nécessite un processus de build pour traiter les fichiers CSS. Cette étape de build s'assure que le code CSS de Tailwind soit inséré conformément aux directives @tailwind utilisées et aux instructions du fichier Tailwind tailwind.config.js.

Pour effectuer cette étape de build, nous avons plusieurs options :

Tailwind CLI

Pour les projets simples, vous pouvez générer votre fichier CSS à l'aide de Tailwind CLI en utilisant la commande suivante :

npx tailwindcss build styles.css -o output.css

Pour connaître toutes les options de la commande build de Tailwind CLI tappez :

npx tailwindcss help build

PostCSS

PostCSS est outil de développement basé sur des plugins JavaScript qui traitent des fichiers CSS pour les transformer ou les optimiser. Chaque plugin effectue une tâche particulière (autoprefixer, minifier, utiliser les futurs avancées de CSS …), il faut faire attention à leur compatibilité et leur ordre d'utilisation.

Installons le package postCSS via npm, nous pouvons en profiter pour installer également le package autoprefixer pour améliorer la compatibilité de nos CSS dans les différents navigateurs.

$ npm install postcss-cli autoprefixer

PostCSS dispose d'un plugin pour traiter les fichiers du framework TailwindCSS.

Commençons par créer un fichier de configuration postCSS postcss.config.js à la racine de notre projet pour y déclarer les plugins que nous souhaitons utiliser.

// postcss.config.js

module.exports = {
    plugins: [
        require('tailwindcss'),
        require('autoprefixer'),
    ]
}

Nous allons ensuite indiquer dans la partie "scripts" de notre fichier package.json une commande pour builder notre fichier style.css via postcss

// package.json

{
  "name": "project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "buildcss": "postcss css/styles.css -o build/styles.css"
  },
  "author": "",
  "license": "ISC"
}

Le script de build postCSS prend en entrée notre fichier css/styles.css et le process pour fournir un fichier build/styles.css en sortie.

Pour éviter de builder le fichier style.css manuellement à chaque modification, il est possible de l'automatiser avec l'option watch (- w en notation courte).

// installer watch dans votre terminal
$ npm install watch

// ajouter l'option watch "-w" dans votre fichier package.json
...
  "scripts": {
    "buildcss": "postcss css/styles.css -o build/styles.css -w"
  },
...

Pour executer ce script, tappez la commande suivante depuis le dossier racine de votre projet.

$ npm run build

Nous pouvons maintenant appeler le fichier build/styles.css dans le header de nos templates front-end ou nos fichiers html.

Utilisation d'un Bundler

Pour les projets un peu plus complexes, vous devrez probablement utiliser un bundle de type Webpack, Laravel Mix, Parcel ou Brunch. La documentation officielle de Tailwind propose des exemples de configurations pour différents bundlers.

Concepts

Les classes utilitaires

Nous avons l'habitude d'écrire nos styles dans un fichier CSS, de définir nos noms de classes et de les ajouter à nos balises HTML. Nous l'avons vue dans le chapitre "présentation", avec Tailwind, vous stylez vos éléments en appliquant des classes utilitaires pré-existantes directement dans vos balises HTML.

Cette approche peut sembler contre intuitive au premier abord mais si on s'y intéresse de plus prêt, elle comporte de nombreux avantages.

Responsive design

Tailwind gère la gestion du responsive design à l'aide d'un système de prefixes (sm:class, md:class, lg:class, xl:class) que l'on applique aux classes utilitaires.

<div class="justify-start sm:justify-center"></div>

Par défaut, Tailwind utilise des points de ruptures "mobile first". Les classes utilitaires non prefixées s'appliquent à toutes les tailles d'écrans. Les classes préfixées ne prennent effet qu'au point de rupture spécifié et au-delà.

Cela signifie donc que les classes non prefixées sont celles qui s'appliquent en priorités pour les écrans mobiles. Pour les tailles d'écrans plus larges, vous devez prefixer les classes si vous souhaitez mettre en place un design responsive. Si vous décidez de conserver cette approche "mobile first" il est conseillé de consruire votre design en commencant par les écrans mobiles puis de passer aux tailles d'écrans supérieures.

Les points de rupture par défaut du framework sont les suivants :

/* Small (sm) */
@media (min-width: 640px) { /* ... */ }

/* Medium (md) */
@media (min-width: 768px) { /* ... */ }

/* Large (lg) */
@media (min-width: 1024px) { /* ... */ }

/* Extra Large (xl) */
@media (min-width: 1280px) { /* ... */ }

Ces points de ruptures peuvent être personnalisés dans le fichier de configuration tailwind.config.js, nous verrons cela dans le chapitre "Personnalisations".

Responsive design

Les pseudo-classes permettent d’appliquer des styles à des éléments HTML uniquement lorsque ceux-ci sont dans un certain état (cliqués, activés, etc.).

Tailwind utilise, comme pour le responsive, un système de prefixage des classes utilitaires pour appliquer les pseudo-classes.

<div class="bg-gray-200 hover:bg-white hover:border-gray-300"><div>

Pour ne pas alourdir davantage le framework, Tailwind ne gère pas toutes les variantes des pseudo-classes mais uniquement celles les plus utilisées.

Tailwind supporte hover, focus, active, disabled, visited, first-child, last-child, odd-child, even-child, group-hover, et focus-within.

Si vous avez besoin de cibler une pseudo-classe qui n'est pas gérée par défaut par Tailwind, vous pouvez étendre les variantes supportées en écrivant un plugin.

Exemple d'utilisation de la pseudo-classe hover

<button class="bg-transparent hover:bg-blue-500 text-blue-700 hover:text-white...">
  Hover me
</button>

Vous pouvez contrôler quelles variantes de pseudo-classes sont activées pour une classe utilitaire dans la section variants de votre fichier tailwind.config.js :

// tailwind.config.js
module.exports = {
  // ...
  variants: {
    backgroundColor: ['responsive', 'hover', 'focus'],
  },
}

Sur l'exemple ci-dessus, j'active sur la classe utilitaire ayant pour clé backgroundColor uniquement les prefixes gérant la responsivité, le survol et le focus.

Vous pouvez également combiner les prefixes des pseudo-classes avec ceux des points de rupture responsive. Pour cela, appliquer toujours le prefixe responsive en premier.

<button class="bg-orange-500 sm:hover:bg-green-600">
  Button
</button>

Les styles de base

Tailwind applique par défaut un certain nombre de "reset" basé sur normalize.css pour harmoniser le style des balises HTML dans les différents navigateurs.

Mais vous pouvez aussi appliquer vos propres styles de base.

En utilisant des classes utilitaires dans votre HTML

Si vous souhaitez juste appliquer des styles de base aux éléments <html> et <body> Tailwind recommande d'appliquer des classes utilitaires dans les balises en questions plutôt que d'écrire du CSS.

<!doctype html>
<html lang="en" class="text-gray-900 antialiased leading-tight">
  <!-- ... -->
  <body class="min-h-screen bg-gray-100">
    <!-- ... -->
  </body>
</html>

En écrivant du CSS

En revanche, si vous souhaitez appliquer des styles de base uniquement à des éléments spécifiques, mieux vaut les écrire dans votre fichier styles.css de la façon suivante :

@tailwind base;

h1 {
  @apply text-2xl;
}
h2 {
  @apply text-xl;
}
h3 {
  @apply text-lg;
}
a {
  @apply text-blue-600 underline;
}

@tailwind components;

@tailwind utilities;

Tailwind préconise l'utilisation de @apply ou theme() pour que vos nouvelles classes soient gérées via le framework.

La même approche est conseillée pour introduire vos propres fonts avec @font-face :

@tailwind base;

@font-face {
  font-family: Proxima Nova;
  font-weight: 400;
  src: url(/fonts/proxima-nova/400-regular.woff) format("woff");
}
@font-face {
  font-family: Proxima Nova;
  font-weight: 500;
  src: url(/fonts/proxima-nova/500-medium.woff) format("woff");
}

@tailwind components;

@tailwind utilities;

En écrivant un pugin

Ecrire un plugin est un peu plus compliqué mais cela peut être utile si vous souhaitez :

Partager ce plugin de "Reset" avec la communauté et permettre à d'autres de l'installer facilement.

Réutiliser votre "Reset" personnalisé dans d'autres projets à l'aide de dépendances JS plutôt que CSS.

Exemple en utilisant addBase qui importera automatiquement vos styles de bases dans le @tailwind base

// tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addBase, config }) {
      addBase({
        'h1': { fontSize: config('theme.fontSize.2xl') },
        'h2': { fontSize: config('theme.fontSize.xl') },
        'h3': { fontSize: config('theme.fontSize.lg') },
      })
    })
  ]
}

Extraire des composants

Au fur et à mesure que votre projet grandit, des patterns de combinaison de classes utilitaires vont se répéter. Ca sera le cas par exemple avec les boutons de votre interface. Dans ce cas, ça peut être intéressant de construire un composant "btn" pour factoriser votre code.

Plusieurs approches sont possibles :

Créer un composant javaScript (ou à l'aide d'un framework JS comme Vue ou React)

Extraire le composant avec @apply dans le fichier tailwind.config.js

Ecrire un plugin "composant"

Extraire le composant avec @apply

Pour les composants simples (boutons, cards …) il est plus judicieux d'extraire le composant avec la directive @apply Ces composants doivent être déclarés avant l'instruction@tailwind utilities et les pseudo-classes doivent être traitées sur une ligne distincte.

@tailwind base;

@tailwind components;

.btn-blue {
  @apply bg-blue-500 text-white font-bold py-2 px-4 rounded;
}
.btn-blue:hover {
  @apply bg-blue-700;
}

@tailwind utilities;

Il est important de bien décomposer les composants pour ne pas répéter des classes inutilement. Si par exemple deux boutons partagent des classes communes (padding, coins arrondies …) , faites en une classe commune.

// plutôt que d'écrire ....
.btn-blue {
  @apply bg-blue-500 text-white font-bold py-2 px-4 rounded;
}
.btn-gray {
  @apply bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded;
}

// préférez ...
.btn {
  @apply font-bold py-2 px-4 rounded; /* cette partie est commune aux deux boutons */
}
.btn-blue {
  @apply bg-blue-500 text-white;
}
.btn-gray {
  @apply bg-gray-400 text-gray-800;
}

// dans le html ...
<button class="btn btn-blue">Button</button>
<button class="btn btn-gray">Button</button>

Ecrire un plugin composant

Pour écrire un plugin composant, vous devez utiliser la fonction addComponents Vous trouverez plus de détails dans la documentation officielle.

// tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addComponents }) {
      const buttons = {
        '.btn': {
          padding: '.5rem 1rem',
          borderRadius: '.25rem',
          fontWeight: '600',
        },
        '.btn-blue': {
          backgroundColor: '#3490dc',
          color: '#fff',
          '&:hover': {
            backgroundColor: '#2779bd'
          },
        },
        '.btn-red': {
          backgroundColor: '#e3342f',
          color: '#fff',
          '&:hover': {
            backgroundColor: '#cc1f1a'
          },
        },
      }

      addComponents(buttons)
    })
  ]
}

Ajout de nouvelles classes utilitaires

Bien que Tailwind offre une grande variété de classes utilitaires, vous pouvez avoir besoin d'en ajouter d'autres.

La manière la plus simple et de les ajouter dans votre fichier styles.css après l'instruction @tailwind utilities

@tailwind base;
@tailwind components;
@tailwind utilities;

.rotate-0 {
  transform: rotate(0deg);
}
.rotate-90 {
  transform: rotate(90deg);
}
.rotate-180 {
  transform: rotate(180deg);
}
.rotate-270 {
  transform: rotate(270deg);
}

Pseudo-classes & responsive

Si vous souhaitez créer une variante responsive de vos propres classes utilitaires basée sur les points de ruptures déjà définies dans votre fichier tailwind.config.js enveloppez vos classes utilitaires dans une directive @responsive

@tailwind base;
@tailwind components;
@tailwind utilities;

@responsive {
  .rotate-0 {
    transform: rotate(0deg);
  }
  .rotate-90 {
    transform: rotate(90deg);
  }
  .rotate-180 {
    transform: rotate(180deg);
  }
  .rotate-270 {
    transform: rotate(270deg);
  }
}
<div class="rotate-180 md:rotate-0"></div>

Consulter la documentation officielle pour en savoir plus sur le responsive.

Variantes de pseudo-classes

Si vous souhaitez créer une variante de pseudo-classes de vos propres classes utilitaires, dans votre fichier tailwind.config.js enveloppez vos classes utilitaires dans une directive @variants de la façon suivante :

@tailwind base;
@tailwind components;
@tailwind utilities;

@variants hover, focus {
  .rotate-0 {
    transform: rotate(0deg);
  }
  .rotate-90 {
    transform: rotate(90deg);
  }
  .rotate-180 {
    transform: rotate(180deg);
  }
  .rotate-270 {
    transform: rotate(270deg);
  }
}

Tailwind générera automatiquement des versions préfixées des pseudo-classes pour chaque utilitaire personnalisé :

<div class="rotate-0 hover:rotate-90"></div>

Les variantes de pseudo-classe sont générées dans le même ordre que dans la directive @variants, donc si vous souhaitez qu'une pseudo-classe ait la priorité sur une autre, assurez-vous de l'énumérer en dernier :

/* Focus prendra le dessus sur hover */
@variants hover, focus {
  .rotate-0 {
    transform: rotate(0deg);
  }
  /* ... */
}

/* Hover prendra le dessus sur focus */
@variants focus, hover {
  .rotate-0 {
    transform: rotate(0deg);
  }
  /* ... */
}

Si vous souhaitez générer à la fois des variantes responsive et pseudo-classes de vos utilitaires personnalisés, enveloppez la directive @variants dans une directive @responsive :

@tailwind base;
@tailwind components;
@tailwind utilities;

@responsive {
  @variants hover, focus {
    .rotate-0 {
      transform: rotate(0deg);
    }
    .rotate-90 {
      transform: rotate(90deg);
    }
    .rotate-180 {
      transform: rotate(180deg);
    }
    .rotate-270 {
      transform: rotate(270deg);
    }
  }
}

Consulter la documentation officielle pour en savoir plus sur les pseudo-classes.

Déclarer ses classes utilitaires via un plugin

Vous pouvez également écrire un plugin pour ajouter vos classes utilitaires si vous souhaitez les partager plus facilement.

// tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addUtilities }) {
      const newUtilities = {
        '.rotate-0': {
          transform: 'rotate(0deg)',
        },
        '.rotate-90': {
          transform: 'rotate(90deg)',
        },
        '.rotate-180': {
          transform: 'rotate(180deg)',
        },
        '.rotate-270': {
          transform: 'rotate(270deg)',
        },
      }

      addUtilities(newUtilities, ['responsive', 'hover'])
    })
  ]
}

Consultez la documentation officielle pour en savoir plus sur l'écriture d'un plugin pour ses classes utilitaires.

Directives et fonctions

La directive @tailwind

La directive @tailwind permet d'importer les styles bases, components, utilities et screens du framework.

/**
 * This injects Tailwind's base styles and any base styles registered by
 * plugins.
 */
@tailwind base;

/**
 * This injects Tailwind's component classes and any component classes
 * registered by plugins.
 */
@tailwind components;

/**
 * This injects Tailwind's utility classes and any utility classes registered
 * by plugins.
 */
@tailwind utilities;

/**
 * Use this directive to control where Tailwind injects the responsive
 * variations of each utility.
 *
 * If omitted, Tailwind will append these classes to the very end of
 * your stylesheet by default.
 */
 @tailwind screens;

La directive @apply

La directive @apply permet d'extraire des composants dans sa propre feuille de style si des éléments se répètent dans votre projet.

.btn {
  transform: translateY(-1px);
  @apply block bg-red-500;
}
.btn:hover {
  @apply bg-blue-500;
}
@screen md {
  .btn {
    @apply inline-block;
  }
}

On peut utiliser les classes utilitaires du framework et/ou ses propres propriété:valeur

Les pseudo-classes et le responsive doivent être traités séparement.

La directive @variants

Vous pouvez générer des versions responsive, hover, focus, active, focus-withinet group-hover de vos propres classes utilitaires en incluant leurs définitions dans la directive @variants

/* input : */
@variants focus, hover {
  .rotate-0 {
    transform: rotate(0deg);
  }
  .rotate-90 {
    transform: rotate(90deg);
  }
}

/* output : */
.rotate-0 {
  transform: rotate(0deg);
}
.rotate-90 {
  transform: rotate(90deg);
}

.focus\:rotate-0:focus {
  transform: rotate(0deg);
}
.focus\:rotate-90:focus {
  transform: rotate(90deg);
}

.hover\:rotate-0:hover {
  transform: rotate(0deg);
}
.hover\:rotate-90:hover {
  transform: rotate(90deg);
}

Les variantes de pseudo-classes sont générées dans l'ordre dans lequel vous les spécifiez dans le fichier styles.css.

Ainsi, si vous voulez que les classes utilitaires de focus soient prioritaires sur les classes utilitaires de hover par exemple, assurez-vous que focus vient après hover dans la liste :

/* Input */
@variants hover, focus {
  .banana {
    color: yellow;
  }
}

/* Output */
.banana {
  color: yellow;
}
.hover\:banana:hover {
  color: yellow;
}
.focus\:banana:focus {
  color: yellow;
}

La directive @responsive

Vous pouvez générer des variantes responsive de vos propres classes utilitaires en enveloppant leurs définitions dans la directive @responsive :

/* Input ... */
@responsive {
  .bg-gradient-brand {
    background-image: linear-gradient(blue, green);
  }
}

/* Output ... avec les points de rupture par défaut */
.bg-gradient-brand {
  background-image: linear-gradient(blue, green);
}

/* ... */

@media (min-width: 640px) {
  .sm\:bg-gradient-brand {
    background-image: linear-gradient(blue, green);
  }
  /* ... */
}

@media  (min-width: 768px) {
  .md\:bg-gradient-brand {
    background-image: linear-gradient(blue, green);
  }
  /* ... */
}

@media (min-width: 1024px) {
  .lg\:bg-gradient-brand {
    background-image: linear-gradient(blue, green);
  }
  /* ... */
}

@media (min-width: 1280px) {
  .xl\:bg-gradient-brand {
    background-image: linear-gradient(blue, green);
  }
  /* ... */
}

La directive @screen

La directive @screen vous permet de créer des media queries qui référencent vos points de ruprures par leur nom au lieu de dupliquer leurs valeurs dans votre propre CSS.

Par exemple, si vous avez un point de rupture sm à 640px et que vous devez écrire un CSS personnalisé qui référence ce point de rupture.

Au lieu d'écrire une media queries brute qui duplique cette valeur comme ceci :

<code>@media (min-width: 640px) { /* ... */ }</code>

Vous pouvez utiliser la directive @screen et référencer le point de rupture par son nom :

@screen sm {
  /* ... */
}

La fonction theme()

Utilisez la fonction theme() pour accéder aux valeurs de configuration de votre Tailwind en utilisant la notation pointée.

Cela peut être une alternative utile à l'utilisation de la directive @apply lorsque vous souhaitez référencer une valeur de votre configuration de votre theme pour une partie seulement d'une déclaration :

.content-area {
  height: calc(100vh - theme('spacing.12'));
}

N'utilisez pas la syntaxe du tiret lorsque vous accédez à des valeurs mais plutôt la synthaxe pointé :

/* Nope, ne faite pas cela ... */
.btn-blue {
  background-color: theme('colors.blue-500');
}

/* mais plutôt ... */

.btn-blue {
  background-color: theme('colors.blue.500');
}

Personnalisations

Configuration

Ce qui fait la force de Tailwind, ce sont ses nombreuses possibilités de personnalisation. Par défaut, Tailwind cherchera un fichier optionnel tailwind.config.js à la racine de votre projet où vous pourrez définir toutes vos personnalisations.

Chaque section du fichier de configuration est facultative, il vous suffit donc de préciser ce que vous souhaitez modifier. Toute section manquante sera remplacée par la configuration par défaut de Tailwind.

Si Tailwind CLI est installé, vous pouvez générer un fichier tailwind.config.js minimal avec la commande :

$ npx tailwindcss init

// tailwind.config.js à la racine de votre projet
module.exports = {
  theme: {},
  variants: {},
  plugins: [],
}

- theme permet de personnaliser tout ce qui concerne le design

- variants permet de contrôler quels variantes de pseudo-classes on souhaite ajouter à nos classes utilitaires

- plugins permet d'enregistrer des plugins tiers qui peuvent être utilisés pour générer des classes utilitaires supplémentaires, des composants, des styles de base (reset) ou des variantes de pseudo-classes personnalisées.

// tailwind.config.js
module.exports = {
  plugins: [
    require('tailwindcss-transforms'),
    require('tailwindcss-transitions'),
    require('tailwindcss-border-gradients'),
  ],
}

- prefix permet d'ajouter un préfixe personnalisé à toutes les classes utilitaires générées par Tailwind. Cela peut être très utile pour éviter des conflits de noms lorsque vous superposez Tailwind à des CSS existants.

// tailwind.config.js
module.exports = {
  prefix: 'thewhale-',
}

// output ...
.thewhale-text-left {
  text-align: left;
}
.thewhale-text-center {
  text-align: center;
}
...

// dans le html ...
<div class="thewhale-text-lg md:thewhale-text-xl thewhale-bg-red-500 hover:thewhale-bg-blue-500">
  <!-- -->
</div>

Les préfixes ne sont ajoutés qu'aux classes générées par Tailwind. Aucun préfixe ne sera ajouté à vos propres classes personnalisées.

Si vous souhaitez également préfixer vos propres classes utilitaires, il suffit d'ajouter le préfixe à la définition de la classe :

@responsive  {
  .thewhale-bg-brand-gradient { /* ... */ }
}

- important Configurer important à true dans le fichier de configuration, ajoutera !important à toutes les classes utilitaires par défaut de Tailwind. Cela peut etre utile si vous souhaitez utiliser des styles CSS externes au framework et que les styles de Tailwind prennent le dessus.

// tailwind.config.js
module.exports = {
  important: true,
}

// pour faire la meme chose sur ces propres classes utilitaires
// ajouter !important à la fin de ses déclarations
@responsive  {
  .bg-brand-gradient {
    background-image: linear-gradient(#3490dc, #6574cd) !important;
  }
}

Consulter la documentation officielle pour plus de précisions et identifier les éventuelles précautions.

- separator permet de personnaliser le caractère ou la chaîne à utiliser pour séparer les préfixes de variantes de pseudo-classes (responsive, hover, focus, etc.) des noms des classes utilitaires. Tailwind utilise deux points par défaut (:), mais il peut être utile de changer cela si vous utilisez un langage de template comme Pug qui ne supporte pas les caractères spéciaux dans les noms de classe.

// tailwind.config.js
module.exports = {
  separator: '_',
}

- core plugins permet de désactiver complètement les classes que Tailwind générerait normalement par défaut si vous n'en avez pas besoin pour votre projet. Si vous ne fournissez aucune configuration de corePlugins, tous les plugins de base (qui définissent les classes utilitaires de Tailwind) seront activés par défaut. Si vous souhaitez désactiver des plugins de base spécifiques, fournissez un objet pour corePlugins qui déclare ces plugins à false :

// tailwind.config.js
module.exports = {
  corePlugins: {
    float: false,
    objectFit: false,
    objectPosition: false,
  }
}

Si vous souhaitez établir une liste blanche des plugins de base qui doivent être activés, fournissez un tableau comprenant une liste des plugins de base que vous souhaitez utiliser :

// tailwind.config.js
module.exports = {
  corePlugins: [
    'margin',
    'padding',
    'backgroundColor',
    // ...
  ]
}

Si vous souhaitez désactiver tous les plugins de base de Tailwind et utiliser simplement Tailwind comme outil pour traiter vos propres plugins personnalisés, fournissez un tableau vide :

// tailwind.config.js
module.exports = {
  corePlugins: []
}

La liste des plugins de Tailwind est disponible dans la documentation officielle.

Référencer Tailwind dans javaScript

Il peut être utile de référencer vos valeurs de configuration dans votre propre JavaScript côté client - par exemple pour accéder à certaines des valeurs de votre thème lors de l'application dynamique de styles en ligne dans un composant React ou Vue.

Pour vous faciliter la tâche, Tailwind fournit un helper resolveConfig que vous pouvez utiliser pour générer une version entièrement fusionnée de votre objet de configuration :

import resolveConfig from 'tailwindcss/resolveConfig'
import tailwindConfig from './tailwind.config.js'

const fullConfig = resolveConfig(tailwindConfig)

fullConfig.theme.width[4]
// => '1rem'

fullConfig.theme.screens.md
// => '768px'

fullConfig.theme.boxShadow['2xl']
// => '0 25px 50px -12px rgba(0, 0, 0, 0.25)'

Theme

TailwindsCSS définit des valeurs par défaut que vous pouvez retrouver sur le dépôt Github du projet. Toutes ces valeurs peuvent être redefinit ou étendue avec vos propres valeurs selon vos besoins.

En modifiant cet objet theme et en re-buildant le fichier styles.css, vous pouvez personnaliser le framework de différentes manières :

en définissant de nouvelles classes

en changeant des classes existantes

en étendant des classes existantes

Dans le fichier tailwind.config.js l'objet javaScript theme contient toutes les définissions de styles qui régissent les aspects visuels du framework (palette de couleurs, fonts stack, bordure, ombres, points de rupture pour le responsive etc) avec une clé pour chaque aspect visuel ( screens, fontFamily, borderWidth etc). Excepté pour les clés screens, colors et spacing, les autres clés correspondent à des plugins du "Core" de Tailwind.

// tailwind.config.js
module.exports = {
  theme: {
    screens: {
      sm: '640px',
      md: '768px',
      lg: '1024px',
      xl: '1280px',
    },
    fontFamily: {
      display: ['Gilroy', 'sans-serif'],
      body: ['Graphik', 'sans-serif'],
    },
    borderWidth: {
      default: '1px',
      '0': '0',
      '2': '2px',
      '4': '4px',
    },
    extend: {
      colors: {
        cyan: '#9cdbff',
      },
      spacing: {
        '96': '24rem',
        '128': '32rem',
      }
    }
  }
}

Screens

La section screens permet de définir les points de rupture pour la gestion du responsive.

Voir la documentation officielle pour la personnalisation des points de rupture.

Colors

La section colors permet de définir votre palette de couleurs. Les plugins "Core" backgroundColor, textColor, et borderColor hériteront de ces couleurs.

Voir la documentation officielle pour la personnalisation des couleurs.

Spacing

La section spacing permet de définir les espacements. Les plugins "Core" padding, margin, negativeMargin, width, et height hériteront de ces espacements.

Voir la documentation officielle pour la personnalisation des espacements.

Core plugins

Les autres clés de la section theme sont utilisées pour configurer les valeurs qui seront disponibles pour chacun des plugins du "Core".

Exemple avec la clé borderRadius qui définit la class rounded avec la propriété border-radius utilisé pour arrondir les coins :

// tailwind.config.js

module.exports = {
  theme: {
    borderRadius: {
      default: '.25rem',
      'none': '0',
      'sm': '.125rem',
      'lg': '.5rem',
      'full': '9999px',
    },
  }
}

Après l'étape de build, cette configuration donnera àccès aux classes suivantes :

/* build/styles.css */

.rounded      { border-radius: .25rem }
.rounded-none { border-radius: 0 }
.rounded-sm   { border-radius: .125rem }
.rounded-lg   { border-radius: .5rem }
.rounded-full { border-radius: 9999px }

Dans l'objet borderRadius la clé correspond au suffix qui sera ajouté au nom de la classe rounded et la valeur correspond à la valeur qui s'appliquera à la propriété border-radius

Lorsque la clé est default, cela correspond à la création de la classe rounded sans suffix.

Pour consulter la configuration de chaque plugin, se référer au fichier de configuration par défaut de Tailwind.

Remplacer des valeurs du theme

Pour remplacer des valeurs par défaut du theme, indiquer dans votre fichier tailwind.config.js la clé que vous souhaitez redéfinir et ajouter vos propres valeurs. Toutes les autres clés non redéfinies seront préservé et correspondront aux valeurs par défaut du framework.

// tailwind.config.js
module.exports = {
  theme: {
    // Replaces all of the default `opacity` values
    opacity: {
      '0': '0',
      '20': '0.2',
      '40': '0.4',
      '60': '0.6',
      '80': '0.8',
      '100': '1',
    }
  }
}

Etendre le theme

Si vous souhaitez conserver les valeurs du thème par défaut mais y ajouter des valeurs personnels, utilisez la clé extend de la façon suivante :

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      // Adds a new breakpoint in addition to the default breakpoints
      screens: {
        '2xl': '1440px',
      }
    }
  }
}

Vous pouvez biensure à la fois remplacer les valeurs d'une clé et etendre une autre clé du theme dans votre fichier tailwind.config.js.

Référencer d'autres valeurs au theme

Si vous avez besoin de référencer une autre valeur dans votre theme, vous pouvez le faire en fournissant une closure au lieu d'une valeur statique. La closure recevra une fonction theme() que vous pourrez utiliser pour rechercher d'autres valeurs dans votre theme en utilisant la notation pointée.

Par exemple, vous pouvez générer des classes utilitaires de remplissage pour chaque couleur de votre palette de couleurs en référençant le theme ("colors") dans votre configuration :

// tailwind.config.js
module.exports = {
  theme: {
    colors: {
      // ...
    },
    fill: theme => theme('colors')
  }
}

La fonction theme() tente de trouver la valeur que vous recherchez à partir de l'objet theme entièrement fusionné, afin de pouvoir faire référence à vos propres personnalisations ainsi qu'aux valeurs de theme par défaut. Elle fonctionne également de manière récursive, de sorte que tant qu'il y a une valeur statique à la fin de la chaîne, elle sera capable de résoudre la valeur que vous recherchez.

Référencer des valeurs du theme par defaut

Si vous avez besoin de référencer des valeurs par défaut du thème, vous pouvez le faire en les important de tailwindcss/defaultTheme.

Exemple : ajouter une fonte dans un "font stacks" existant de Tailwind :

// tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: [
          'Lato',
          ...defaultTheme.fontFamily.sans,
        ]
      }
    }
  }
}

Désactiver un plugin core entier

Si vous ne désirez pas générer des classes pour un plugin du Core, utilisez la clé corePlugins et à l'intérieur, désactivez le plugin en lui passant la valeur false.

// tailwind.config.js
module.exports = {
  corePlugins: {
    opacity: false,
  }
}

Ajouter vos propres clés au theme

Il existe un certain nombre de situations où il peut être utile d'ajouter vos propres clés à l'objet theme.

Un exemple de cela est l'ajout de nouvelles clés pour créer une source unique pour les valeurs qui sont communes entre plusieurs plugins de base. Par exemple, vous pourriez extraire un objet positions partagé qui pourrait être référencé à la fois par les plugins backgroundPosition et objectPosition :

// tailwind.config.js
module.exports = {
  theme: {
    positions: {
      bottom: 'bottom',
      center: 'center',
      left: 'left',
      'left-bottom': 'left bottom',
      'left-top': 'left top',
      right: 'right',
      'right-bottom': 'right bottom',
      'right-top': 'right top',
      top: 'top',
    },
    backgroundPosition: theme => theme('positions'),
    objectPosition: theme => theme('positions'),
  }
}

Un autre exemple est l'ajout d'une nouvelle clé de référence à l'intérieur d'un plugin personnalisé. Par exemple, si vous avez écrit un plugin de gradients pour votre projet, vous pouvez ajouter une clé de gradients à l'objet de votre theme auquel le plugin fait référence :

// tailwind.config.js
module.exports = {
  theme: {
    gradients: theme => ({
      'blue-green': [theme('colors.blue.500'), theme('colors.green.500')],
      'purple-blue': [theme('colors.purple.500'), theme('colors.blue.500')],
      // ...
    })
  },
  plugins: [
    require('./plugins/gradients')
  ],
}

Puisque l'objet theme est entièrement disponible dans votre CSS en utilisant la fonction theme(), vous pouvez également ajouter une clé juste pour pouvoir le référencer dans votre CSS.

Points de rupture

Vous définissez les points de rupture de votre projet dans la section theme.screens de votre fichier tailwind.config.js. Les clés sont vos noms d'écran (utilisés comme préfixe, comme md:text-center), et les valeurs sont la largeur minimale min-width où ce point de rupture doit commencer.

Les points de rupture par défaut s'inspirent des résolutions des appareils courants :

// tailwind.config.js
module.exports = {
  theme: {
    screens: {
      'sm': '640px',
      // => @media (min-width: 640px) { ... }
      'md': '768px',
      // => @media (min-width: 768px) { ... }
      'lg': '1024px',
      // => @media (min-width: 1024px) { ... }
      'xl': '1280px',
      // => @media (min-width: 1280px) { ... }
    }
  }
}

Vous pouvez modifier les prefixes et/ou les tailles d'écrans :

// tailwind.config.js
module.exports = {
  theme: {
    screens: {
      'tablet': '640px',
      // => @media (min-width: 640px) { ... }
      'laptop': '1024px',
      // => @media (min-width: 1024px) { ... }
      'desktop': '1280px',
      // => @media (min-width: 1280px) { ... }
    },
  }
}

Si vous préférez travailler avec des points de rupture en max-width plutôt qu'en min-width ou les deux à la fois, utilisez les clés max et min dans vos objets de la façon suivante :

// tailwind.config.js > utilisation de max-width
module.exports = {
  theme: {
    screens: {
      'xl': {'max': '1279px'},
      // => @media (max-width: 1279px) { ... }
      'lg': {'max': '1023px'},
      // => @media (max-width: 1023px) { ... }
      'md': {'max': '767px'},
      // => @media (max-width: 767px) { ... }
      'sm': {'max': '639px'},
      // => @media (max-width: 639px) { ... }
    }
  }
}

// tailwind.config.js > utilisationde max-width & min-width
module.exports = {
  theme: {
    screens: {
      'sm': {'min': '640px', 'max': '767px'},
      'md': {'min': '768px', 'max': '1023px'},
      'lg': {'min': '1024px', 'max': '1279px'},
      'xl': {'min': '1280px'},
    },
  }
}

Points de rupture multi-rang

Parfois, il peut être utile d'avoir un point de rupture qui s'applique sur plusieurs rang de taille d'écran.

Par exemple, si vous avez une barre latérale et que vous voulez que vos points de rupture soient basés sur la largeur de la zone de contenu principale plutôt que sur la zone entière (sidebar + contenu principal). Vous pouvez simuler que l'un de vos points de rupture (ici md:) se ramène à un point d'arrêt plus petit (ici sm:) lorsque la barre latérale devient visible et réduit la zone de contenu principale :

// tailwind.config.js
module.exports = {
  theme: {
    screens: {
      'sm': '500px',
      'md': [
        {'min': '668px', 'max': '767px'},
        // La Sidebar apparait à 768px
        // entre 768px et 868px, ce sont les styles 'sm:' qui s'appliquent
        // au delà de 868px, l'espace occupé par le contenu princpal est assez large 
        // pour appliquer de nouveau les styles de 'md:'
        {'min': '868px'}
      ],
      'lg': '1100px',
      'xl': '1400px',
    }
  }
}

Media queries personalisées

Si vous avez besoin de fournir media-queries entièrement personnalisée pour un point de rupture, vous pouvez le faire en utilisant un objet avec une clé raw :

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      screens: {
        'portrait': {'raw': '(orientation: portrait)'},
        // => @media (orientation: portrait) { ... }
      }
    }
  }
}

Styles pour l'impression

La clé raw peut être particulièrement utile si vous souhaitez appliquer des styles spécifiques pour l'impression par exemple.

Il vous suffit d'ajouter une clé print sous theme.extend.screens :

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      screens: {
        'print': {'raw': 'print'},
        // => @media  print { ... }
      }
    }
  }
}

Vous pouvez ensuite utiliser des classes comme print:text-black pour spécifier des styles qui ne doivent être appliqués que lorsque quelqu'un essaie d'imprimer la page sur laquelle vous travaillez :

<div class="text-gray-700 print:text-black">
  <!-- ... -->
</div>

Couleurs

La palette de couleurs par défaut de Tailwind est visible dans la documentation oficielle

Par défaut, ces couleurs sont automatiquement partagées par les classes utilitaires textColor, borderColor et backgroundColor Ainsi, la configuration ci-dessous génère des classes comme .text-indigo, .border-blue et .bg-red

// tailwind.config.js
module.exports = {
  theme: {
    colors: {
      indigo: '#5c6ac4',
      blue: '#007ace',
      red: '#de3618',
    }
  }
}

Synthaxe imbriquée des objets

Vous pouvez définir vos couleurs soit comme une simple liste de paires clé-valeur comme nous l'avons fait ci-dessus, soit en utilisant une notation d'objets imbriqués où les clés imbriquées (ici lighter, default, dark) sont ajoutées au nom de la couleur de base (ici indigo) en tant que modificateurs.

// tailwind.config.js
module.exports = {
  theme: {
    colors: {
      indigo: {
        lighter: '#b3bcf5',
        default: '#5c6ac4',
        dark: '#202e78',
      }
    }
  }
}

Comme dans beaucoup d'autres endroits dans Tailwind, la clé default est spéciale et signifie "pas de modificateur", donc cette configuration génère respectivement les classes .text-indigo-lighter, .text-indigo, et .text-indigo-dark.

Notez que vous devez utiliser la notation pointée pour accéder aux couleurs imbriquées lorsque vous utilisez la fonction theme() - la notation avec le tiret est uniquement utilisée pour les noms de classe CSS réels.

/* Nope ! */
.btn-blue {
  background-color: theme('colors.blue-500');
}

/* Yessss ! */
.btn-blue {
  background-color: theme('colors.blue.500');

Remplacer la palette de couleurs par défaut

Utilisez theme.colors pour remplacer la palette de couleurs par défaut. le code ci-dessous désactivera la palette de couleurs par défaut de Tailwind et générera respectivement les classes bg-indigo, text-blue et border-red à la place.

// tailwind.config.js
module.exports = {
  theme: {
    colors: {
      indigo: '#5c6ac4',
      blue: '#007ace',
      red: '#de3618',
    }
  }
}

Etendre la palette de couleurs par défaut

Si vous souhaitez étendre la palette de couleurs par défaut, vous pouvez le faire en utilisant dans la section theme les clés extend.colors Le code ci-dessous va générer la classe bg-regal-blue en plus de toutes les couleurs par défaut de Tailwind.

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        'regal-blue': '#243c5a',
      }
    }
  }
}

Remplacer une couleur de la palette par défaut

Si vous souhaitez remplacer une des couleurs par défaut de Tailwind mais préserver le reste, il vous suffit de fournir les nouvelles valeurs dans la section theme.extend.colors de votre fichier tailwind.config.js.

Dans le code ci-dessous, nous remplacons les gris froids par défaut par une palette de gris neutre :

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        gray: {
          '100': '#f5f5f5',
          '200': '#eeeeee',
          '300': '#e0e0e0',
          '400': '#bdbdbd',
          '500': '#9e9e9e',
          '600': '#757575',
          '700': '#616161',
          '800': '#424242',
          '900': '#212121',
        }
      }
    }
  }
}

Remplacer une nuance de couleur de la palette par défaut

L'option la plus simple est d'importer le thème par défaut et de l'étendre dans la couleur que vous souhaitez personnaliser avec la nouvelle valeur de teinte :

// tailwind.config.js
const { colors } = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    extend: {
      colors: {
        blue: {
          ...colors.blue,
          '900': '#1e3656',
        }
      }
    }
  }
}

Désactiver une couleur de la palette par défaut

Si vous souhaitez désactiver une couleur par défaut parce que vous ne l'utilisez pas dans votre projet, le plus simple est de construire une nouvelle palette de couleurs qui fait référence au thème par défaut.

Le code ci-dessous exclut les couleurs teal, orange et rose, mais inclut le reste des couleurs par défaut :Remplacer une nuance de couleur de la palette par défaut

L'option la plus simple est d'importer le thème par défaut et de l'étendre dans la couleur que vous souhaitez personnaliser avec la nouvelle valeur de teinte :

// tailwind.config.js
const { colors } = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    colors: {
      black: colors.black,
      white: colors.white,
      gray: colors.gray,
      red: colors.red,
      yellow: colors.yellow,
      green: colors.green,
      blue: colors.blue,
      indigo: colors.indigo,
      purple: colors.purple,
    }
  }
}

Si vous êtes à l'aise avec la notion javaScript de destructuring, vous pouvez faire la même chose de la façon suivante :

// tailwind.config.js
const { colors: { teal, orange, pink, ...colors } } = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    colors: colors
  }
}

Nommer ses couleurs

Tailwind utilise par défaut des noms de couleurs littéraux (comme rouge, vert, etc.) et une échelle numérique (où 100 est clair et 900 est foncé). Cela s'avère assez pratique pour la plupart des projets, mais il y a de bonnes raisons d'utiliser également d'autres conventions de dénomination.

Par exemple, si vous travaillez sur un projet qui doit soutenir plusieurs thèmes, il peut être judicieux d'utiliser des noms plus abstraits comme primaire et secondaire :

// tailwind.config.js
module.exports = {
  theme: {
    colors: {
      primary: '#5c6ac4',
      secondary: '#ecc94b',
      // ...
    }
  }
}

Vous pouvez configurer ces couleurs explicitement comme nous l'avons fait ci-dessus, ou vous pouvez même utiliser les couleurs par défaut de Tailwind et alias celles dont vous avez besoin :

// tailwind.config.js
const { colors } = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    colors: {
      primary: colors.indigo,
      secondary: colors.yellow,
      neutral: colors.gray,
    }
  }
}

Vous pourriez même définir ces couleurs à l'aide de propriétés personnalisées CSS (variables) pour faciliter le changement de thème sur le client :

// tailwind.config.js
module.exports = {
  theme: {
    colors: {
      primary: 'var(--color-primary)',
      secondary: 'var(--color-secondary)',
      // ...
    }
  }
}

Et dans votre CSS …

:root {
  --color-primary: #5c6ac4;
  --color-secondary: #ecc94b;
  /* ... */
}

@tailwind  base;
@tailwind  components;
@tailwind  utilities;

Espacements

La clé spacing du theme permet de remplacer l'échelle d'espacement par défaut de Tailwind.

// tailwind.config.js
module.exports = {
  theme: {
    spacing: {
      '1': '8px',
      '2': '12px',
      '3': '16px',
      '4': '24px',
      '5': '32px',
      '6': '48px',
    }
  }
}

Par défaut, l'échelle d'espacement est partagée par les classes utilitaires de padding, de margin, de width et de height, de sorte que la configuration ci-dessus génère des classes comme .p-2, .mt-3, .w-5, .h-6, etc.

Remplacer l'échelle d'espacement par défaut

Si vous souhaitez remplacer l'échelle d'espacement par défaut, vous pouvez le faire en utilisant la section theme.spacing de votre fichier tailwind.config.js. Le code ci-dessous désactivera l'échelle d'espacement par défaut de Tailwind et générera à la place les classes p-sm, m-md, w-lg et h-xl.

// tailwind.config.js
module.exports = {
  theme: {
    spacing: {
      sm: '8px',
      md: '12px',
      lg: '16px',
      xl: '24px',
    }
  }
}

Etendre l'échelle d'espacement par défaut

Si vous souhaitez étendre l'échelle d'espacement par défaut, vous pouvez le faire en utilisant la section theme.extend.spacing dans votre fichier tailwind.config.js. Le code ci-dessous générera respectivement les classes p-72, m-84 et h-96 en plus de tous les autres classes utilitaires d'espacement et de taille par défaut de Tailwind.

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      spacing: {
        '72': '18rem',
        '84': '21rem',
        '96': '24rem',
      }
    }
  }
}

Variantes responsives et de pseudo-classes

La section variants de votre fichier tailwind.config.js est l'endroit où vous contrôlez quels plugins d'utilitaires de base doivent avoir des variantes responsives et des variantes de pseudo-classes.

// tailwind.config.js
module.exports = {
  variants: {
    appearance: ['responsive'],
    // ...
    borderColor: ['responsive', 'hover', 'focus'],
    // ...
    outline: ['responsive', 'focus'],
    // ...
    zIndex: ['responsive'],
  },
}

Chaque propriété est un nom de plugin de base pointant vers un tableau de variantes à générer pour ce plugin. Les variantes suivantes sont prises en charge dès le départ :

'responsive'

'group-hover'

'focus-within'

'first'

'last'

'odd'

'even'

'hover'

'focus'

'active'

'visited'

'disabled'

Il est important de noter que votre tableau de variantes n'est pas fusionné avec les valeurs par défaut, donc si vous souhaitez activer une autre variante pour un utilitaire, vous devez répéter les variantes par défaut pour cet utilitaire également.

N'indiquez pas seulement les variantes supplémentaires que vous souhaitez activer :

// tailwind.config.js > nope !
module.exports = {
  variants: {
    backgroundColor: ['active'],
  },
}

Mais fournissez toujours la liste complète des variantes que vous souhaitez activer :

// tailwind.config.js
module.exports = {
  variants: {
    backgroundColor: ['responsive', 'hover', 'focus', 'active'],
  },
}

Ordonner les pseudo-classes

Il est important de noter que les variantes sont générées dans l'ordre dans lequel vous les indiquez, de sorte que les variantes à la fin de la liste auront la priorité sur les variantes au début de la liste.

Dans cet exemple, les variantes de focus ont la priorité la plus élevée pour les utilitaires backgroundColor, mais les variantes de hover ont la priorité la plus élevée pour les utilitaires borderColor :

// tailwind.config.js
module.exports = {
  variants: {
    backgroundColor: ['hover', 'focus'],
    borderColor: ['focus', 'hover'],
  },
}

Le code ci-dessus générera les CSS suivante :

.bg-black { background-color: #000 }
.bg-white { background-color: #fff }
/* ... */

.hover\:bg-black:hover { background-color: #000 }
.hover\:bg-white:hover { background-color: #fff }
/* ... */

.focus\:bg-black:focus { background-color: #000 }
.focus\:bg-white:focus { background-color: #fff }
/* ... */

.border-black { border-color: #000 }
.border-white { border-color: #fff }
/* ... */

.focus\:border-black:focus { border-color: #000 }
.focus\:border-white:focus { border-color: #fff }
/* ... */

.hover\:border-black:hover { border-color: #000 }
.hover\:border-white:hover { border-color: #fff }
/* ... */

Ces classes seront utilisées de la façon suivante dans le HTML :

<input class="focus:bg-white hover:bg-black focus:border-white hover:border-black">

...si l'input était survolée et focalisée en même temps, le fond serait blanc mais la bordure serait noire.

En général, nous recommandons l'ordre suivant pour les variantes intégrées, bien que vous soyez libre d'utiliser l'ordre qui vous semble le plus logique pour votre propre projet :

['responsive', 'group-hover', 'focus-within', 'first', 'last', 'odd', 'even', 'hover', 'focus', 'active', 'visited', 'disabled']

Les pseudo-classes pour le responsive

La variante responsive est la seule variante qui n'est pas affectée par l'ordre dans lequel vous listerez la configuration de vos variantes.

Cela est dû au fait que la variante responsive s'empile automatiquement avec des variantes des pseudo-classes, ce qui signifie que si vous spécifiez à la fois des variantes responsives et des variantes de hover pour un utilitaire, Tailwind générera également des variantes de hover réactives :

// tailwind.config.js
module.exports = {
  variants: {
    backgroundColor: ['responsive', 'hover'],
    borderColor: ['responsive', 'focus'],
  },
}

Le code ci-dessus générera le code CSS suivant :

.bg-black { background-color: #000 }
/* ... */
.hover\:bg-black:hover { background-color: #000 }
/* ... */

.border-black { border-color: #000 }
/* ... */
.focus\:border-black:focus { border-color: #000 }
/* ... */


@media (min-width: 640px) {
  .sm\:bg-black { background-color: #000 }
  /* ... */
  .sm\:hover\:bg-black:hover { background-color: #000 }
  /* ... */

  .sm\:border-black { border-color: #000 }
  /* ... */
  .sm\:focus\:border-black:focus { border-color: #000 }
  /* ... */
}

@media (min-width: 768px) {
  .md\:bg-black { background-color: #000 }
  /* ... */
  .md\:hover\:bg-black:hover { background-color: #000 }
  /* ... */

  .md\:border-black { border-color: #000 }
  /* ... */
  .md\:focus\:border-black:focus { border-color: #000 }
  /* ... */
}

@media (min-width: 1024px) {
  .lg\:bg-black { background-color: #000 }
  /* ... */
  .lg\:hover\:bg-black:hover { background-color: #000 }
  /* ... */

  .lg\:border-black { border-color: #000 }
  /* ... */
  .lg\:focus\:border-black:focus { border-color: #000 }
  /* ... */
}

@media (min-width: 1280px) {
  .xl\:bg-black { background-color: #000 }
  /* ... */
  .xl\:hover\:bg-black:hover { background-color: #000 }
  /* ... */

  .xl\:border-black { border-color: #000 }
  /* ... */
  .xl\:focus\:border-black:focus { border-color: #000 }
  /* ... */
}

Les variantes responsive sont regroupées et insérées par défaut à la fin de votre feuille de style pour éviter les problèmes de spécificité. Si vous souhaitez personnaliser ce comportement pour une raison quelconque, vous pouvez utiliser la directive @tailwind screens pour spécifier où les variantes réactives doivent être insérées.

Les pseudo-classes par défaut

Vous pouvez utiliser la variante spéciale default pour contrôler où les versions normales et non préfixées d'un utilitaire sont générées par rapport aux autres variantes.

// tailwind.config.js
module.exports = {
  variants: {
    backgroundColor: ['hover', 'default', 'focus'],
  },
}

Le code ci-dessus générera le CSS suivant :

.hover\:bg-black:hover { background-color: #000 }
.hover\:bg-white:hover { background-color: #fff }
/* ... */

.bg-black { background-color: #000 }
.bg-white { background-color: #fff }
/* ... */

.focus\:bg-black:focus { background-color: #000 }
.focus\:bg-white:focus { background-color: #fff }
/* ... */

Activer toutes les pseudo-classes

Pour spécifier un ensemble global de variantes qui doit être appliqué à toutes les classes utilitaires, vous pouvez affecter un tableau de variantes directement à la propriété des variantes :

// tailwind.config.js
module.exports  = {
  variants: ['responsive', 'group-hover', 'focus-within', 'first', 'last', 'odd', 'even', 'hover', 'focus', 'active', 'visited', 'disabled']
}

Notez que l'activation de toutes les variantes pour tous les plugins se traduira par des fichiers de taille beaucoup plus importante. Avant de procéder à cette opération, assurez-vous de lire notre guide sur le contrôle de la taille des fichiers.

Utiliser des pseudo-classes personnalisées

Si vous avez écrit ou installé un plugin qui ajoute une nouvelle variante, vous pouvez activer cette variante en l'incluant dans la configuration de vos variantes comme s'il s'agissait d'une variante intégrée.

Par exemple, le plugin tailwindcss-interaction-variants ajoute une variante visitée (entre autres) :

// tailwind.config.js
{
  variants: {
    backgroundColor: ['responsive', 'hover', 'focus', 'visited'],
  },
  plugins: [
    require('tailwindcss-interaction-variants')(),
  ],
}

Pour en savoir plus sur la création de variantes personnalisées, consultez la documentation sur les plugins de variantes.

Référence des pseudo-classes par défaut

Voici une référence complète de la configuration des pseudo-classes par défaut de Tailwind, qui peut être utile lorsque vous souhaitez ajouter une nouvelle variante tout en conservant les valeurs par défaut.

// Default configuration
module.exports = {
  // ...
  variants: {
    accessibility: ['responsive', 'focus'],
    alignContent: ['responsive'],
    alignItems: ['responsive'],
    alignSelf: ['responsive'],
    appearance: ['responsive'],
    backgroundAttachment: ['responsive'],
    backgroundColor: ['responsive', 'hover', 'focus'],
    backgroundPosition: ['responsive'],
    backgroundRepeat: ['responsive'],
    backgroundSize: ['responsive'],
    borderCollapse: ['responsive'],
    borderColor: ['responsive', 'hover', 'focus'],
    borderRadius: ['responsive'],
    borderStyle: ['responsive'],
    borderWidth: ['responsive'],
    boxShadow: ['responsive', 'hover', 'focus'],
    boxSizing: ['responsive'],
    clear: ['responsive'],
    cursor: ['responsive'],
    display: ['responsive'],
    fill: ['responsive'],
    flex: ['responsive'],
    flexDirection: ['responsive'],
    flexGrow: ['responsive'],
    flexShrink: ['responsive'],
    flexWrap: ['responsive'],
    float: ['responsive'],
    fontFamily: ['responsive'],
    fontSize: ['responsive'],
    fontSmoothing: ['responsive'],
    fontStyle: ['responsive'],
    fontWeight: ['responsive', 'hover', 'focus'],
    gap: ['responsive'],
    gridAutoFlow: ['responsive'],
    gridColumn: ['responsive'],
    gridColumnEnd: ['responsive'],
    gridColumnStart: ['responsive'],
    gridRow: ['responsive'],
    gridRowEnd: ['responsive'],
    gridRowStart: ['responsive'],
    gridTemplateColumns: ['responsive'],
    gridTemplateRows: ['responsive'],
    height: ['responsive'],
    inset: ['responsive'],
    justifyContent: ['responsive'],
    letterSpacing: ['responsive'],
    lineHeight: ['responsive'],
    listStylePosition: ['responsive'],
    listStyleType: ['responsive'],
    margin: ['responsive'],
    maxHeight: ['responsive'],
    maxWidth: ['responsive'],
    minHeight: ['responsive'],
    minWidth: ['responsive'],
    objectFit: ['responsive'],
    objectPosition: ['responsive'],
    opacity: ['responsive', 'hover', 'focus'],
    order: ['responsive'],
    outline: ['responsive', 'focus'],
    overflow: ['responsive'],
    padding: ['responsive'],
    placeholderColor: ['responsive', 'focus'],
    pointerEvents: ['responsive'],
    position: ['responsive'],
    resize: ['responsive'],
    rotate: ['responsive', 'hover', 'focus'],
    scale: ['responsive', 'hover', 'focus'],
    skew: ['responsive', 'hover', 'focus'],
    stroke: ['responsive'],
    strokeWidth: ['responsive'],
    tableLayout: ['responsive'],
    textAlign: ['responsive'],
    textColor: ['responsive', 'hover', 'focus'],
    textDecoration: ['responsive', 'hover', 'focus'],
    textTransform: ['responsive'],
    transform: ['responsive'],
    transformOrigin: ['responsive'],
    transitionDuration: ['responsive'],
    transitionProperty: ['responsive'],
    transitionTimingFunction: ['responsive'],
    translate: ['responsive', 'hover', 'focus'],
    userSelect: ['responsive'],
    verticalAlign: ['responsive'],
    visibility: ['responsive'],
    whitespace: ['responsive'],
    width: ['responsive'],
    wordBreak: ['responsive'],
    zIndex: ['responsive'],
  }
}

Ecrire un plugin

Les plugins vous permettent d'enregistrer de nouveaux styles pour que Tailwind les injecte dans la feuille de style de l'utilisateur en utilisant JavaScript au lieu de CSS.

Pour commencer avec votre premier plugin, importez la fonction plugin() de Tailwind depuis tailwindcss/plugin, et appelez-la avec une fonction anonyme comme premier argument dans la liste des plugins dans votre fichier de configuration :

// tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addUtilities, addComponents, e, prefix, config }) {
      // Ajoutez vos styles personnalisés ici ...
    }),
  ]
}

Les fonctions de plugin reçoivent un seul argument d'objet qui peut être déstructuré en plusieurs fonctions "helper" :

addUtilities(), pour l'enregistrement de nouveaux styles utilitaires.

addComponents(), pour l'enregistrement de nouveaux styles de composants.

addBase(), pour l'enregistrement de nouveaux styles de base.

addVariant(), pour l'enregistrement de variantes personnalisées.

e(), pour les chaînes de caractères d'échappement destinées à être utilisées dans les noms de classe.

prefix(), pour appliquer manuellement le préfixe configuré par l'utilisateur à des parties d'un sélecteur.

theme(), pour rechercher des valeurs dans la configuration du thème de l'utilisateur.

variants(), pour rechercher des valeurs dans la configuration des variantes de l'utilisateur.

config(), pour rechercher des valeurs dans la configuration Tailwind de l'utilisateur postcss, pour effectuer des manipulations de bas niveau avec PostCSS directement.

Pour tous les détails sur la création d'un plugin Tailwind, consultez la documentation officielle dont voici les principaux chapitres :

Ajouter des utilitaires

Ajouter des composants

Ajouter des styles de base

Echapper des noms de classes

Préfixer des selecteurs manuellement

Référencer la configuration de l'utilisateur

Exposer les options

Synthaxe CSS dans le JS

Ajouter des variants

Optimisation du fichier CSS de sortie

Quelque soit le projet sur lequel vous travaillerez, il y a de forte chance que vous n'utilisiez pas toutes les classes mises à disposition par Tailwind. Le framework entier étant relativement lourd (783.5kb non minifié), vous avez tout intérêt à optimiser le fichier de sortie du build pour votre environnement de production.

Purger les classes CSS non utilisées avec Purgecss

PurgeCSS est un utilitaire qui détecte les classes d'une feuille de styles qui ne sont pas utilisées dans vos fichiers (pages html, templates …) et les purges afin de réduire la taille de votre feuille de styles.

Le créateur de Tailwind n'exclue pas l'idée d'intégrer PurgeCSS dans Tailwind dans un futur proche donc en attendant voici la procédure pour installer et utiliser PurgeCSS.

Nous utiliserons postCSS pour intégrer purgeCSS dans notre workflow. La documentation Tailwind recommande d'activer purgeCSS uniquement pour la mise en production, le traitement via purgeCSS prenant un certain temps, cela peut vite devenir pénible en développement où vous devez builder régulièrement votre feuille de styles.

Installation de PurgeCSS

Commençons par installer le package PurgeCSS @fullhuman/postcss-purgecss à l'aide de npm ou yarn :

# avec npm
$ npm install @fullhuman/postcss-purgecss --save-dev

# avec yarn
$ yarn add @fullhuman/postcss-purgecss -D

Ensuite, installer PurgeCSS comme dernier plugin dans votre fichier de configuration postCSS postcss.config.js

// postcss.config.js
const purgecss = require('@fullhuman/postcss-purgecss')({

  // Specify the paths to all of the template files in your project 
  content: [
    './src/**/*.html',
    './src/**/*.vue',
    './src/**/*.jsx',
    // etc.
  ],

  // Include any special characters you're using in this regular expression
  defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
})

module.exports = {
  plugins: [
    require('tailwindcss'),
    require('autoprefixer'),
    ...process.env.NODE_ENV === 'production'
      ? [purgecss]
      : []
  ]
}

La documentation Tailwind recommande de n'appliquer purgeCSS que sur les classes utilitaires et non sur les composants ou les styles de bases (reset). Pour se faire, nous utiliserons la fonction whitelisting de purgeCSS.

/* purgecss: début à ignorer */
@tailwind  base;
@tailwind  components;
/* purgecss: fin à ignorer */

@tailwind  utilities;

Ecrire du HTML que l'on peut facilement purger

Purgecss utilise des "extracteurs" pour déterminer quelles chaînes de caractères de vos templates sont des classes. Dans l'exemple ci-dessous, nous utilisons un extracteur personnalisé qui trouvera toutes les classes que Tailwind génère par défaut :

const purgecss = require('@fullhuman/postcss-purgecss')({
  // ...
  defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
})

Cet extracteur personnalisé cherche simplement les chaînes de caractères qui correspondent à cette expression régulière dans l'ensemble du fichier : /[\w-:/]+(?<!:)/g

Cela signifie qu'il est important d'éviter de créer dynamiquement des chaînes de classes dans vos modèles avec une concaténation de chaînes, sinon Purgecss ne saura pas préserver ces classes.

<!-- Ne faites pas cela ... -->
<div :class="text-{{ error ? 'red' : 'green' }}-600"></div>

<!-- Faites plutôt cela ... -->
<div :class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>

Tant qu'un nom de classe apparaît dans votre template dans son intégralité, Purgecss ne le supprimera pas.

Comprendre le Regex utilisé

L'expression régulière /[\w-:/]+(?<!:)/g que Tailwind recommande comme point de départ correspond à tous les caractères non standard que Tailwind utilise par défaut, comme : et /.

Cette expression régulière utilise également un "lookbehind" pour s'assurer que si une chaîne se termine par :, le : n'est pas considéré comme faisant partie de la chaîne. Ceci afin d'assurer la compatibilité avec la syntaxe des objets de classe pris en charge par Vue et la bibliothèque Classnames pour React :

<!-- Match `hidden`, not `hidden:` -->
<div :class="{ hidden: !isOpen, ... }"><!-- ... --></div>

Il est important de noter qu'en raison de l'aspect négatif de cette regex, elle n'est compatible qu'avec le Node.js 9.11.2 et supérieur. Si vous avez besoin d'utiliser une version plus ancienne de Node.js pour construire vos actifs, vous pouvez utiliser cette expression régulière à la place :

- /[\w-/:]+(?<!:)/g
+ /[\w-/:]*[\w-/:]/g

Personnaliser le Regex

Si vous utilisez d'autres caractères spéciaux dans vos noms de classe, veillez à mettre à jour l'expression régulière pour les inclure également.

Par exemple, si vous avez personnalisé Tailwind pour créer des classes comme w-50%, vous voudrez ajouter % à l'expression régulière :

- /[\w-/:]+(?<!:)/g
+ /[\w-/:%]+(?<!:)/g

Conclusion

Le framework CSS Tailwind se différencie des autres frameworks CSS par son approche plus bas niveau qui permet une grande flexibilité dans l'élaboration de son design. Ce qui fait la force de ce framework, c'est aussi la liberté qu'il offre aux dévelopeurs et développeuses front-end pour personnaliser ou étendre le framework afin de l'adapter à leurs besoins.

Sources :

Documentation oficielle de TailwindCSS

Tailwind CSS For Absolute Beginners

Quelques ressources vidéos intéressantes :

Designing with Tailwind CSS

Introduction to Tailwind and the utility first workflow