Niveau 25 — Les Composants UI

Les Composants UI

Bibliothèque complète de composants UI en CSS pur : boutons, cartes, navigation, feedback, overlays, formulaires et layouts. Chaque composant est déclinable, accessible et modulaire.

1. Comprendre les composants UI

En une phrase : Un composant UI est un élément d'interface réutilisable, autonome et modulaire, qui encapsule une structure HTML, un style CSS et éventuellement un comportement JS pour former les briques de base d'une interface utilisateur.

Les composants UI sont les briques fondamentales d'une interface. Chaque composant possède :

ANATOMIE D'UN COMPOSANT UI
═══════════════════════════

  Props (attributs)          États
  ──────────────────         ──────────────
  • variant (primary...)     • :hover
  • size (sm, md, lg)        • :focus
  • disabled                 • :active
  • loading                  • .is-loading
  • icon                     • .is-disabled

  ┌─────────────────────────────────────┐
  │  ┌──────────┐  ┌────────────────┐   │
  │  │  Icone   │  │  Texte label   │   │  ← Structure HTML
  │  └──────────┘  └────────────────┘   │
  └─────────────────────────────────────┘
           │               │
           └───────┬───────┘
                   │
  ┌─────────────────────────────────────┐
  │  padding, border-radius, shadow     │  ← Style CSS
  │  colors, transitions, focus ring    │
  └─────────────────────────────────────┘

Structure typique d'un composant UI

Principe : Chaque composant CSS doit pouvoir fonctionner de manière autonome sans dépendre d'un contexte spécifique. C'est la base de la réutilisabilité.

2. Syntaxe et structure

Convention : Chaque composant suit la convention BEM (voir Niveau 24). Le nom du bloc est le nom du composant, les éléments et modificateurs en découlent.
/* Structure BEM pour chaque composant */
.nom-composant { }                    /* Bloc */
.nom-composant__element { }           /* Élément */
.nom-composant--modificateur { }      /* Modificateur */
.nom-composant__element--modificateur { } /* Élément modifié */

/* Exemple avec un bouton */
.btn { }
.btn__icon { }
.btn--primary { }
.btn--small { }
.btn--loading { }
.btn__icon--left { }

/* Exemple avec une carte */
.card { }
.card__image { }
.card__title { }
.card__body { }
.card--featured { }
.card--compact { }

3. Visualisation — Aperçu des composants

CATÉGORIES DE COMPOSANTS
═══════════════════════════

  🔘 BOUTONS          7 variantes × 3 tailles
  🃏 CARTES           7 types (basic, product, profile, stats, blog, team, testimonial)
  🧭 NAVIGATION       6 composants (navbar, sidebar, breadcrumbs, pagination, tabs, mega-menu)
  💬 FEEDBACK         5 composants (alert, toast, badge, progress, skeleton)
  🪟 OVERLAY          5 composants (modal, tooltip, popover, dropdown, accordion)
  📝 FORMULAIRES      6 composants (input-group, checkbox, radio, switch, select, range, file-upload)
  📐 LAYOUT           3 composants (hero, footer, container)

  Total : 39+ composants

Vue d'ensemble des composants couverts dans ce chapitre

4. Exemples progressifs — Tous les composants

4.1 Boutons

Variantes de boutons
Tailles
États
<!-- HTML Boutons -->
<button class="btn btn--primary btn--md">Primaire</button>
<button class="btn btn--secondary btn--md">Secondaire</button>
<button class="btn btn--outline btn--md">Outline</button>
<button class="btn btn--ghost btn--md">Ghost</button>
<button class="btn btn--primary btn--icon">★</button>
<button class="btn btn--primary btn--loading">Chargement</button>
<button class="btn btn--primary btn--disabled">Désactivé</button>

<!-- Tailles -->
<button class="btn btn--primary btn--sm">Small</button>
<button class="btn btn--primary btn--md">Medium</button>
<button class="btn btn--primary btn--lg">Large</button>
/* CSS Boutons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-weight: 600;
  border: 2px solid transparent;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s;
  font-family: inherit;
}

/* Variantes */
.btn--primary { background: var(--color-primary); color: white; }
.btn--primary:hover { background: var(--color-primary-hover); }
.btn--secondary { background: #64748b; color: white; }
.btn--outline { background: transparent; color: var(--color-primary); border-color: var(--color-primary); }
.btn--outline:hover { background: var(--color-primary); color: white; }
.btn--ghost { background: transparent; color: #64748b; }
.btn--ghost:hover { background: #f1f5f9; }

/* Tailles */
.btn--sm { padding: 0.4rem 0.8rem; font-size: 0.8rem; }
.btn--md { padding: 0.55rem 1.1rem; font-size: 0.9rem; }
.btn--lg { padding: 0.75rem 1.5rem; font-size: 1rem; }

/* États */
.btn--loading { color: transparent !important; pointer-events: none; position: relative; }
.btn--loading::after {
  content: '';
  position: absolute;
  width: 1rem;
  height: 1rem;
  border: 2px solid rgba(255,255,255,0.3);
  border-top-color: white;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}
.btn--disabled { opacity: 0.5; cursor: not-allowed; pointer-events: none; }

/* Icône */
.btn--icon { width: 2.2rem; height: 2.2rem; padding: 0; border-radius: 50%; }

4.2 Cartes

Carte basique

Titre de la carte
Description du contenu avec quelques lignes de texte pour montrer l'espacement.
Deuxième carte
Un autre exemple de carte avec une couleur différente pour montrer la flexibilité.

Carte produit

Casque Audio Pro
79,99 € 119,99 €
Enceinte Bluetooth
49,99 €
Clavier Mécanique
129,99 €

Carte profil

JD
Jean Dupont
Développeur Frontend
ML
Marie Lambert
UX Designer

Carte statistiques

📊
12 847
Visiteurs
↑ +12.5%
💰
24 521 €
Revenus
↑ +8.2%
📦
1 234
Commandes
↓ -3.1%
4.8/5
Note moyenne
↑ +0.2

Carte blog

15 mars 2026 · 8 min de lecture · CSS
Guide complet de l'architecture CSS moderne
Découvrez les meilleures pratiques pour organiser vos feuilles de style sur des projets de toute taille. De BEM à ITCSS, passons en revue toutes les méthodologies.

Carte équipe

AP
Alice Petit
Lead Developer
BM
Bruno Martin
UI Designer
CD
Claire Dubois
Project Manager

Carte témoignage

"Ce cours m'a permis de comprendre les fondamentaux du CSS moderne. Les exemples pratiques sont excellents et la progression est bien pensée."
SL
Sophie Leroy
Développeuse Full-Stack

4.3 Navigation

Navbar

<!-- Navbar -->
<nav class="navbar">
  <a href="#" class="navbar__logo">MonSite</a>
  <ul class="navbar__links">
    <li><a href="#" class="navbar__link navbar__link--active">Accueil</a></li>
    <li><a href="#" class="navbar__link">Produits</a></li>
  </ul>
  <a href="#" class="navbar__cta">Connexion</a>
</nav>

Sidebar navigation

Zone de contenu

Le contenu principal s'affiche ici à côté de la sidebar.

Breadcrumbs

Pagination

Tabs

Contenu de l'onglet sélectionné. Changez d'onglet pour voir l'interaction.
<!-- Tabs -->
<div class="tabs">
  <button class="tab tab--active">Onglet 1</button>
  <button class="tab">Onglet 2</button>
  <button class="tab">Onglet 3</button>
</div>
/* CSS Tabs */
.tabs { display: flex; border-bottom: 2px solid #e2e8f0; }

.tab {
  padding: 0.6rem 1.25rem;
  border: none;
  background: transparent;
  color: #64748b;
  font-weight: 500;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition: all 0.2s;
}

.tab:hover { color: #1e293b; }
.tab--active { color: #2563eb; border-bottom-color: #2563eb; font-weight: 600; }

4.4 Composants de feedback

Alertes

Votre profil a été mis à jour avec succès.
⚠️ Votre email n'a pas été vérifié. Veuillez consulter votre boîte de réception.
Une erreur est survenue lors de la sauvegarde. Réessayez.
ℹ️ Une nouvelle version est disponible. Mettez à jour pour accéder aux dernières fonctionnalités.
<!-- Alertes -->
<div class="alert alert--success">✅ Opération réussie</div>
<div class="alert alert--warning">⚠️ Attention...</div>
<div class="alert alert--error">❌ Erreur...</div>
<div class="alert alert--info">ℹ️ Information</div>

Toast notification

Fichier sauvegardé avec succès

Badges

En ligne En attente Hors ligne Nouveau
🛒 Panier 3 📩 Messages 12
<!-- Badges -->
<span class="badge badge--success">En ligne</span>
<span class="badge badge--warning">En attente</span>
<span class="badge badge--error">Hors ligne</span>

<!-- Badge compteur -->
<span class="badge badge--count">3</span>

Barres de progression

Upload en cours... 72%
Stockage utilisé 45%
Mémoire 89%
<!-- Progress bar -->
<div class="progress">
  <div class="progress__bar progress__bar--blue" style="width: 72%;"></div>
</div>

Skeleton loader

4.5 Overlays

Modal

Confirmer la suppression
Êtes-vous sûr de vouloir supprimer cet élément ? Cette action est irréversible.
<!-- Modal -->
<div class="modal-overlay">
  <div class="modal">
    <div class="modal__header">
      <h3 class="modal__title">Titre</h3>
      <button class="modal__close">✕</button>
    </div>
    <div class="modal__body">Contenu...</div>
    <div class="modal__footer">
      <button class="btn btn--ghost">Annuler</button>
      <button class="btn btn--primary">Confirmer</button>
    </div>
  </div>
</div>

Tooltip

Ceci est un tooltip !
Plus d'informations ici
Besoin d'aide ?
<!-- Tooltip -->
<div class="tooltip-wrapper">
  <button class="btn btn--primary">Hover</button>
  <div class="tooltip">Texte du tooltip</div>
</div>
/* CSS Tooltip */
.tooltip-wrapper { position: relative; display: inline-block; }
.tooltip-wrapper:hover .tooltip { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }

.tooltip {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: #1e293b;
  color: white;
  padding: 0.4rem 0.75rem;
  border-radius: 6px;
  font-size: 0.8rem;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  transition: all 0.2s;
}

.tooltip::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: #1e293b;
}

Popover

Paramètres rapides
Configurez vos préférences directement.

Dropdown menu

<!-- Dropdown -->
<div class="dropdown">
  <button class="btn btn--outline dropdown__trigger">Options ▾</button>
  <div class="dropdown__menu">
    <a href="#" class="dropdown__item">Modifier</a>
    <a href="#" class="dropdown__item">Supprimer</a>
  </div>
</div>

Accordion

BEM (Block Element Modifier) est une méthodologie de nommage CSS qui organise le code en blocs (composants), éléments (parties d'un bloc) et modificateurs (variantes). Elle favorise la maintenabilité et la réutilisabilité.
Utilisez le kebab-case (tirets) pour les noms de classes. En BEM, séparez le bloc et l'élément avec __ et le modificateur avec --. Exemple : .card__title--large.
Il n'y a pas de "meilleure" méthodologie universelle. BEM est le meilleur choix pour la majorité des projets. Pour les très gros projets, ITCSS + BEM est recommandé. Pour le prototypage rapide, Tailwind CSS (utility-first) est idéal.
<!-- Accordion -->
<div class="accordion">
  <div class="accordion__item accordion__item--open">
    <button class="accordion__header">
      <span>Question</span>
      <span class="accordion__icon">▼</span>
    </button>
    <div class="accordion__body">Réponse...</div>
  </div>
</div>

4.6 Composants de formulaire

Input groups

🔍
@gmail.com
https://
<!-- Input group -->
<div class="input-group">
  <span class="input-group__prefix">🔍</span>
  <input type="text" class="input-group__input" placeholder="Rechercher...">
</div>

<div class="input-group">
  <input type="email" class="input-group__input" placeholder="Email">
  <span class="input-group__suffix">@gmail.com</span>
</div>

Checkbox, Radio, Switch

<!-- Checkbox -->
<label class="checkbox">
  <input type="checkbox">
  <span class="checkbox__check">✓</span>
  <span>Label</span>
</label>

<!-- Radio -->
<label class="radio">
  <input type="radio" name="group">
  <span class="radio__circle"></span>
  <span>Option</span>
</label>

<!-- Switch -->
<label class="switch">
  <input type="checkbox">
  <span class="switch__track">
    <span class="switch__thumb"></span>
  </span>
  <span>Label</span>
</label>

Select dropdown

Range slider

Luminosité 50%

File upload

📁
Cliquez pour upload ou glissez-déposez
PNG, JPG, PDF (max. 5MB)

4.7 Composants de layout

Hero section

Maîtrisez le CSS moderne
De zéro à expert en 30 niveaux. Apprenez les concepts, les bonnes pratiques et créez des interfaces professionnelles.
<!-- Hero -->
<section class="hero">
  <h1 class="hero__title">Titre principal</h1>
  <p class="hero__text">Sous-titre ou description</p>
  <div class="hero__actions">
    <button class="btn btn--primary btn--lg">CTA</button>
    <button class="btn btn--ghost btn--lg">Secondaire</button>
  </div>
</section>

Footer multi-colonnes

<!-- Footer -->
<footer class="footer">
  <div class="footer__grid">
    <div>
      <div class="footer__brand">MonSite</div>
      <p class="footer__desc">Description...</p>
    </div>
    <div>
      <h4 class="footer__heading">Liens</h4>
      <a href="#" class="footer__link">Page 1</a>
      <a href="#" class="footer__link">Page 2</a>
    </div>
  </div>
  <div class="footer__bottom">© 2026 MonSite</div>
</footer>

5. Erreurs fréquentes

Erreur 1 : Utiliser des ID au lieu de classes pour les composants
/* FAUX — les IDs sont uniques, pas réutilisables */
#main-button { background: #2563eb; }
#header-nav { display: flex; }

/* CORRECT — les classes sont réutilisables */
.btn--primary { background: #2563eb; }
.navbar { display: flex; }
Erreur 2 : Composants monolithiques sans variantes
/* FAUX — un seul style, pas de flexibilité */
.btn {
  background: #2563eb;
  color: white;
  padding: 0.5rem 1rem;
  border-radius: 8px;
  font-size: 14px;
}

/* CORRECT — composant avec variantes et tailles */
.btn { /* styles de base */ }
.btn--primary { /* variante */ }
.btn--outline { /* variante */ }
.btn--sm { /* taille */ }
.btn--lg { /* taille */ }
Erreur 3 : Oublier les états hover/focus/disabled
/* FAUX — pas de retour visuel pour l'utilisateur */
.btn { background: #2563eb; }

/* CORRECT — tous les états couverts */
.btn { background: #2563eb; transition: all 0.2s; }
.btn:hover { background: #1d4ed8; }
.btn:focus-visible { box-shadow: 0 0 0 3px rgba(37,99,235,0.3); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
Erreur 4 : Imbriquer les composants (couplage fort)
/* FAUX — le composant dépend du parent */
.sidebar .card { padding: 1rem; }
.nav .btn { font-size: 0.8rem; }

/* CORRECT — le composant est autonome */
.card { padding: 1.5rem; }
.card--compact { padding: 1rem; }
.btn--sm { font-size: 0.8rem; }
Erreur 5 : Nommer les classes selon l'apparence plutôt que la fonction
/* FAUX — nommage visuel */
.blue-box { background: blue; }
.rounded { border-radius: 50%; }
.shadow { box-shadow: ...; }

/* CORRECT — nommage sémantique */
.alert--info { background: #eff6ff; }
.avatar { border-radius: 50%; }
.card { box-shadow: var(--shadow-sm); }

6. Bonnes pratiques

Règles d'or pour les composants UI :
  • Autonomie — chaque composant doit fonctionner sans contexte externe.
  • Variantes via modificateurs BEM — pas de classes multiples imbriquées.
  • Couverture des états — hover, focus, active, disabled, loading pour chaque composant interactif.
  • Accessibilité — rôles ARIA, navigation au clavier, contraste suffisant.
  • Responsive — chaque composant doit s'adapter à sa zone de contenu.
  • Variables CSS — utiliser des tokens pour les couleurs, espaces, ombres.
  • Fichier par composant — un fichier CSS par composant pour la maintenabilité.
  • Nommage prévisible — suivre BEM strictement pour que tout le monde comprenne le code.

Checklist de qualité pour un composant

Critère Vérification
Nommage BEM .bloc__element--modificateur respecté
Variantes Modificateurs pour taille, couleur, variante
États hover, focus-visible, active, disabled
Accessibilité Contraste AA, focus visible, rôles ARIA
Responsive Testé sur mobile, tablette, desktop
Autonomie Pas de dépendance au contexte parent
Transitions Changements d'état fluides (transition)
DRY Pas de duplication, tokens CSS utilisés

7. Mini-défi

Défi 1 : Bouton complet

Créez un composant bouton avec : 4 variantes (primary, secondary, outline, ghost), 3 tailles (sm, md, lg), état loading avec spinner CSS, état disabled, et support d'icône à gauche.

Défi 2 : Carte produit e-commerce

Créez une carte produit avec : image, badge promo (-30%), titre, note (étoiles), prix barré, prix actuel, bouton "Ajouter au panier", et un modificateur "épuisé" qui grise le tout.

Défi 3 : Formulaire complet

Créez un formulaire de connexion avec : input group (email avec icône), input group (mot de passe avec icône œil), checkbox "Se souvenir de moi", bouton "Se connecter", lien "Mot de passe oublié", et un divider "ou continuer avec" suivi de boutons sociaux.

Défi 4 : Modal avec formulaire

Créez un modal de confirmation contenant : un titre, un texte de description, un input de confirmation, et deux boutons (Annuler / Confirmer). Le modal doit avoir un overlay sombre et une animation d'entrée.

Défi 5 : Dashboard complet

Assemblez au moins 5 composants de ce cours pour créer un mini-dashboard : navbar, sidebar, 3 cartes stats, une barre de progression, et un tableau avec skeleton loaders.

8. Projets pratiques

Projet 1 : Design system UI complet

Créez un design system contenant tous les composants de ce chapitre, organisé en fichiers modulaires avec BEM :

  • Tous les boutons (7 variantes × 3 tailles)
  • Toutes les cartes (7 types)
  • Toute la navigation (6 composants)
  • Tous les feedbacks (5 composants)
  • Tous les overlays (5 composants)
  • Tous les formulaires (7 composants)
  • Les layouts (3 composants)
  • Design tokens (variables) pour tout le système
  • Dark mode avec variables CSS

Projet 2 : Landing page complète

Créez une landing page en assemblant les composants :

  • Navbar avec logo, links et CTA
  • Hero section avec titre, description et 2 boutons
  • Section fonctionnalités avec 3 cartes stats
  • Section témoignages avec 2 cartes testimonial
  • Section pricing avec 3 cartes produit
  • Footer multi-colonnes
  • Modal newsletter au scroll

Projet 3 : Mini-application e-commerce

Créez une page produit e-commerce avec :

  • Navbar avec panier (badge compteur)
  • Breadcrumbs
  • Carte produit avec galerie
  • Sélecteur de taille (radio custom)
  • Quantité (input number custom)
  • Boutons "Ajouter au panier" et "Acheter"
  • Section avis avec skeleton loaders
  • Accordion pour détails produit
  • Footer

9. Révision

Récapitulatif des composants

Catégorie Composants Variantes principales
Boutons 7 types primary, secondary, outline, ghost, danger, success, icon
Cartes 7 types basic, product, profile, stats, blog, team, testimonial
Navigation 6 types navbar, sidebar, breadcrumbs, pagination, tabs, mega-menu
Feedback 5 types alert, toast, badge, progress, skeleton
Overlays 5 types modal, tooltip, popover, dropdown, accordion
Formulaires 7 types input-group, checkbox, radio, switch, select, range, file-upload
Layout 3 types hero, footer, container

Quiz rapide

  1. Qu'est-ce qu'un composant UI et quels sont ses attributs principaux ?
  2. Comment nommer un modificateur de composant en BEM ?
  3. Quels états doit couvrir un composant interactif ?
  4. Pourquoi un composant doit-il être autonome ?
  5. Comment créer un tooltip CSS-only ?
  6. Quelle est la différence entre un popover et un tooltip ?
  7. Comment implémenter un switch custom en CSS ?
  8. Pourquoi utiliser skeleton loaders au lieu de spinners ?
  9. Quel composant de navigation est adapté pour plus de 7 pages ?
  10. Comment créer un accordion CSS-only ?
Réponses :
  1. Un élément d'interface réutilisable avec : structure HTML, style CSS, variantes (taille, couleur) et états (hover, focus, disabled).
  2. Avec -- : .btn--primary, .card--featured.
  3. hover, focus-visible, active, disabled, loading.
  4. Pour la réutilisabilité — il doit fonctionner dans n'importe quel contexte sans dépendre du parent.
  5. Avec position: absolute + opacity/visibility sur :hover du parent.
  6. Le tooltip est un simple texte d'aide. Le popover contient du contenu riche (titre, texte, boutons).
  7. Avec <input type="checkbox"> caché + <span> stylé en track + thumb, toggled via :checked.
  8. Les skeleton loaders montrent la structure future, les spinners indiquent juste un chargement. Les skeletons réduisent le layout shift.
  9. La pagination.
  10. Avec des détails/summary ou des input checkbox cachés + label pour contrôler l'affichage via :checked.

Cheat sheet rapide

/* ============================================
   COMPOSANTS UI — Cheat Sheet
   ============================================ */

/* --- BOUTONS --- */
.btn { display: inline-flex; align-items: center; gap: 0.5rem;
       padding: 0.55rem 1.1rem; border: 2px solid transparent;
       border-radius: 8px; font-weight: 600; cursor: pointer;
       transition: all 0.2s; }
.btn--primary { background: #2563eb; color: white; }
.btn--outline { background: transparent; color: #2563eb; border-color: #2563eb; }
.btn--sm { padding: 0.4rem 0.8rem; font-size: 0.8rem; }
.btn--lg { padding: 0.75rem 1.5rem; font-size: 1rem; }

/* --- CARTES --- */
.card { background: white; border: 1px solid #e2e8f0;
        border-radius: 12px; overflow: hidden; }
.card__body { padding: 1.25rem; }
.card__title { font-weight: 700; margin-bottom: 0.5rem; }

/* --- ALERTES --- */
.alert { padding: 0.75rem 1rem; border-radius: 8px; display: flex; gap: 0.75rem; }
.alert--success { background: #f0fdf4; color: #166534; }
.alert--error { background: #fef2f2; color: #991b1b; }

/* --- TOOLTIP --- */
.tooltip-wrapper:hover .tooltip { opacity: 1; visibility: visible; }
.tooltip { position: absolute; bottom: calc(100% + 8px); left: 50%;
           transform: translateX(-50%); background: #1e293b;
           color: white; padding: 0.4rem 0.75rem; border-radius: 6px;
           opacity: 0; visibility: hidden; transition: all 0.2s; }

/* --- MODAL --- */
.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5);
                 display: flex; align-items: center; justify-content: center; }
.modal { background: white; border-radius: 16px; max-width: 480px; width: 90%;
         box-shadow: 0 20px 60px rgba(0,0,0,0.15); }

/* --- SWITCH --- */
.switch__track { width: 2.75rem; height: 1.5rem; background: #d1d5db;
                 border-radius: 9999px; position: relative; transition: background 0.2s; }
.switch input:checked + .switch__track { background: #2563eb; }
.switch__thumb { position: absolute; width: 1.2rem; height: 1.2rem;
                 background: white; border-radius: 50%; top: 0.15rem; left: 0.15rem;
                 transition: transform 0.2s; }
.switch input:checked + .switch__track .switch__thumb { transform: translateX(1.25rem); }