shadcn/ui : guide complet d'installation et de personnalisation du thème (variables CSS)

La première fois que j’ai utilisé shadcn/ui, j’ai été déconcerté par le fait que ce n’est « pas un paquet npm ». Copier du code dans le projet ? Ça paraissait rudimentaire.
Après quelques essais, j’ai compris que c’est précisément sa force : vous possédez tout le source des composants, vous modifiez comme vous voulez, sans conflits de versions ni limites imposées par une lib.
Aujourd’hui, on parle installation, configuration et personnalisation du thème shadcn/ui, en mettant l’accent sur les variables CSS pour un design system aligné sur votre marque. À la fin de l’article, vous devriez tenir la config de base en 5 minutes, puis consacrer une heure ou deux à peaufiner le thème.
1. Installation rapide : deux approches
Méthode 1 : initialisation CLI (recommandée)
Pour un nouveau projet, lancez :
npx shadcn@latest init
La CLI pose plusieurs questions : TypeScript ou JavaScript ? Quel style ? Quel thème par défaut ? Suivez les invites.
Après installation, vous aurez notamment :
components.json— fichier de configurationlib/utils.ts— utilitairescomponents/ui/— répertoire des composants
Pour ajouter un composant, par exemple un bouton :
npx shadcn@latest add button
Le code est copié dans components/ui/button.tsx ; importez-le et utilisez-le.
Piège à connaître : si le projet tourne déjà depuis un moment, tailwind.config.js et globals.css contiennent peut-être déjà beaucoup de réglages. La commande init les écrase — installez shadcn le plus tôt possible.
Un bon conseil : traitez shadcn/ui comme une des « premières dépendances » du projet, pas un ajout tardif. J’ai appris à mes dépens.
Méthode 2 : installation manuelle (projets existants)
Si le projet est déjà structuré et que le risque d’écrasement par la CLI est trop élevé, installez à la main.
Étape 1 : Tailwind CSS
Les composants shadcn s’appuient sur Tailwind. Si ce n’est pas installé, suivez le guide officiel — on ne détaille pas ici.
Étape 2 : dépendances
npm install class-variance-authority clsx tailwind-merge
npm install lucide-react
class-variance-authority (CVA) servira pour les variantes de composants.
Étape 3 : alias de chemins
Dans tsconfig.json :
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}
Vous pourrez importer avec @/components/ui/button au lieu de ../../../.
Étape 4 : créer components.json
À la racine du projet :
{
"style": "new-york",
"rsc": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "app/globals.css",
"baseColor": "neutral",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}
cssVariables: true indique que le thème repose sur des variables CSS, pas uniquement sur des classes utility Tailwind.
Étape 5 : styles de base
Ajoutez dans globals.css les styles de base shadcn — détaillés dans la section thème ci-dessous.
2. Comprendre le système de thème : variables CSS
Le thème shadcn/ui repose sur une convention simple : chaque couleur a une paire background et foreground.
Exemple :
:root {
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
}
--primary est le fond du bouton, --primary-foreground le texte dessus. Modifier une variable met à jour tous les composants qui l’utilisent.
Liste des variables CSS
Variables par défaut shadcn/ui :
| Variable | Usage |
|---|---|
--background | Fond de page |
--foreground | Texte de page |
--card | Fond de carte |
--card-foreground | Texte de carte |
--popover | Fond de popover |
--popover-foreground | Texte de popover |
--primary | Couleur principale (boutons, liens) |
--primary-foreground | Texte sur la couleur principale |
--secondary | Couleur secondaire |
--secondary-foreground | Texte sur la couleur secondaire |
--muted | Fond atténué |
--muted-foreground | Texte atténué |
--accent | Couleur d’accent |
--accent-foreground | Texte sur l’accent |
--destructive | Actions destructives (suppression) |
--destructive-foreground | Texte sur destructive |
--border | Bordures |
--input | Champs de saisie |
--ring | Anneau de focus |
Une fois le couple background / foreground assimilé, le reste suit logiquement.
Le secret du format HSL
Les valeurs ne sont pas au format HSL classique :
/* ❌ HSL standard */
--primary: hsl(222.2, 47.4%, 11.2%);
/* ✅ format shadcn */
--primary: 222.2 47.4% 11.2%;
Pourquoi ce format « nu » ?
Tailwind gère les modificateurs d’opacité, par ex. bg-primary/50 pour 50 % d’opacité. Avec un hsl() complet dans la variable, cela ne fonctionne pas.
Au format nu, Tailwind ajoute hsl() et l’opacité automatiquement — astucieux.
3. Personnaliser le thème de votre marque
Méthode 1 : modifier directement les variables CSS
Ouvrez globals.css, section :root, changez les valeurs.
Passer du bleu par défaut au violet :
:root {
--primary: 270 60% 60%;
--primary-foreground: 0 0% 100%;
}
.dark {
--primary: 270 60% 70%;
--primary-foreground: 0 0% 0%;
}
Enregistrez : tous les boutons et liens en bg-primary deviennent violets.
Méthode 2 : espace colorimétrique OKLCH (Tailwind v4)
Avec Tailwind v4, OKLCH donne une perception plus uniforme qu’HSL et des palettes plus cohérentes.
:root {
--primary: oklch(0.6 0.2 270);
--primary-foreground: oklch(0.98 0 0);
}
Pour oklch(0.6 0.2 270) :
0.6— luminosité (0-1)0.2— chroma (environ 0-0,4)270— teinte en degrés (0-360)
Méthode 3 : générateur en ligne
Pour éviter de tout régler à la main : Shadcn Theme Generator
Choisissez une couleur principale ; l’outil produit l’ensemble des variables, clair et sombre. Copiez-collez dans globals.css.
4. Configuration du mode sombre
Bascule de thème avec next-themes
shadcn/ui n’inclut pas de bascule de thème ; next-themes s’en charge.
Installation :
npm install next-themes
Dans layout.tsx :
import { ThemeProvider } from "next-themes"
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="fr" suppressHydrationWarning>
<body>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
>
{children}
</ThemeProvider>
</body>
</html>
)
}
Points clés :
suppressHydrationWarningévite les avertissements d’hydratationattribute="class"bascule via une classedefaultTheme="system"suit le système par défautenableSystemactive la détection du thème système
Bouton de bascule
Avec le hook useTheme :
import { useTheme } from "next-themes"
import { Moon, Sun } from "lucide-react"
export function ThemeToggle() {
const { theme, setTheme } = useTheme()
return (
<button
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
className="p-2 rounded-md hover:bg-accent"
>
{theme === "dark" ? <Sun size={20} /> : <Moon size={20} />}
</button>
)
}
Mode sombre par défaut
Option 1 : classe dark en dur
<html lang="fr" className="dark">
Thème fixe sombre, sans bascule.
Option 2 : thème par défaut
<ThemeProvider
attribute="class"
defaultTheme="dark" // sombre par défaut
enableSystem={false} // pas de détection système
>
L’utilisateur peut basculer ; l’état initial est sombre.
5. Personnalisation avancée : variantes de composants
Variantes custom avec CVA
Pour des styles supplémentaires (danger, succès, dégradé), CVA simplifie la définition :
import { cva, type VariantProps } from "class-variance-authority"
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
Utilisation :
<button className={buttonVariants({ variant: "destructive", size: "lg" })}>
Supprimer
</button>
Ne pas modifier le source shadcn d’origine
Bonne pratique : le code est dans votre repo, mais évitez de toucher les fichiers générés par shadcn. Les mises à jour imposent sinon des merges manuels.
Préférez un wrapper :
// components/brand-button.tsx
import { Button } from "@/components/ui/button"
import { cva } from "class-variance-authority"
const brandButtonVariants = cva("...", {
variants: {
brand: {
primary: "bg-brand-primary text-white",
secondary: "bg-brand-secondary text-black",
},
},
})
export function BrandButton({ brand, ...props }) {
return <Button className={brandButtonVariants({ brand })} {...props} />
}
Le Button d’origine reste intact ; vos mises à jour shadcn ne cassent pas BrandButton.
6. Problèmes fréquents
Les styles ne s’appliquent pas après installation
Vérifiez :
globals.cssest-il importé danslayout.tsx?- La config
contentde Tailwind inclut-ellecomponents/**/*? - Les chemins dans
components.jsonsont-ils corrects ?
Clignotement au changement de thème
Souvent un problème d’hydratation :
suppressHydrationWarningsur<html>ThemeProviderenveloppe toute l’application- Ne lisez pas
themecôté serveur (undefined en SSR)
Variables CSS ignorées
Causes possibles :
- Nom incorrect (
--primary-foreground, pas--primaryForeground) - Pas de bloc
.darkcorrespondant - Format invalide (HSL ou OKLCH « nu » requis)
Conflits de styles
Si un autre design system coexiste :
- Namespace sur les composants shadcn (ex.
shadcn-button) - Ajuster la priorité des layers Tailwind
- Variantes CVA propres, sans dépendre des styles par défaut
7. Synthèse
L’installation shadcn/ui est simple une fois comprise l’idée « copier le code plutôt qu’installer un paquet » : contrôle total, maintenance locale des composants.
Pour le thème, le système de variables CSS est élégant : quelques valeurs modifiées, toute l’app suit. Avec next-themes, clair/sombre tient en quelques lignes.
En bref :
- Nouveaux projets : privilégiez
npx shadcn@latest init - Variables sémantiques : primary, secondary, pas des noms de couleur bruts
- Contraste en clair et en sombre
- Wrappers plutôt que modification du source shadcn
La prochaine fois que vous montez une UI thématisée rapidement, essayez shadcn/ui — le plaisir du copier-coller contrôlé, il faut le vivre.
Références
- shadcn/ui — Installation
- shadcn/ui — Theming
- shadcn/ui — Dark Mode
- Generate Custom shadcn/ui Themes
- Theming in shadcn UI: CSS Variables
Installation et personnalisation du thème shadcn/ui
Installer shadcn/ui depuis zéro, configurer le système de thème et obtenir un design de marque
⏱️ Estimated time: 30 min
- 1
Step 1: Initialisation rapide via CLI
Dans un nouveau projet, lancez :
• npx shadcn@latest init
• Choisissez TypeScript / style New York / thème par défaut
• Attendez la fin de la configuration par la CLI - 2
Step 2: Modifier la couleur principale de marque
Éditez les variables CSS dans globals.css :
• Ouvrez app/globals.css
• Repérez --primary sous :root
• Remplacez par votre couleur de marque (format HSL ou OKLCH)
• Ajustez aussi --primary-foreground pour le contraste - 3
Step 3: Configurer le mode sombre
Installez et configurez next-themes :
• npm install next-themes
• Ajoutez ThemeProvider dans layout.tsx
• Définissez suppressHydrationWarning pour éviter les avertissements d'hydratation
• Créez un composant de bascule de thème - 4
Step 4: Créer des variantes de composants
Définissez des styles custom avec CVA :
• Installez class-variance-authority
• Définissez variants et defaultVariants
• Appliquez buttonVariants() dans le composant
• Gardez les composants shadcn d'origine intacts
FAQ
Quelle différence entre shadcn/ui et une bibliothèque UI classique ?
Pourquoi installer shadcn/ui dès l'initialisation d'un nouveau projet ?
Pourquoi les variables CSS sont-elles au format « nu » plutôt qu'en HSL standard ?
Comment modifier la couleur principale de marque ?
Pourquoi le mode sombre clignote-t-il au chargement ?
Faut-il modifier directement le source des composants shadcn ?
7 min de lecture · Publié le: 26 mars 2026 · Mis à jour le: 27 juil. 2026
Tailwind & shadcn/ui en pratique
Si vous arrivez depuis la recherche, le plus rapide est de passer à l’article précédent ou suivant de cette série.
Précédent
Qu'est-ce que shadcn/ui ? Guide de comparaison avec MUI, Chakra et autres bibliothèques
Comparaison approfondie de shadcn/ui, Material-UI, Chakra UI et Ant Design sur sept dimensions : taille du bundle, flexibilité de personnalisation, expérience de développement, accessibilité, et plus encore.
Partie 3 sur 14
Suivant
Construire un squelette admin avec shadcn/ui : Sidebar + Layout, bonnes pratiques
Maîtrisez les bonnes pratiques d'intégration shadcn/ui Sidebar et Next.js Layout. De l'architecture des composants au design responsive et au contrôle d'accès — un squelette admin extensible pas à pas, avec exemples de code complets
Partie 5 sur 14



Commentaires
Connectez-vous avec GitHub pour laisser un commentaire