<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tailwind CSS on kenji.blog</title><link>http://kenji.blog/fr/tags/tailwind-css/</link><description>Recent content in Tailwind CSS on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 03:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/fr/tags/tailwind-css/index.xml" rel="self" type="application/rss+xml"/><item><title>Personnalisation du thème Hugo : Comment intégrer Tailwind CSS</title><link>http://kenji.blog/fr/p/hugo-tailwind-css-customization-guide/</link><pubDate>Sun, 13 Sep 2026 03:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/hugo-tailwind-css-customization-guide/</guid><description>&lt;img src="http://kenji.blog/p/hugo-tailwind-css-customization-guide/img/eyecatch.jpg" alt="Featured image of post Personnalisation du thème Hugo : Comment intégrer Tailwind CSS" />&lt;h1 id="introduction--la-puissante-synergie-entre-le-générateur-de-site-statique-hugo-et-tailwind-css">Introduction : La puissante synergie entre le générateur de site statique Hugo et Tailwind CSS
&lt;/h1>&lt;p>Dans le développement Web front-end moderne, concilier les performances et l&amp;rsquo;expérience de développement (DX : Developer Experience) est l&amp;rsquo;une des priorités majeures de tout projet. L&amp;rsquo;association de &lt;strong>Hugo&lt;/strong>, qui possède l&amp;rsquo;une des vitesses de compilation les plus rapides au monde parmi les générateurs de sites statiques (SSG), et de &lt;strong>Tailwind CSS&lt;/strong>, qui a introduit le paradigme novateur du &amp;ldquo;utility-first&amp;rdquo; (utilitaire d&amp;rsquo;abord), constitue sans doute l&amp;rsquo;une des réponses ultimes à ce défi.&lt;/p>
&lt;p>Hugo est écrit en Go et présente des performances exceptionnelles, permettant de compiler un site de plusieurs milliers de pages en quelques secondes, voire en millisecondes. D&amp;rsquo;autre part, Tailwind CSS permet d&amp;rsquo;accélérer l&amp;rsquo;itération du design en éliminant les allers-retours entre les fichiers CSS et HTML grâce à l&amp;rsquo;écriture directe d&amp;rsquo;innombrables classes utilitaires prédéfinies (&lt;code>flex&lt;/code>, &lt;code>text-center&lt;/code>, &lt;code>mt-4&lt;/code>, etc.) dans le code HTML.&lt;/p>
&lt;p>Cet article explique de manière approfondie et détaillée comment intégrer Tailwind CSS à un thème Hugo, et comment construire un pipeline d&amp;rsquo;assets avancé (Hugo Pipes) en utilisant PostCSS, depuis les bases de l&amp;rsquo;architecture jusqu&amp;rsquo;à l&amp;rsquo;optimisation mathématique des performances.&lt;/p>
&lt;hr>
&lt;h2 id="1-lévolution-du-css-utility-first-et-lapproche-orientée-composants">1. L&amp;rsquo;évolution du CSS &amp;ldquo;utility-first&amp;rdquo; et l&amp;rsquo;approche orientée composants
&lt;/h2>&lt;p>Avant de passer aux instructions d&amp;rsquo;intégration de Tailwind CSS, il est très utile de comprendre pourquoi nous devrions utiliser Tailwind CSS, ainsi que l&amp;rsquo;histoire et l&amp;rsquo;évolution de la philosophie de conception CSS qui se cache derrière.&lt;/p>
&lt;h3 id="les-limites-de-la-conception-css-traditionnelle-bem-et-oocss">Les limites de la conception CSS traditionnelle (BEM et OOCSS)
&lt;/h3>&lt;p>Autrefois dans le développement Web, l&amp;rsquo;utilisation de noms de classes sémantiques était considérée comme la meilleure pratique. Par exemple, pour créer un composant de carte, le code HTML et le CSS étaient séparés comme suit :&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;card&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">img&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;card__image&amp;#34;&lt;/span> &lt;span class="na">src&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;image.jpg&amp;#34;&lt;/span> &lt;span class="na">alt&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;thumbnail&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;card__content&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">h2&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;card__title&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>Titre&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">h2&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;card__description&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>La description va ici.&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="cl">&lt;span class="p">.&lt;/span>&lt;span class="nc">card&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">border-radius&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="kt">px&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">box-shadow&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="kt">px&lt;/span> &lt;span class="mi">6&lt;/span>&lt;span class="kt">px&lt;/span> &lt;span class="nb">rgba&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mf">0.1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">background-color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#ffffff&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">overflow&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">hidden&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">.&lt;/span>&lt;span class="nc">card__title&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">font-size&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">1.5&lt;/span>&lt;span class="kt">rem&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">font-weight&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">bold&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#333333&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* La suite contient d&amp;#39;autres styles détaillés */&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Une conception basée sur BEM (Block Element Modifier) comme celle-ci fonctionne bien lorsque le projet est de petite taille, mais a tendance à causer les problèmes suivants :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Épuisement et fatigue liés au nommage&lt;/strong> : À chaque fois que vous créez un composant similaire, vous devez penser à un nouveau nom de classe (ex. &lt;code>card-news&lt;/code>, &lt;code>card-featured&lt;/code>, etc.).&lt;/li>
&lt;li>&lt;strong>Gonflement du CSS&lt;/strong> : Le nombre de lignes de CSS augmente à chaque ajout de fonctionnalité. Le CSS existant est rarement supprimé par peur de ne pas savoir &amp;ldquo;où il est utilisé&amp;rdquo;, ce qui conduit à l&amp;rsquo;accumulation de code mort.&lt;/li>
&lt;li>&lt;strong>Changement de contexte&lt;/strong> : Puisque la structure HTML et les styles CSS sont gérés dans des fichiers séparés, le nombre d&amp;rsquo;allers-retours entre les onglets dans l&amp;rsquo;éditeur augmente de manière exponentielle.&lt;/li>
&lt;/ol>
&lt;h3 id="le-changement-de-paradigme-avec-tailwind-css">Le changement de paradigme avec Tailwind CSS
&lt;/h3>&lt;p>Tailwind CSS résout ces problèmes en utilisant l&amp;rsquo;approche de la &amp;ldquo;combinaison de classes utilitaires&amp;rdquo;. Le composant de carte ci-dessus ressemblerait à ceci si vous utilisiez Tailwind CSS :&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;rounded-lg shadow-md bg-white overflow-hidden&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">img&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;w-full h-48 object-cover&amp;#34;&lt;/span> &lt;span class="na">src&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;image.jpg&amp;#34;&lt;/span> &lt;span class="na">alt&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;thumbnail&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;p-6&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">h2&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;text-2xl font-bold text-gray-800&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>Titre&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">h2&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;mt-2 text-gray-600&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>La description va ici.&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Étant donné que les noms de classe eux-mêmes représentent des valeurs de style spécifiques (&lt;code>p-6&lt;/code> équivaut à &lt;code>padding: 1.5rem;&lt;/code>, etc.), vous pouvez prévoir le résultat final du rendu simplement en regardant le HTML. De plus, le compilateur JIT (Just-In-Time) de Tailwind extrait uniquement les classes réellement utilisées dans le fichier CSS de production, ce qui réduit considérablement la taille du fichier CSS.&lt;/p>
&lt;hr>
&lt;h2 id="2-larchitecture-de-hugo-pipes-et-postcss">2. L&amp;rsquo;architecture de Hugo Pipes et PostCSS
&lt;/h2>&lt;p>Pour intégrer Tailwind CSS dans Hugo, il est nécessaire de comprendre le pipeline de traitement des assets appelé &lt;strong>Hugo Pipes&lt;/strong>. Hugo Pipes est une fonctionnalité puissante qui permet de gérer tous les traitements liés aux assets directement dans Hugo, comme la compilation de Sass/SCSS, le bundle et la minification JavaScript, et l&amp;rsquo;exécution de &lt;strong>PostCSS&lt;/strong> que nous utiliserons ici.&lt;/p>
&lt;p>PostCSS est un outil permettant de transformer le CSS à l&amp;rsquo;aide de plugins JavaScript. Tailwind CSS lui-même fonctionne en réalité comme un plugin PostCSS.&lt;/p>
&lt;h3 id="le-mécanisme-de-transformation-ast-abstract-syntax-tree-avec-postcss">Le mécanisme de transformation AST (Abstract Syntax Tree) avec PostCSS
&lt;/h3>&lt;p>Comprendre comment PostCSS traite le CSS est extrêmement utile lors de la résolution de problèmes. Le diagramme Mermaid ci-dessous montre le pipeline par lequel PostCSS lit un fichier CSS, le transforme via des plugins et produit le CSS final.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;CSS brut (styles.css)&amp;#34;] --&amp;gt;|Parseur| B[&amp;#34;AST (Arbre de syntaxe abstraite)&amp;#34;]
B --&amp;gt; C[&amp;#34;Plugin 1 : Tailwind CSS&amp;#34;]
C --&amp;gt; D[&amp;#34;Plugin 2 : Autoprefixer&amp;#34;]
D --&amp;gt; E[&amp;#34;Plugin N : cssnano&amp;#34;]
E --&amp;gt;|Stringifier| F[&amp;#34;CSS compilé et optimisé&amp;#34;]
&lt;/pre>
&lt;ol>
&lt;li>&lt;strong>Parseur&lt;/strong> : Analyse la chaîne CSS brute en entrée et la convertit en AST (Arbre de syntaxe abstraite), une structure de données manipulable par le programme.&lt;/li>
&lt;li>&lt;strong>Plugins&lt;/strong> :
&lt;ul>
&lt;li>&lt;strong>Tailwind CSS&lt;/strong> : Analyse les fichiers de modèle (HTML ou Markdown) et ajoute les classes utilitaires utilisées sous forme de nœuds à l&amp;rsquo;AST. Il développe également les directives &lt;code>@tailwind&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Autoprefixer&lt;/strong> : Consulte la base de données &lt;code>Can I Use&lt;/code> et ajoute les préfixes vendeurs nécessaires (&lt;code>-webkit-&lt;/code>, &lt;code>-moz-&lt;/code>, etc.) aux propriétés de l&amp;rsquo;AST.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Stringifier&lt;/strong> : Convertit l&amp;rsquo;AST transformé en une chaîne CSS compréhensible par le navigateur pour sa sortie.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="3-configuration-de-lenvironnement-et-prérequis">3. Configuration de l&amp;rsquo;environnement et prérequis
&lt;/h2>&lt;p>Passons maintenant aux étapes d&amp;rsquo;intégration concrètes. Tout d&amp;rsquo;abord, nous vérifierons si les logiciels nécessaires sont installés.&lt;/p>
&lt;h3 id="prérequis">Prérequis
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>Hugo Extended Version&lt;/strong> :
Vous avez besoin de la &lt;strong>version Extended&lt;/strong> de Hugo, et non de la version standard, car elle inclut des fonctionnalités de traitement Sass/SCSS et une intégration native de PostCSS. Exécutez la commande suivante dans le terminal et assurez-vous que la chaîne &lt;code>extended&lt;/code> est présente dans les informations de version.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">hugo version
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Sortie attendue :&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># hugo v0.121.2-4146... windows/amd64 BuildDate=... VendorInfo=gohugoio +extended&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>Node.js et npm&lt;/strong> :
Les dépendances comme Tailwind CSS et PostCSS fonctionnent sur Node.js. Assurez-vous que Node.js (version LTS recommandée) est installé.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">node -v
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">npm -v
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;/ol>
&lt;h3 id="installation-des-paquets-npm">Installation des paquets npm
&lt;/h3>&lt;p>Initialisez npm dans le répertoire racine de votre projet (là où se trouve le fichier de configuration de Hugo &lt;code>hugo.toml&lt;/code>) et installez les paquets nécessaires.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Génération de package.json&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">npm init -y
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Installation de Tailwind CSS, PostCSS et Autoprefixer en tant que dépendances de développement&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">npm install -D tailwindcss postcss postcss-cli autoprefixer
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;blockquote>
&lt;p>[!IMPORTANT]
Si &lt;code>postcss-cli&lt;/code> n&amp;rsquo;est pas installé, une erreur peut survenir lorsque Hugo appelle PostCSS en interne. Assurez-vous de l&amp;rsquo;installer car Hugo Pipes utilise &lt;code>postcss-cli&lt;/code> en interne.&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="4-création-des-fichiers-de-configuration-postcss--tailwind-css">4. Création des fichiers de configuration (PostCSS &amp;amp; Tailwind CSS)
&lt;/h2>&lt;p>Une fois l&amp;rsquo;installation des paquets terminée, créez deux fichiers de configuration importants qui contrôlent le comportement du projet. Placez-les dans le répertoire racine du projet.&lt;/p>
&lt;h3 id="création-de-tailwindconfigjs">Création de tailwind.config.js
&lt;/h3>&lt;p>Exécutez la commande suivante dans le terminal pour générer le fichier de configuration par défaut.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">npx tailwindcss init
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ouvrez le fichier &lt;code>tailwind.config.js&lt;/code> généré dans votre éditeur et configurez la propriété &lt;code>content&lt;/code>. C&amp;rsquo;est une étape très importante. Tailwind analyse les fichiers aux chemins spécifiés ici et extrait les classes utilisées. Spécifiez précisément les fichiers de disposition (layouts) et de contenu en fonction de la structure du projet Hugo.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="cm">/** @type {import(&amp;#39;tailwindcss&amp;#39;).Config} */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">exports&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Spécifie les cibles d&amp;#39;analyse en fonction de la structure du répertoire Hugo
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">content&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;./content/**/*.md&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;./content/**/*.html&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;./layouts/**/*.html&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;./assets/**/*.js&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Si vous utilisez un thème, vous devez également inclure le répertoire du thème
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// &amp;#34;./themes/mon-theme/layouts/**/*.html&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">theme&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">extend&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Les extensions de couleurs personnalisées ou de polices se font ici
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">colors&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;brand-primary&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;#3490dc&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;brand-secondary&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;#ffed4a&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">fontFamily&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;sans&amp;#39;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;Helvetica Neue&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Arial&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Hiragino Kaku Gothic ProN&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Meiryo&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;sans-serif&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">plugins&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Ajoutez des plugins officiels si nécessaire (ex. plugin Typography)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// require(&amp;#39;@tailwindcss/typography&amp;#39;),
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="création-de-postcssconfigjs">Création de postcss.config.js
&lt;/h3>&lt;p>Ensuite, créez &lt;code>postcss.config.js&lt;/code> à la racine du projet pour définir quels plugins PostCSS exécuter et dans quel ordre.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">exports&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">plugins&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">tailwindcss&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">autoprefixer&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Avec cette configuration, lorsque Hugo appellera PostCSS, le traitement de Tailwind CSS sera effectué en premier, suivi de l&amp;rsquo;ajout des préfixes vendeurs par Autoprefixer.&lt;/p>
&lt;hr>
&lt;h2 id="5-construction-du-pipeline-dassets-css-dans-hugo">5. Construction du pipeline d&amp;rsquo;assets CSS dans Hugo
&lt;/h2>&lt;p>Une fois la configuration terminée, nous allons enfin intégrer Tailwind CSS dans le thème Hugo.&lt;/p>
&lt;h3 id="5-1-création-du-fichier-css-point-dentrée">5-1. Création du fichier CSS point d&amp;rsquo;entrée
&lt;/h3>&lt;p>Créez un fichier CSS qui servira de point d&amp;rsquo;entrée dans le répertoire &lt;code>assets/css/&lt;/code> (créez-le s&amp;rsquo;il n&amp;rsquo;existe pas). Nous le nommerons &lt;code>main.css&lt;/code>.&lt;/p>
&lt;p>&lt;strong>Chemin du fichier : &lt;code>assets/css/main.css&lt;/code>&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* Chargement des styles de base de Tailwind (CSS reset, etc.) */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">@&lt;/span>&lt;span class="k">tailwind&lt;/span> &lt;span class="nt">base&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* Chargement des classes de composants */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">@&lt;/span>&lt;span class="k">tailwind&lt;/span> &lt;span class="nt">components&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* Chargement des classes utilitaires */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">@&lt;/span>&lt;span class="k">tailwind&lt;/span> &lt;span class="nt">utilities&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* Vous pouvez ajouter votre propre CSS personnalisé ici si nécessaire,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"> mais il est recommandé d&amp;#39;utiliser extend de tailwind.config.js autant que possible */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">@&lt;/span>&lt;span class="k">layer&lt;/span> &lt;span class="nt">components&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">.&lt;/span>&lt;span class="nc">btn-primary&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">@apply&lt;/span> &lt;span class="err">bg-blue-500&lt;/span> &lt;span class="n">hover&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="n">bg-blue-700&lt;/span> &lt;span class="kc">text&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="kc">white&lt;/span> &lt;span class="k">font&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="kc">bold&lt;/span> &lt;span class="n">py-2&lt;/span> &lt;span class="n">px-4&lt;/span> &lt;span class="n">rounded&lt;/span> &lt;span class="k">transition&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">colors&lt;/span> &lt;span class="n">duration-300&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="5-2-modification-du-fichier-de-disposition-headhtml">5-2. Modification du fichier de disposition (head.html)
&lt;/h3>&lt;p>Ensuite, nous allons écrire le pipeline pour charger le fichier CSS ci-dessus depuis un modèle Hugo et le traiter avec PostCSS. Généralement, vous modifierez le modèle partiel qui définit la balise &lt;code>&amp;lt;head&amp;gt;&lt;/code> (par exemple, &lt;code>layouts/partials/head.html&lt;/code>).&lt;/p>
&lt;p>&lt;strong>Chemin du fichier : &lt;code>layouts/partials/head.html&lt;/code>&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go-html-template" data-lang="go-html-template">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">head&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">charset&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;utf-8&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;viewport&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;width=device-width, initial-scale=1&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>&lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="na">.Title&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span> | &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="na">.Site.Title&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- Récupère assets/css/main.css --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">:=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">resources&lt;/span>&lt;span class="na">.Get&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;css/main.css&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- Définition des options pour PostCSS --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$options&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">:=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">dict&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;inlineImports&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">true&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">|&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">resources&lt;/span>&lt;span class="na">.PostCSS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$options&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- Pipeline d&amp;#39;optimisation des assets pour l&amp;#39;environnement de production --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">if&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">hugo&lt;/span>&lt;span class="na">.IsProduction&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- 1. Minification (compression) --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">|&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">minify&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- 2. Fingerprint (ajout de hachage pour le contournement du cache) --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">|&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">fingerprint&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;sha512&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- 3. Sortie de la balise avec SRI (Subresource Integrity) --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">link&lt;/span> &lt;span class="na">rel&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;stylesheet&amp;#34;&lt;/span> &lt;span class="na">href&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="na">.RelPermalink&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span> &lt;span class="na">integrity&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="na">.Data.Integrity&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span> &lt;span class="na">crossorigin&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;anonymous&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">else&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- Dans l&amp;#39;environnement de développement, sortie sans compression (priorité à la vitesse de build) --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">link&lt;/span> &lt;span class="na">rel&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;stylesheet&amp;#34;&lt;/span> &lt;span class="na">href&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nx">$css&lt;/span>&lt;span class="na">.RelPermalink&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">end&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">head&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="explication-du-pipeline-et-diagramme-mermaid">Explication du pipeline et diagramme Mermaid
&lt;/h4>&lt;p>Illustrons la série d&amp;rsquo;étapes de traitement que le code modèle Go ci-dessus effectue sur le fichier CSS.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;assets/css/main.css&amp;#34;] --&amp;gt;|resources.Get| B[&amp;#34;Espace mémoire de Hugo&amp;#34;]
B --&amp;gt;|resources.PostCSS| C[&amp;#34;Processus PostCSS + Tailwind JIT&amp;#34;]
C --&amp;gt; D{&amp;#34;hugo.IsProduction ?&amp;#34;}
D -- &amp;#34;Oui (Environnement de production)&amp;#34; --&amp;gt; E[&amp;#34;minify (Suppression des espaces et sauts de ligne)&amp;#34;]
E --&amp;gt; F[&amp;#34;fingerprint (Calcul de hachage)&amp;#34;]
F --&amp;gt; G[&amp;#34;public/css/main.[hash].css (Avec SRI)&amp;#34;]
D -- &amp;#34;Non (Environnement de développement)&amp;#34; --&amp;gt; H[&amp;#34;public/css/main.css&amp;#34;]
&lt;/pre>
&lt;ol>
&lt;li>&lt;strong>&lt;code>resources.Get&lt;/code>&lt;/strong> : Recherche le fichier spécifié dans le répertoire &lt;code>assets&lt;/code> et le charge en tant qu&amp;rsquo;objet ressource en mémoire.&lt;/li>
&lt;li>&lt;strong>&lt;code>resources.PostCSS&lt;/code>&lt;/strong> : Applique le traitement de Tailwind CSS et Autoprefixer au code source CSS en se référant à &lt;code>postcss.config.js&lt;/code> à la racine du projet. En environnement de développement (&lt;code>hugo server&lt;/code>), le mode JIT est activé, générant rapidement uniquement les classes nécessaires lors de la modification des fichiers.&lt;/li>
&lt;li>&lt;strong>&lt;code>minify&lt;/code>&lt;/strong> : Supprime les espaces blancs et les commentaires inutiles pour minimiser la taille du fichier lors de la compilation pour l&amp;rsquo;environnement de production (ex. &lt;code>hugo --environment production&lt;/code>).&lt;/li>
&lt;li>&lt;strong>&lt;code>fingerprint&lt;/code>&lt;/strong> : Calcule un hachage SHA basé sur le contenu du fichier et l&amp;rsquo;ajoute au nom du fichier (ex. &lt;code>main.ab12cd...css&lt;/code>). Cela permet de réaliser un &amp;ldquo;cache busting&amp;rdquo; (contournement du cache), s&amp;rsquo;assurant que le nouveau fichier est chargé lors d&amp;rsquo;une mise à jour du CSS, tout en utilisant le puissant cache du navigateur.&lt;/li>
&lt;li>&lt;strong>&lt;code>integrity&lt;/code>&lt;/strong> : Utilise la valeur de hachage calculée par le Fingerprint pour générer un attribut SRI afin de prévenir toute falsification depuis un CDN ou autre.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="6-analyse-mathématique-des-performances-dans-loptimisation-css">6. Analyse mathématique des performances dans l&amp;rsquo;optimisation CSS
&lt;/h2>&lt;p>L&amp;rsquo;un des plus grands avantages de l&amp;rsquo;adoption de Tailwind CSS est la minimisation extrême de la taille du fichier CSS distribué. Analysons quantitativement l&amp;rsquo;impact de cela sur les performances Web (en particulier le First Contentful Paint : FCP) à l&amp;rsquo;aide de modèles mathématiques.&lt;/p>
&lt;h3 id="modèle-de-réduction-de-la-taille-des-fichiers-css">Modèle de réduction de la taille des fichiers CSS
&lt;/h3>&lt;p>Avec les frameworks CSS traditionnels (comme Bootstrap), tous les styles, même ceux qui ne sont pas utilisés, sont chargés, ce qui tend à augmenter la taille du fichier $S_{original}$ (environ 150 Ko à 200 Ko).
En supposant que $S_{purged}$ soit la taille après application du processus de purge (Purge) des classes inutilisées par le compilateur JIT de Tailwind CSS, et $R_{purge}$ le taux de réduction, on peut l&amp;rsquo;exprimer comme suit :&lt;/p>
$$
S_{purged} = S_{original} \times (1 - R_{purge})
$$&lt;p>Dans un projet typique, $R_{purge}$ atteint près de $0.9$ (réduction de 90%), et $S_{purged}$ se limite à seulement 10 Ko - 20 Ko environ.&lt;/p>
&lt;p>De plus, lors de la distribution, le serveur compresse les fichiers avec Brotli ou Gzip. Si le taux de compression est $R_{compress}$ (généralement autour de 0.7 - 0.8), la taille finale de la charge utile transmise sur le réseau, $S_{final}$, est calculée par la formule suivante :&lt;/p>
$$
S_{final} = S_{purged} \times (1 - R_{compress})
$$&lt;h3 id="chemin-de-rendu-critique-et-latence-du-réseau">Chemin de rendu critique et latence du réseau
&lt;/h3>&lt;p>Le temps nécessaire au navigateur pour afficher le premier contenu à l&amp;rsquo;écran (FCP) peut être approximé par la somme du temps de téléchargement HTML, du temps de téléchargement CSS et du temps de rendu.&lt;/p>
$$
T_{FCP} \approx RTT + \frac{S_{HTML}}{BW} + RTT + \frac{S_{final}}{BW} + T_{render}
$$&lt;p>Ici,&lt;/p>
&lt;ul>
&lt;li>$RTT$ : Round Trip Time (Temps de latence aller-retour avec le serveur)&lt;/li>
&lt;li>$BW$ : Bande passante du réseau (Bandwidth)&lt;/li>
&lt;/ul>
&lt;p>Dans les environnements où $BW$ est faible et $RTT$ est important (latence élevée) comme les réseaux mobiles, l&amp;rsquo;approche de Tailwind CSS qui réduit $S_{final}$ à quelques kilo-octets permet de rapprocher le terme $\frac{S_{final}}{BW}$ au plus près de zéro, ce qui est le moteur des scores spectaculaires obtenus (Google PageSpeed Insights, etc.).&lt;/p>
&lt;hr>
&lt;h2 id="7-démarrage-du-serveur-de-développement-et-vérification-du-hot-reload">7. Démarrage du serveur de développement et vérification du Hot Reload
&lt;/h2>&lt;p>Une fois toute la configuration terminée, démarrez le serveur de développement Hugo pour vérifier que Tailwind CSS fonctionne correctement.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">hugo server -D
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Accédez à &lt;code>http://localhost:1313/&lt;/code> dans votre navigateur et vérifiez que le site s&amp;rsquo;affiche.
Ouvrez un fichier de contenu Markdown ou un modèle Hugo (les fichiers sous &lt;code>layouts/&lt;/code>) et essayez d&amp;rsquo;ajouter une classe.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Exemple d&amp;#39;application de classes Tailwind pour un test --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;bg-gradient-to-r from-blue-500 to-purple-600 text-white p-8 rounded-xl shadow-2xl text-center transform transition duration-500 hover:scale-105&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">h1&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;text-4xl font-extrabold tracking-tight&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>Tailwind CSS + Hugo est génial !&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">h1&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;mt-4 text-lg font-medium&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>Vérifiez que le rechargement à chaud (hot reload) s&amp;#39;applique instantanément.&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Au moment où vous sauvegardez le fichier, le puissant observateur de fichiers de Hugo coopère avec le compilateur JIT de Tailwind pour reconstruire le CSS en quelques millisecondes, et vous devriez ressentir le plaisir de voir votre navigateur se recharger automatiquement (hot reload).&lt;/p>
&lt;h3 id="dépannage--si-les-styles-ne-sappliquent-pas">Dépannage : Si les styles ne s&amp;rsquo;appliquent pas
&lt;/h3>&lt;p>Si les modifications ne s&amp;rsquo;appliquent pas, vérifiez les points suivants :&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Paramétrage du chemin &lt;code>content&lt;/code> dans &lt;code>tailwind.config.js&lt;/code>&lt;/strong>
Si le chemin des fichiers à analyser est incorrect, Tailwind ne pourra pas détecter les classes utilisées dans ces fichiers et ne les inclura pas dans le CSS en sortie. Surtout si vous utilisez un thème, assurez-vous de ne pas avoir oublié d&amp;rsquo;inclure le chemin du répertoire du thème.&lt;/li>
&lt;li>&lt;strong>Erreurs PostCSS&lt;/strong>
Si une erreur telle que &lt;code>Error: failed to transform resource: PostCSS not found&lt;/code> s&amp;rsquo;affiche dans les journaux du serveur Hugo du terminal, il est probable que &lt;code>npm install&lt;/code> ne se soit pas exécuté correctement ou que &lt;code>postcss-cli&lt;/code> soit manquant.&lt;/li>
&lt;li>&lt;strong>Effacer le cache Hugo&lt;/strong>
Dans de rares cas, l&amp;rsquo;ancien CSS peut persister à cause du cache de Hugo. Arrêtez le serveur, démarrez-le avec &lt;code>hugo server --ignoreCache&lt;/code>, ou essayez de supprimer le répertoire temporaire du système d&amp;rsquo;exploitation (comme &lt;code>/tmp/hugo_cache/&lt;/code>).&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="8-build-pour-lenvironnement-de-production-et-améliorations-avancées">8. Build pour l&amp;rsquo;environnement de production et améliorations avancées
&lt;/h2>&lt;p>Lors du déploiement de votre site sur un serveur de production (Netlify, Vercel, GitHub Pages, Cloudflare Pages, etc.), vous devez définir les variables d&amp;rsquo;environnement et exécuter le pipeline d&amp;rsquo;optimisation pour la production.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Exemple de commande de build pour la production&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">NODE_ENV&lt;/span>&lt;span class="o">=&lt;/span>production hugo --minify --environment production
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>L&amp;rsquo;ajout de l&amp;rsquo;indicateur &lt;code>--environment production&lt;/code> exécute le bloc &lt;code>{{ if hugo.IsProduction }}&lt;/code> dans &lt;code>head.html&lt;/code>, déclenchant la minification CSS et l&amp;rsquo;ajout du Fingerprint.&lt;/p>
&lt;h3 id="stylisation-du-markdown-avec-le-plugin-typography">Stylisation du Markdown avec le plugin Typography
&lt;/h3>&lt;p>Dans les sites de blogs et de documentation comme ceux créés avec Hugo, vous ne pouvez pas ajouter directement des classes aux éléments HTML purs (tels que &lt;code>&amp;lt;h1&amp;gt;&lt;/code>, &lt;code>&amp;lt;p&amp;gt;&lt;/code>, &lt;code>&amp;lt;ul&amp;gt;&lt;/code>) générés à partir du Markdown. Le &lt;strong>plugin Typography&lt;/strong> officiel de Tailwind est extrêmement utile dans de tels cas.&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Installation du plugin&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">npm install -D @tailwindcss/typography
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>
&lt;p>Ajout à &lt;code>tailwind.config.js&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">exports&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">plugins&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;@tailwindcss/typography&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>
&lt;p>Application dans le modèle
Il suffit d&amp;rsquo;ajouter la classe &lt;code>prose&lt;/code> (et des variantes de couleur et de taille selon vos préférences) à l&amp;rsquo;élément conteneur qui affiche le corps de l&amp;rsquo;article pour appliquer de magnifiques styles par défaut.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-go-html-template" data-lang="go-html-template">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">article&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;prose prose-lg prose-blue mx-auto mt-10&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cp">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="na">.Content&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="cp">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">article&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>Grâce à cela, il n&amp;rsquo;est plus du tout nécessaire d&amp;rsquo;écrire des sélecteurs CSS complexes à la main (&lt;code>.article-content h2 { ... }&lt;/code>), et la modularité des composants est parfaitement préservée.&lt;/p>
&lt;hr>
&lt;h2 id="9-conclusion--la-réalisation-dun-écosystème-front-end-hautement-maintenable">9. Conclusion : La réalisation d&amp;rsquo;un écosystème front-end hautement maintenable
&lt;/h2>&lt;p>Félicitations. Vous disposez maintenant d&amp;rsquo;un pipeline d&amp;rsquo;assets de développement Web parfait, combinant le moteur de génération de site statique ultra-rapide de Hugo, les capacités de stylisation modernes de Tailwind CSS et l&amp;rsquo;extensibilité de PostCSS.&lt;/p>
&lt;p>Le point fort de cette architecture est que &lt;strong>&amp;ldquo;la configuration ne se fait qu&amp;rsquo;une seule fois&amp;rdquo;&lt;/strong>. Une fois le pipeline construit, les développeurs peuvent créer des interfaces utilisateur complexes à une vitesse fulgurante en ajoutant simplement des classes utilitaires intuitives aux modèles HTML ou Markdown, sans avoir à ouvrir le moindre fichier CSS.&lt;/p>
&lt;p>De plus, étant donné que la taille du CSS généré est toujours minimisée, cela contribue directement à l&amp;rsquo;amélioration des scores Core Web Vitals, ce qui est extrêmement avantageux du point de vue du SEO.&lt;/p>
&lt;p>La combinaison de Hugo et Tailwind CSS restera sans doute l&amp;rsquo;une des &amp;ldquo;meilleures options&amp;rdquo; pour tout projet, des blogs techniques personnels aux sites d&amp;rsquo;entreprise à grande échelle. N&amp;rsquo;hésitez pas à tirer parti de cette chaîne d&amp;rsquo;outils puissante pour profiter d&amp;rsquo;une expérience de développement Web confortable !&lt;/p></description></item><item><title>Points clés de la conception CSS pour la prise en charge du mode sombre sur les blogs</title><link>http://kenji.blog/fr/p/dark-mode-css-design-patterns/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/dark-mode-css-design-patterns/</guid><description>&lt;img src="http://kenji.blog/p/dark-mode-css-design-patterns/img/eyecatch.jpg" alt="Featured image of post Points clés de la conception CSS pour la prise en charge du mode sombre sur les blogs" />&lt;p>Dans le développement web moderne, la prise en charge du mode sombre (Dark Mode) n&amp;rsquo;est plus une simple « fonctionnalité intéressante à avoir » (Nice to have), mais est devenue une « exigence essentielle » (Must have) pour améliorer l&amp;rsquo;expérience utilisateur (UX). Surtout pour les médias tels que les blogs et les sites de documentation, qui impliquent de longues périodes de lecture de texte, la prise en charge du mode sombre est extrêmement importante car elle réduit la fatigue oculaire des utilisateurs et diminue la consommation de batterie des appareils.&lt;/p>
&lt;p>Dans cet article, nous explorerons en profondeur, du point de vue d&amp;rsquo;un ingénieur front-end, les défis techniques inévitables liés à l&amp;rsquo;intégration du mode sombre sur un blog, ainsi que les points clés d&amp;rsquo;une conception CSS hautement maintenable. Nous couvrirons tout ce qu&amp;rsquo;il faut savoir sur l&amp;rsquo;implémentation du mode sombre : l&amp;rsquo;utilisation des CSS Custom Properties (variables CSS), les contrôles JavaScript avancés et la collaboration SSR pour prévenir le FOUC (Flash of Unstyled Content), la conception des couleurs (RGB, HSL, et le plus récent OKLCH) pour assurer l&amp;rsquo;accessibilité (WCAG 2.1 AAA), et même des exemples de code pratiques utilisant Tailwind CSS.&lt;/p>
&lt;hr>
&lt;h2 id="1-bases-de-la-conception-de-thèmes-avec-les-css-custom-properties-variables-css">1. Bases de la conception de thèmes avec les CSS Custom Properties (variables CSS)
&lt;/h2>&lt;p>Actuellement, l&amp;rsquo;approche la plus standard et la plus puissante pour implémenter le mode sombre est l&amp;rsquo;utilisation des &lt;strong>CSS Custom Properties (variables CSS)&lt;/strong>. Contrairement aux variables des préprocesseurs CSS comme Sass (&lt;code>$color&lt;/code>) qui sont résolues de manière statique lors de la compilation, les variables CSS sont résolues et écrasées dynamiquement à l&amp;rsquo;exécution par le navigateur. Cela permet de modifier instantanément la palette de couleurs de l&amp;rsquo;ensemble de la page simplement en changeant de classe via JavaScript.&lt;/p>
&lt;h3 id="11-définition-dun-thème-de-couleurs-de-base">1.1 Définition d&amp;rsquo;un thème de couleurs de base
&lt;/h3>&lt;p>Tout d&amp;rsquo;abord, nous définissons la palette de couleurs du mode clair (par défaut) en utilisant la pseudo-classe &lt;code>:root&lt;/code>. Ensuite, le modèle de conception classique consiste à écraser ces variables lorsqu&amp;rsquo;un attribut tel que &lt;code>[data-theme='dark']&lt;/code> (ou la classe &lt;code>.dark&lt;/code>) est ajouté.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* Définition des variables pour le mode clair (par défaut) */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">:&lt;/span>&lt;span class="nd">root&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-bg-primary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#ffffff&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-bg-secondary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#f3f4f6&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-text-primary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#111827&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-text-secondary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#4b5563&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-accent&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#3b82f6&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-border&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#e5e7eb&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* Écrasement des variables en mode sombre */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;dark&amp;#39;&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-bg-primary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#111827&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-bg-secondary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#1f2937&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-text-primary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#f9fafb&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-text-secondary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#9ca3af&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-accent&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#60a5fa&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-border&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#374151&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* Application pratique */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">body&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">background-color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">var&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="kc">color&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">bg&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">primary&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">var&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="kc">color&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="kc">text&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">primary&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">transition&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">background-color&lt;/span> &lt;span class="mf">0.3&lt;/span>&lt;span class="kt">s&lt;/span> &lt;span class="kc">ease&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">color&lt;/span> &lt;span class="mf">0.3&lt;/span>&lt;span class="kt">s&lt;/span> &lt;span class="kc">ease&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">a&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">var&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="kc">color&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">accent&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>De cette façon, en séparant complètement la spécification de la disposition et de la typographie de celle de la couleur (thème), la maintenabilité du CSS est considérablement améliorée.&lt;/p>
&lt;h3 id="12-utilisation-de-media-prefers-color-scheme-dark">1.2 Utilisation de @media (prefers-color-scheme: dark)
&lt;/h3>&lt;p>Si le mode sombre est configuré au niveau du système d&amp;rsquo;exploitation (OS), il est souhaitable du point de vue de l&amp;rsquo;UX d&amp;rsquo;appliquer automatiquement le thème sombre dès la première visite de l&amp;rsquo;utilisateur sur le site Web. Cela est rendu possible par la requête multimédia (media query) &lt;code>@media (prefers-color-scheme: dark)&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* Solution de repli lorsque le mode sombre est configuré dans l&amp;#39;OS */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">@&lt;/span>&lt;span class="k">media&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="nt">prefers-color-scheme&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nt">dark&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">:&lt;/span>&lt;span class="nd">root&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="nd">not&lt;/span>&lt;span class="o">([&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;light&amp;#39;&lt;/span>&lt;span class="o">])&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-bg-primary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#111827&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-bg-secondary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#1f2937&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-text-primary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#f9fafb&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-text-secondary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#9ca3af&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-accent&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#60a5fa&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-border&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#374151&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Avec cette syntaxe, à moins que l&amp;rsquo;utilisateur n&amp;rsquo;ait explicitement sélectionné le mode clair (&lt;code>data-theme='light'&lt;/code>), le paramètre du mode sombre de l&amp;rsquo;OS est respecté et les variables sont écrasées.&lt;/p>
&lt;hr>
&lt;h2 id="2-comprendre-les-espaces-colorimétriques-et-laccessibilité-wcag-21-aaa">2. Comprendre les espaces colorimétriques et l&amp;rsquo;accessibilité (WCAG 2.1 AAA)
&lt;/h2>&lt;p>Dans la conception des couleurs du mode sombre, il ne suffit pas de simplement « rendre le fond noir et le texte blanc ». Si le contraste est trop fort, cela peut provoquer un effet de halo, rendant la lecture difficile ; à l&amp;rsquo;inverse, si le contraste est trop faible, la visibilité en pâtit. Dans les directives pour l&amp;rsquo;accessibilité des contenus Web (WCAG - Web Content Accessibility Guidelines), les ratios de contraste pour assurer la visibilité sont strictement définis.&lt;/p>
&lt;h3 id="21-formule-de-calcul-du-ratio-de-contraste-des-wcag">2.1 Formule de calcul du ratio de contraste des WCAG
&lt;/h3>&lt;p>Le ratio de contraste (Contrast Ratio) $CR$ dans les WCAG est défini de la manière suivante en utilisant la luminance relative (Relative Luminance) de la couleur de fond et de la couleur de premier plan.&lt;/p>
$$CR = \frac{L_{lighter} + 0.05}{L_{darker} + 0.05}$$&lt;p>Ici, $L_{lighter}$ est la luminance relative de la couleur la plus claire, et $L_{darker}$ est la luminance relative de la couleur la plus sombre (les valeurs vont de 0.0 à 1.0). Pour atteindre le niveau AAA des WCAG 2.1, un ratio de contraste de &lt;strong>7:1 ou plus&lt;/strong> est requis pour le texte normal, et de &lt;strong>4.5:1 ou plus&lt;/strong> pour le texte de grande taille.&lt;/p>
&lt;p>La luminance relative $L$ est calculée à partir des valeurs RGB de l&amp;rsquo;espace colorimétrique sRGB avec la formule complexe suivante.&lt;/p>
$$L = 0.2126 \times R + 0.7152 \times G + 0.0722 \times B$$&lt;p>Chaque composante ($R, G, B$) utilise une valeur normalisée obtenue en divisant la valeur d&amp;rsquo;origine sur 8 bits ($R_{sRGB}$) par 255, puis subit la conversion suivante pour lever la correction gamma.&lt;/p>
$$
R, G, B =
\begin{cases}
\frac{C_{sRGB}}{12.92} &amp; \text{if } C_{sRGB} \le 0.03928 \\
\left( \frac{C_{sRGB} + 0.055}{1.055} \right)^{2.4} &amp; \text{otherwise}
\end{cases}
$$&lt;p>Il est difficile d&amp;rsquo;effectuer ce calcul manuellement, mais en utilisant des outils de conception de couleurs, on peut sélectionner mécaniquement des couleurs qui répondent à un ratio de contraste de 7:1 ($CR \ge 7.0$).&lt;/p>
&lt;h3 id="22-hsl-vs-rgb-vs-oklch">2.2 HSL vs RGB vs OKLCH
&lt;/h3>&lt;p>Lors de la création de palettes de couleurs, les formats RGB ou HSL étaient autrefois dominants. Cependant, ceux-ci présentent un défaut majeur en termes d&amp;rsquo;« uniformité perceptuelle ».&lt;/p>
&lt;ul>
&lt;li>&lt;strong>RGB&lt;/strong> : Il s&amp;rsquo;agit des trois couleurs primaires de la lumière mécanique, ce qui rend difficile pour les humains de faire des ajustements intuitifs comme « éclaircir » ou « assombrir ».&lt;/li>
&lt;li>&lt;strong>HSL&lt;/strong> : Il utilise la teinte (Hue), la saturation (Saturation) et la luminosité (Lightness), mais la « luminosité (L) » du HSL ne correspond pas à la luminosité perçue par l&amp;rsquo;œil humain. Par exemple, un jaune pur et un bleu pur avec une luminosité de 50 % en HSL ont la même luminosité numériquement, mais le jaune paraît infiniment plus lumineux à l&amp;rsquo;œil humain.&lt;/li>
&lt;li>&lt;strong>OKLCH&lt;/strong> : C&amp;rsquo;est le dernier espace colorimétrique introduit récemment dans CSS Color Module Level 4. Composé de la luminosité perceptuelle (Lightness), de la chromaticité/saturation (Chroma) et de la teinte (Hue), il &lt;strong>correspond parfaitement aux caractéristiques visuelles humaines (uniformité perceptuelle)&lt;/strong>.&lt;/li>
&lt;/ul>
&lt;p>L&amp;rsquo;utilisation d&amp;rsquo;OKLCH permet de conserver la même luminosité perceptuelle (Lightness) même si l&amp;rsquo;on change la teinte (Hue), ce qui rend la génération d&amp;rsquo;une palette de couleurs pour le mode sombre extrêmement prévisible et sûre.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* Exemple de définition de variables CSS utilisant OKLCH */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">:&lt;/span>&lt;span class="nd">root&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">/* Mode clair avec une luminosité de base élevée et une saturation modérée */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--bg-base&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">oklch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.98&lt;/span> &lt;span class="mf">0.01&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--text-base&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">oklch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.25&lt;/span> &lt;span class="mf">0.02&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--primary-brand&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">oklch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.65&lt;/span> &lt;span class="mf">0.15&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;dark&amp;#34;&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">/* En mode sombre, il suffit d&amp;#39;inverser la luminosité pour maintenir facilement le contraste perceptuel */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--bg-base&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">oklch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.20&lt;/span> &lt;span class="mf">0.02&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--text-base&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">oklch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.95&lt;/span> &lt;span class="mf">0.01&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--primary-brand&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">oklch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.75&lt;/span> &lt;span class="mf">0.15&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c">/* Légèrement plus clair pour assurer la visibilité en mode sombre */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>En adoptant ainsi l&amp;rsquo;OKLCH, vous pouvez construire simplement une logique qui garantit un ratio de contraste constant (au niveau WCAG AAA) à travers plusieurs thèmes.&lt;/p>
&lt;hr>
&lt;h2 id="3-prévention-du-fouc-flash-of-unstyled-content-et-hydratation-ssr">3. Prévention du FOUC (Flash of Unstyled Content) et hydratation SSR
&lt;/h2>&lt;p>Ce qui préoccupe le plus les développeurs dans la prise en charge du mode sombre, c&amp;rsquo;est le problème de scintillement de l&amp;rsquo;écran appelé &lt;strong>FOUC (Flash of Unstyled Content)&lt;/strong>.&lt;/p>
&lt;h3 id="31-le-piège-du-basculement-de-thème-par-js-côté-client">3.1 Le piège du basculement de thème par JS côté client
&lt;/h3>&lt;p>Dans les SPA comme React ou Vue (ou les sites statiques via SSG), il est courant d&amp;rsquo;enregistrer les paramètres de l&amp;rsquo;utilisateur dans le &lt;code>localStorage&lt;/code> et de les lire avec JavaScript pour basculer de thème. Cependant, si ce processus est effectué via &lt;code>useEffect&lt;/code> dans React par exemple, les problèmes suivants se produisent.&lt;/p>
&lt;ol>
&lt;li>Le navigateur rend le HTML/CSS du mode clair.&lt;/li>
&lt;li>Le bundle JS est chargé et exécuté.&lt;/li>
&lt;li>Le paramètre &lt;code>dark&lt;/code> est lu depuis le &lt;code>localStorage&lt;/code>.&lt;/li>
&lt;li>La classe &lt;code>dark&lt;/code> est ajoutée au HTML, et l&amp;rsquo;écran s&amp;rsquo;assombrit soudainement (scintillement).&lt;/li>
&lt;/ol>
&lt;h3 id="32-une-prévention-parfaite-du-fouc--utilisation-de-cookie-et-ssr">3.2 Une prévention parfaite du FOUC : Utilisation de Cookie et SSR
&lt;/h3>&lt;p>La meilleure pratique pour prévenir complètement le FOUC et éviter les erreurs d&amp;rsquo;hydratation consiste à &lt;strong>enregistrer le paramètre de thème de l&amp;rsquo;utilisateur dans &lt;code>document.cookie&lt;/code> et à renvoyer le HTML avec les classes appropriées ajoutées lors du rendu côté serveur (SSR)&lt;/strong>.&lt;/p>
&lt;p>Le diagramme de séquence ci-dessous illustre le flux idéal d&amp;rsquo;initialisation du thème à l&amp;rsquo;aide de cookies.&lt;/p>
&lt;pre class="mermaid">
sequenceDiagram
participant User as &amp;#34;Utilisateur&amp;#34;
participant Browser as &amp;#34;Navigateur OS&amp;#34;
participant Server as &amp;#34;Serveur SSR&amp;#34;
participant DOM as &amp;#34;Client DOM&amp;#34;
User-&amp;gt;&amp;gt;Browser: &amp;#34;Demande de page&amp;#34;
Browser-&amp;gt;&amp;gt;Server: &amp;#34;Requête GET avec Cookie (theme=dark)&amp;#34;
Server--&amp;gt;&amp;gt;Browser: &amp;#34;Renvoie HTML avec &amp;lt;html data-theme=&amp;#39;dark&amp;#39;&amp;gt;&amp;#34;
Browser-&amp;gt;&amp;gt;DOM: &amp;#34;Rendu HTML initial (Aucun FOUC)&amp;#34;
DOM-&amp;gt;&amp;gt;DOM: &amp;#34;Exécution du script d&amp;#39;hydratation&amp;#34;
alt &amp;#34;Cookie absent (Première visite)&amp;#34;
DOM-&amp;gt;&amp;gt;Browser: &amp;#34;Vérifie OS prefers-color-scheme&amp;#34;
Browser--&amp;gt;&amp;gt;DOM: &amp;#34;Résultat matchMedia (ex. dark)&amp;#34;
DOM-&amp;gt;&amp;gt;DOM: &amp;#34;Définit data-theme=&amp;#39;dark&amp;#39; via script bloquant en ligne&amp;#34;
end
&lt;/pre>
&lt;h3 id="33-ligne-de-défense-via-un-script-en-ligne-pour-les-sites-statiques-sans-cookies">3.3 Ligne de défense via un script en ligne (Pour les sites statiques sans cookies)
&lt;/h3>&lt;p>Pour les blogs générés uniquement de manière statique (SSG) où le SSR est impossible (comme les exports statiques de Hugo, Gatsby ou Astro), il est indispensable de placer un script JavaScript en ligne s&amp;rsquo;exécutant de manière bloquante à l&amp;rsquo;intérieur de la balise &lt;code>&amp;lt;head&amp;gt;&lt;/code>, qui ajoute la classe juste avant le rendu du DOM.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- À placer à la fin de la balise &amp;lt;head&amp;gt; --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">script&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="kd">function&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">var&lt;/span> &lt;span class="nx">localTheme&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">localStorage&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">getItem&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;theme&amp;#39;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">var&lt;/span> &lt;span class="nx">osTheme&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">window&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">matchMedia&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;(prefers-color-scheme: dark)&amp;#39;&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="nx">matches&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="s1">&amp;#39;dark&amp;#39;&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;light&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">var&lt;/span> &lt;span class="nx">theme&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">localTheme&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="nx">osTheme&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">document&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">documentElement&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">setAttribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;data-theme&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">theme&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">e&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">script&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ce petit script bloque le rendu du navigateur et s&amp;rsquo;exécute immédiatement. Ainsi, au moment où l&amp;rsquo;écran est affiché, l&amp;rsquo;attribut &lt;code>data-theme&lt;/code> est déjà configuré, ce qui permet de prévenir complètement le scintillement de l&amp;rsquo;écran (FOUC).&lt;/p>
&lt;hr>
&lt;h2 id="4-approches-dimplémentation-avec-tailwind-css-et-scsscss-natif">4. Approches d&amp;rsquo;implémentation avec Tailwind CSS et SCSS/CSS natif
&lt;/h2>&lt;p>Lors de l&amp;rsquo;intégration du mode sombre dans un projet réel, il est important de comprendre l&amp;rsquo;approche de chaque outil.&lt;/p>
&lt;h3 id="41-le-mode-sombre-dans-tailwind-css">4.1 Le mode sombre dans Tailwind CSS
&lt;/h3>&lt;p>Tailwind CSS fournit par défaut une variante &lt;code>dark:&lt;/code>, ce qui rend l&amp;rsquo;implémentation du mode sombre très facile. On configure la propriété &lt;code>darkMode&lt;/code> dans le fichier de configuration (&lt;code>tailwind.config.js&lt;/code>).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// tailwind.config.js
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="nx">module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">exports&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// &amp;#39;media&amp;#39; (dépendant des paramètres OS) ou &amp;#39;class&amp;#39; (basculable manuellement)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">darkMode&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;class&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">theme&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">extend&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">colors&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cm">/* Extension de la palette de couleurs Tailwind à l&amp;#39;aide de variables CSS */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">primary&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;rgb(var(--color-primary) / &amp;lt;alpha-value&amp;gt;)&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">background&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;rgb(var(--color-background) / &amp;lt;alpha-value&amp;gt;)&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Du côté HTML, il suffit d&amp;rsquo;ajouter les classes de la manière suivante.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">h1&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;text-2xl font-bold&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>Hello World&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">h1&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;mt-2&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>Tailwind makes dark mode incredibly easy.&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Cependant, écrire &lt;code>dark:bg-xxx&lt;/code> pour tous les éléments peut causer une surcharge excessive des composants. Pour les blogs ou applications de grande envergure, il est recommandé d&amp;rsquo;adopter une conception hybride (conception de couleurs sémantiques) où &lt;strong>les variables CSS servent de base, et Tailwind référence ces variables CSS&lt;/strong>.&lt;/p>
&lt;p>Le diagramme de classes ci-dessous montre l&amp;rsquo;héritage des variables CSS et les couches d&amp;rsquo;application.&lt;/p>
&lt;pre class="mermaid">
classDiagram
class GlobalCSSVariables {
&amp;#34;--color-brand-500&amp;#34;
&amp;#34;--color-gray-900&amp;#34;
}
class SemanticVariables {
&amp;#34;--bg-primary&amp;#34;
&amp;#34;--text-base&amp;#34;
&amp;#34;--accent&amp;#34;
}
class TailwindConfig {
&amp;#34;theme.colors.background&amp;#34;
&amp;#34;theme.colors.primary&amp;#34;
}
class UIComponents {
&amp;#34;class=&amp;#39;bg-background text-primary&amp;#39;&amp;#34;
}
GlobalCSSVariables &amp;lt;|-- SemanticVariables : &amp;#34;:root &amp;amp; .dark&amp;#34;
SemanticVariables &amp;lt;|-- TailwindConfig : &amp;#34;tailwind.config.js&amp;#34;
TailwindConfig &amp;lt;.. UIComponents : &amp;#34;Applique les classes utilitaires&amp;#34;
&lt;/pre>
&lt;h3 id="42-implémentation-en-raw-scsscss-utilisation-des-mixins">4.2 Implémentation en Raw SCSS/CSS (Utilisation des Mixins)
&lt;/h3>&lt;p>Pour les projets qui n&amp;rsquo;utilisent pas Tailwind et écrivent leur propre SCSS, on utilise les &lt;code>@mixin&lt;/code> pour encapsuler les styles du mode sombre.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-scss" data-lang="scss">&lt;span class="line">&lt;span class="cl">&lt;span class="cm">/* Définition du Mixin SCSS */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">@mixin&lt;/span>&lt;span class="nf"> dark-mode&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cm">/* Supporte à la fois l&amp;#39;attribut [data-theme=&amp;#39;dark&amp;#39;] et les paramètres de l&amp;#39;OS */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">[&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;dark&amp;#39;&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="k">&amp;amp;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">@content&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">@media&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">prefers-color-scheme&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="ni">dark&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nd">:root:not&lt;/span>&lt;span class="o">([&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;light&amp;#39;&lt;/span>&lt;span class="o">])&lt;/span> &lt;span class="k">&amp;amp;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">@content&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm">/* Exemple d&amp;#39;utilisation */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nc">.card&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">background-color&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mh">#ffffff&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">color&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mh">#333333&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">border&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="kt">px&lt;/span> &lt;span class="ni">solid&lt;/span> &lt;span class="mh">#eeeeee&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">@include&lt;/span>&lt;span class="nd"> dark-mode&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">background-color&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mh">#1a202c&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">color&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mh">#e2e8f0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">border-color&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mh">#2d3748&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Cette méthode est intuitive, mais la taille du fichier CSS compilé a tendance à s&amp;rsquo;alourdir (la requête multimédia est dupliquée pour chaque sélecteur). C&amp;rsquo;est pourquoi la tendance actuelle se tourne plutôt vers une conception axée sur les variables CSS (Custom Properties).&lt;/p>
&lt;hr>
&lt;h2 id="5-optimisation-du-mode-sombre-pour-les-images-image-et-les-svg">5. Optimisation du mode sombre pour les images (Image) et les SVG
&lt;/h2>&lt;p>Même si la conception des couleurs pour le texte et les arrière-plans est achevée, si les images et les icônes (SVG) placées comme contenu restent en mode clair, elles paraîtront éblouissantes et se détacheront trop en mode sombre. Leur optimisation est également essentielle.&lt;/p>
&lt;h3 id="51-filtres-css-pour-réduire-la-luminosité-des-images">5.1 Filtres CSS pour réduire la luminosité des images
&lt;/h3>&lt;p>Les images bitmap telles que les photos peuvent être trop lumineuses si elles sont affichées telles quelles en mode sombre. En utilisant la propriété CSS &lt;code>filter&lt;/code> pour réduire légèrement la luminosité (brightness) et augmenter le contraste (contrast) de l&amp;rsquo;image, on peut la faire fondre naturellement dans l&amp;rsquo;interface du thème sombre.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;dark&amp;#39;&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="nt">img&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="nd">not&lt;/span>&lt;span class="o">([&lt;/span>&lt;span class="nt">src&lt;/span>&lt;span class="o">*=&lt;/span>&lt;span class="s2">&amp;#34;.svg&amp;#34;&lt;/span>&lt;span class="o">])&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">/* Réduit la luminosité et augmente un peu le contraste */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">filter&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">brightness&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.8&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="nb">contrast&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">1.1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">transition&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">filter&lt;/span> &lt;span class="mf">0.3&lt;/span>&lt;span class="kt">s&lt;/span> &lt;span class="kc">ease&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;dark&amp;#39;&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="nt">img&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="nd">hover&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">/* Restaure la luminosité d&amp;#39;origine au survol (si l&amp;#39;utilisateur veut voir les détails) */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">filter&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">brightness&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="nb">contrast&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="52-remplacement-dimages-via-la-balise-picture">5.2 Remplacement d&amp;rsquo;images via la balise &lt;code>&amp;lt;picture&amp;gt;&lt;/code>
&lt;/h3>&lt;p>Les images de logos ou les diagrammes explicatifs (comme les JPEG avec un fond blanc fixe) ne peuvent pas être gérés uniquement par des filtres. Dans ces cas-là, la bonne solution consiste à utiliser l&amp;rsquo;élément HTML &lt;code>&amp;lt;picture&amp;gt;&lt;/code> et les requêtes multimédias (media queries) pour afficher un autre fichier image spécifique au mode sombre.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">picture&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- Affiché pour les utilisateurs ayant configuré leur OS en mode sombre --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">source&lt;/span> &lt;span class="na">srcset&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;/img/logo-dark.png&amp;#34;&lt;/span> &lt;span class="na">media&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;(prefers-color-scheme: dark)&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- Par défaut (mode clair) --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">img&lt;/span> &lt;span class="na">src&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;/img/logo-light.png&amp;#34;&lt;/span> &lt;span class="na">alt&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;Logo du site&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">picture&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>※ Toutefois, cette méthode ne se synchronise pas avec les basculements manuels comme via &lt;code>localStorage&lt;/code> (elle ne dépend que des paramètres de l&amp;rsquo;OS). Si vous implémentez un basculement manuel, vous devrez modifier dynamiquement la source &lt;code>src&lt;/code> des images avec JS ou basculer un &lt;code>display: none&lt;/code> via des classes CSS.&lt;/p>
&lt;h3 id="53-prise-en-charge-de-currentcolor-pour-les-icônes-svg">5.3 Prise en charge de &lt;code>currentColor&lt;/code> pour les icônes SVG
&lt;/h3>&lt;p>La méthode la plus élégante pour les SVG en ligne utilisés pour des icônes est de lier leur couleur de remplissage à la couleur du texte de l&amp;rsquo;élément parent. Pour ce faire, spécifiez &lt;code>currentColor&lt;/code> dans l&amp;rsquo;attribut &lt;code>fill&lt;/code> ou &lt;code>stroke&lt;/code> du SVG.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- La valeur de la propriété color du CSS (ex: var(--text-primary)) est appliquée automatiquement --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">svg&lt;/span> &lt;span class="na">viewBox&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;0 0 24 24&amp;#34;&lt;/span> &lt;span class="na">fill&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;currentColor&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">path&lt;/span> &lt;span class="na">d&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;M12 2L2 22h20L12 2z&amp;#34;&lt;/span> &lt;span class="p">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">svg&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ainsi, lors du passage au mode sombre, si la couleur du texte de l&amp;rsquo;élément parent devient blanche, l&amp;rsquo;icône SVG passera aussi automatiquement à une teinte blanche.&lt;/p>
&lt;hr>
&lt;h2 id="6-conclusion--vers-une-conception-durable-du-mode-sombre">6. Conclusion : Vers une conception durable du mode sombre
&lt;/h2>&lt;p>Pour implémenter un mode sombre de haute qualité sur un blog ou une application web, une conception CSS couvrant les points suivants est indispensable.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Utiliser les CSS Custom Properties&lt;/strong> : Éviter le codage en dur (hardcoding) des spécifications de couleurs et les abstraire dans des noms de variables sémantiques (ex: &lt;code>--bg-primary&lt;/code>).&lt;/li>
&lt;li>&lt;strong>Adopter l&amp;rsquo;espace colorimétrique OKLCH&lt;/strong> : Concevoir de manière logique des ratios de contraste hautement accessibles (7:1 ou plus) répondant à la norme WCAG 2.1 AAA, au sein d&amp;rsquo;un espace colorimétrique perceptuellement uniforme.&lt;/li>
&lt;li>&lt;strong>Appliquer des mesures strictes contre le FOUC&lt;/strong> : Éliminer complètement les scintillements de l&amp;rsquo;écran lors du chargement initial grâce à l&amp;rsquo;association du SSR et des cookies, ou via des scripts bloquants en ligne dans le &lt;code>&amp;lt;head&amp;gt;&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Optimiser les médias et les ressources&lt;/strong> : Harmoniser les éléments autres que le texte avec le thème sombre en exploitant &lt;code>filter: brightness()&lt;/code>, &lt;code>currentColor&lt;/code> et la balise &lt;code>&amp;lt;picture&amp;gt;&lt;/code>.&lt;/li>
&lt;/ol>
&lt;p>Ces attentions minutieuses, qui vont bien au-delà d&amp;rsquo;une simple « inversion de couleurs », constituent les conditions d&amp;rsquo;un blog moderne offrant une expérience de lecture (reading experience) supérieure, agréable pour les yeux et appréciée durablement par les utilisateurs. Développeurs sur le point d&amp;rsquo;introduire le mode sombre, n&amp;rsquo;hésitez pas à vous référer aux modèles de conception présentés dans cet article.&lt;/p></description></item></channel></rss>