Retour aux articles

Des tokens Figma au code : les brancher dans Tailwind CSS v4 avec @theme

  • Tailwind CSS
  • Figma

Le chaînon manquant entre design et code

Dans un précédent article, on a vu comment structurer ses design tokens dans Figma : des valeurs brutes (les primitives) et des noms qui décrivent leur usage (les tokens sémantiques). Reste la question que tout le monde se pose ensuite : comment ces tokens arrivent-ils dans le code ?

Avec Tailwind CSS v4, la réponse est devenue beaucoup plus simple. Fini le fichier tailwind.config.js : la configuration se fait directement en CSS, avec des variables. Exactement le format dans lequel on pense déjà ses tokens.

L'idée clé : dans Tailwind v4, chaque variable déclarée dans @theme crée automatiquement les classes utilitaires correspondantes. Déclarer --color-primary, c'est obtenir bg-primary, text-primary, border-primary... sans rien configurer d'autre.

1. Déclarer ses tokens dans @theme

css
/* app/globals.css */
@import "tailwindcss";

@theme {
	--color-primary: #6b21a8;
	--color-primary-hover: #581c87;

	--font-display: "Satoshi", sans-serif;

	--radius-card: 1rem;
	--shadow-card: 0 8px 24px rgb(0 0 0 / 0.08);
}

Ces quatre lignes génèrent directement des classes utilisables dans le HTML :

html
<article class="rounded-card shadow-card">
	<h2 class="font-display text-primary">Mon projet</h2>
	<a class="bg-primary hover:bg-primary-hover" href="/projets">Voir</a>
</article>

Le préfixe de la variable détermine le type de classes créées. Les plus utiles :

Préfixe de la variable Classes générées Exemple
--color-* bg-*, text-*, border-*, fill-*… --color-primary
--font-* font-* --font-display
--text-* Tailles de texte text-* --text-title
--spacing Toute l'échelle p-*, m-*, gap-*… --spacing: 0.25rem
--radius-* rounded-* --radius-card
--shadow-* shadow-* --shadow-card
--breakpoint-* Préfixes responsive md:, lg:… --breakpoint-tablet

2. Faire correspondre les noms Figma et les noms CSS

C'est là que la rigueur côté Figma paie. Si tes variables Figma s'appellent color/primary et radius/card, leur traduction en CSS est mécanique : on remplace les / par des -, et on ajoute le préfixe attendu par Tailwind.

Dans Figma

  • color/primary
  • color/primary-hover
  • radius/card
  • shadow/card

Dans @theme

  • --color-primary
  • --color-primary-hover
  • --radius-card
  • --shadow-card

Designer et développeur parlent enfin la même langue. Quand le designer dit « ce bouton utilise color/primary », le développeur sait qu'il doit écrire bg-primary. Plus de pipette, plus de code hexadécimal recopié à la main.

Pour les gros design systems, un plugin Figma d'export de variables (comme Tokens Studio) permet de générer un fichier JSON ou CSS, puis de l'intégrer automatiquement. Pour un site vitrine ou un portfolio, une copie manuelle soignée reste souvent plus simple.

3. Gérer le mode sombre avec @theme inline

Dans Figma, un mode sombre se gère avec les modes d'une collection de variables : un même token color/background vaut blanc en mode clair et presque noir en mode sombre. On reproduit exactement cette logique en CSS.

On déclare d'abord des variables CSS classiques, qui changent selon le mode :

css
:root {
	--background: #ffffff;
	--foreground: #171717;
	--primary: #6b21a8;
}

.dark {
	--background: #0a0a0a;
	--foreground: #ededed;
	--primary: #c084fc;
}

Puis on les expose à Tailwind avec @theme inline :

css
@theme inline {
	--color-background: var(--background);
	--color-foreground: var(--foreground);
	--color-primary: var(--primary);
}

Le mot-clé inline est important : il indique à Tailwind d'utiliser directement var(--primary) dans les classes générées, au lieu de figer la valeur. Résultat, bg-primary change de couleur tout seul quand on passe en mode sombre. Aucune classe dark: à ajouter dans le HTML.

Sans inline, Tailwind crée une variable intermédiaire qui peut être résolue au mauvais endroit, et le changement de mode ne se propage pas toujours comme prévu. Dès qu'un token de @theme pointe vers une autre variable, utilise @theme inline.

C'est d'ailleurs le principe utilisé sur ce portfolio, avec une petite variante : les variables changent dans un bloc @media (prefers-color-scheme: dark) plutôt que sur une classe .dark. Le site suit ainsi automatiquement le réglage du système du visiteur.

4. Repartir d'une palette propre

Par défaut, Tailwind fournit une palette complète (red-500, slate-200...). Si ton design system définit ses propres couleurs, ces classes par défaut deviennent un piège : un développeur pressé utilisera bg-purple-700 au lieu de bg-primary, et la cohérence disparaît.

On peut retirer toutes les couleurs par défaut d'une seule ligne :

css
@theme {
	--color-*: initial;

	--color-primary: #6b21a8;
	--color-neutral-100: #f5f5f5;
	--color-neutral-900: #171717;
}

Seules tes couleurs restent disponibles. L'autocomplétion de l'éditeur ne propose plus que les tokens du design system : c'est le meilleur garde-fou possible.

En résumé

Besoin Solution Tailwind v4
Déclarer les tokens du design system Des variables CSS dans @theme
Obtenir les classes utilitaires Automatique, selon le préfixe de la variable
Garder les mêmes noms que Figma color/primary → --color-primary
Mode clair et mode sombre Variables CSS + @theme inline
Empêcher les couleurs hors système --color-*: initial;

Les tokens définis dans Figma deviennent la source unique de vérité, du premier écran de maquette jusqu'à la dernière classe CSS. Et quand la couleur principale change, on modifie une seule ligne.