Pourquoi les cartes dominent le web moderne
La carte (card) est le composant UI le plus répandu sur le web. Google, Facebook, Airbnb, Amazon — tous structurent leur contenu en cartes. Pourquoi ? Parce que la carte est le conteneur parfait : elle regroupe texte, image et action dans un bloc autonome, facilement scannable, naturellement responsive, et infiniment réutilisable.
Anatomie d’une carte bien conçue
Une carte professionnelle combine ces éléments dans un ordre hiérarchique :
- Image/Média (optionnel) — En haut, ratio fixe (16:9, 4:3 ou 1:1). Attire l’œil en premier
- Titre — Court, descriptif, en gras. Maximum 2 lignes avec troncature
- Metadata (optionnel) — Date, auteur, catégorie, durée. Texte petit, couleur discrète
- Description — 2-3 lignes maximum. Résume l’essentiel. Troncature avec -webkit-line-clamp
- Tags/Badges (optionnel) — Catégorie, statut, prix
- Action — Bouton, lien, ou la carte entière est cliquable
6 types de cartes avec code complet
1. Product Card (e-commerce)
<article class="product-card">
<div class="product-card__image">
<img src="produit.webp" alt="Sac en cuir artisanal" loading="lazy">
<span class="badge">-20%</span>
</div>
<div class="product-card__body">
<p class="product-card__category">Maroquinerie</p>
<h3 class="product-card__title">Sac en cuir artisanal de Saint-Louis</h3>
<div class="product-card__price">
<span class="price-old">25 000 FCFA</span>
<span class="price-current">20 000 FCFA</span>
</div>
<button class="btn-primary">Ajouter au panier</button>
</div>
</article>
<style>
.product-card {
border-radius: 12px;
overflow: hidden;
border: 1px solid #e5e7eb;
transition: box-shadow 0.2s, transform 0.2s;
}
.product-card:hover {
box-shadow: 0 8px 24px rgba(0,0,0,0.1);
transform: translateY(-2px);
}
.product-card__image {
position: relative;
aspect-ratio: 1;
overflow: hidden;
}
.product-card__image img {
width: 100%; height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
.product-card:hover .product-card__image img {
transform: scale(1.05);
}
.badge {
position: absolute; top: 12px; left: 12px;
background: #EF4444; color: white;
padding: 4px 10px; border-radius: 6px;
font-size: 0.8rem; font-weight: 600;
}
.product-card__body { padding: 16px; }
.product-card__category {
font-size: 0.8rem; color: #6b7280;
text-transform: uppercase; letter-spacing: 0.05em;
}
.product-card__title {
font-size: 1rem; font-weight: 600; margin: 4px 0 8px;
}
.price-old {
text-decoration: line-through; color: #9ca3af;
margin-right: 8px;
}
.price-current {
font-weight: 700; color: #EF4444; font-size: 1.1rem;
}
</style>
2. Blog Card
<article class="blog-card">
<img src="article.webp" alt="Titre de l'article"
class="blog-card__image" loading="lazy">
<div class="blog-card__body">
<span class="blog-card__tag">Design</span>
<h3 class="blog-card__title">
<a href="/article">Comment créer un design system complet</a>
</h3>
<p class="blog-card__excerpt">
Découvrez les étapes pour construire un design system
qui scale avec votre équipe...
</p>
<div class="blog-card__meta">
<img src="avatar.webp" alt="" class="avatar">
<span>Moussa Diop</span>
<span>·</span>
<time datetime="2025-01-15">15 jan 2025</time>
<span>·</span>
<span>5 min de lecture</span>
</div>
</div>
</article>
<style>
.blog-card__image {
width: 100%; aspect-ratio: 16/9;
object-fit: cover; border-radius: 12px 12px 0 0;
}
.blog-card__body { padding: 20px; }
.blog-card__tag {
display: inline-block; padding: 4px 12px;
background: #EFF6FF; color: #1D4ED8;
border-radius: 9999px; font-size: 0.8rem; font-weight: 500;
}
.blog-card__title a {
color: inherit; text-decoration: none;
font-size: 1.25rem; line-height: 1.3;
}
.blog-card__title a:hover { color: #1D4ED8; }
.blog-card__excerpt {
color: #6b7280; margin: 8px 0 16px;
display: -webkit-box; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; overflow: hidden;
}
.blog-card__meta {
display: flex; align-items: center; gap: 8px;
font-size: 0.85rem; color: #9ca3af;
}
.avatar { width: 28px; height: 28px; border-radius: 50%; }
</style>
3. Pricing Card
<div class="pricing-card pricing-card--featured">
<span class="pricing-badge">Populaire</span>
<h3 class="pricing-name">Professionnel</h3>
<div class="pricing-price">
<span class="price-amount">350 000</span>
<span class="price-currency">FCFA</span>
</div>
<p class="pricing-desc">Pour les PME qui veulent un site complet</p>
<ul class="pricing-features">
<li>✓ Site responsive 5-10 pages</li>
<li>✓ Paiements Wave et Orange Money</li>
<li>✓ SEO de base</li>
<li>✓ Formation 2h incluse</li>
<li>✓ Support 3 mois</li>
</ul>
<a href="#contact" class="btn-primary">Choisir ce plan</a>
</div>
<style>
.pricing-card {
padding: 32px; border-radius: 16px;
border: 1px solid #e5e7eb; text-align: center;
}
.pricing-card--featured {
border: 2px solid #3B82F6;
box-shadow: 0 8px 32px rgba(59,130,246,0.15);
position: relative; transform: scale(1.05);
}
.pricing-badge {
position: absolute; top: -12px; left: 50%;
transform: translateX(-50%);
background: #3B82F6; color: white;
padding: 4px 16px; border-radius: 9999px;
font-size: 0.8rem; font-weight: 600;
}
.price-amount { font-size: 3rem; font-weight: 800; }
.pricing-features {
list-style: none; padding: 0; text-align: left;
margin: 24px 0;
}
.pricing-features li { padding: 8px 0; border-bottom: 1px solid #f3f4f6; }
</style>
4. Testimonial Card
<blockquote class="testimonial-card">
<div class="testimonial-stars">★★★★★</div>
<p class="testimonial-text">
"Notre CA en ligne a triplé en 3 mois grâce au site
créé par ITSkillsCenter. Le support est exceptionnel."
</p>
<footer class="testimonial-author">
<img src="awa.webp" alt="" class="testimonial-avatar">
<div>
<cite class="testimonial-name">Awa Ndiaye</cite>
<p class="testimonial-rôle">Fondatrice, DakarStyle</p>
</div>
</footer>
</blockquote>
Grilles de cartes responsives
/* Grille auto-responsive — pas de media queries nécessaires */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
}
/* Avec container queries pour des cartes adaptatives */
.card-container {
container-type: inline-size;
}
@container (min-width: 500px) {
.blog-card {
display: grid;
grid-template-columns: 200px 1fr;
}
.blog-card__image {
border-radius: 12px 0 0 12px;
height: 100%;
}
}
/* Masonry layout (CSS natif, support en cours) */
.masonry-grid {
columns: 3;
column-gap: 24px;
}
.masonry-grid .card {
break-inside: avoid;
margin-bottom: 24px;
}
Carte cliquable accessible
<!-- Pattern : lien qui couvre toute la carte -->
<article class="card">
<img src="..." alt="...">
<h3><a href="/article" class="card-link">Titre</a></h3>
<p>Description...</p>
</article>
<style>
.card { position: relative; }
/* Le lien couvre toute la carte via pseudo-élément */
.card-link::after {
content: '';
position: absolute;
inset: 0;
}
/* Focus visible sur la carte entière */
.card:has(.card-link:focus-visible) {
outline: 3px solid #3B82F6;
outline-offset: 2px;
}
/* Autres liens à l'intérieur restent cliquables */
.card a:not(.card-link) {
position: relative;
z-index: 1;
}
</style>
Erreurs courantes
- Cartes de hauteurs différentes — Utilisez CSS Grid avec subgrid ou des hauteurs fixes pour les images et la troncature pour le texte
- Trop d’information — Une carte doit donner envie de cliquer, pas tout dire. Limitez à titre + 2 lignes + 1 action
- Hover sans focus — Si vous avez un effet au hover, il faut le même effet au focus clavier pour l’accessibilité
- Images sans ratio fixe — Les images de tailles différentes créent une grille chaotique. Fixez le ratio avec aspect-ratio
- Pas de feedback tactile — Sur mobile, ajoutez un état :activé avec un léger changement de couleur ou d’ombre
Les cartes sont le composant le plus polyvalent du web. Maîtrisez les 4 types de base (product, blog, pricing, testimonial), combinez-les avec CSS Grid pour des layouts responsives, et respectez l’accessibilité avec le pattern de lien englobant. Vous aurez les briques pour construire n’importe quelle interface moderne.
Étape 1 : poser la grille avant de dessiner la carte
Avant d’ouvrir Figma ou d’écrire la moindre ligne de CSS, dessinez la grille. Une carte n’existe pas seule : elle vit dans un ensemble de 3, 6 ou 12 cartes alignées. Pour un site de catalogue de formations vu depuis un smartphone Tecno ou Infinix à Dakar (largeur 360 à 412 pixels), choisissez une grille à une colonne sur mobile, deux colonnes à partir de 768 pixels, trois ou quatre colonnes au-delà de 1280 pixels.
.cards-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
Cette règle CSS crée une grille fluide sans media query. Le navigateur choisit automatiquement le nombre de colonnes selon la largeur disponible. Le résultat : sur un Tecno Spark à 360 pixels, vous obtenez une colonne ; sur un MacBook à 1440 pixels, cinq colonnes. Aucun bug d’overflow horizontal.
Étape 2 : définir l’anatomie d’une carte
Une carte bien conçue contient toujours les mêmes blocs dans le même ordre : un visuel optionnel en haut, un titre court, un texte descriptif de 2 à 3 lignes, des métadonnées (date, auteur, prix), et un appel à l’action. Cet ordre est cognitif : l’œil scanne en F sur desktop et en Z sur mobile. Tout élément hors séquence ralentit la lecture.
<article class="card">
<img class="card__media" src="..." alt="" loading="lazy" />
<header class="card__header"><h3>Formation Python à Dakar</h3></header>
<p class="card__excerpt">Trois mois en présentiel, certifiante, ouverte aux débutants.</p>
<footer class="card__meta"><span>120 000 FCFA</span><a href="...">S'inscrire</a></footer>
</article>
L’utilisation de balises sémantiques (article, header, footer) améliore l’accessibilité et le référencement. Les lecteurs d’écran annoncent correctement la structure. Pensez à fixer alt="" si l’image est purement décorative, sinon décrivez-la en français.
Étape 3 : choisir l’élévation et l’ombre
L’ombre est ce qui sépare une carte plate d’une carte qui « flotte ». Trois niveaux d’élévation suffisent : niveau 1 (état de repos), niveau 2 (au survol), niveau 3 (carte active ou sélectionnée). Évitez les ombres trop sombres qui dénoncent les tutoriels Bootstrap des années 2018.
.card {
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
transition: box-shadow 200ms ease, transform 200ms ease;
}
.card:hover {
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);
transform: translateY(-2px);
}
Le translation négative de 2 pixels donne l’illusion que la carte se soulève. Combinée avec l’ombre plus diffuse, l’effet est subtil mais perceptible. La transition de 200 ms reste sous la limite de fluidité (300 ms maximum pour ne pas paraître lente).
Étape 4 : gérer la typographie dans une carte
Le titre de la carte doit utiliser une taille hiérarchiquement plus petite que le titre de la page. Si la page est en H1 à 32 pixels, les cartes peuvent être en H3 à 18 ou 20 pixels. La hauteur de ligne est cruciale : 1.4 pour le titre, 1.6 pour le texte courant. En français, les lignes sont plus longues qu’en anglais (15 % de plus en moyenne) ; prévoyez des cartes plus larges ou des titres plus courts.
.card__header h3 { font-size: 1.125rem; line-height: 1.4; margin: 0 0 0.5rem; }
.card__excerpt { font-size: 0.9375rem; line-height: 1.6; color: #475569; }
Les valeurs en rem respectent la préférence utilisateur (taille de police par défaut). Un visiteur malvoyant qui a augmenté la taille de police dans son navigateur verra des cartes proportionnellement plus grandes, sans casser la mise en page.
Étape 5 : tronquer le texte sans casser la grille
Une carte avec un titre de 5 lignes et une autre avec un titre de 1 ligne déséquilibrent la grille. Tronquez intelligemment avec line-clamp. Cette propriété est désormais standard dans tous les navigateurs modernes (Chrome, Firefox, Safari, Edge depuis 2023).
.card__excerpt {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
Cette technique force le texte à 3 lignes maximum avec ellipsis automatique. Pour le titre, utilisez line-clamp: 2. Le résultat : toutes les cartes ont la même hauteur visible sans calcul JavaScript, et l’alignement reste parfait même avec du contenu de longueur variable.
Étape 6 : rendre la carte cliquable en entier
Sur mobile, un visiteur qui touche le titre, le visuel ou la zone vide doit arriver sur la fiche détaillée. Évitez l’erreur de coller un onclick JavaScript : préférez la technique du lien étendu, accessible aux lecteurs d’écran et au clavier.
.card { position: relative; }
.card__title-link::after {
content: "";
position: absolute;
inset: 0;
}
Le pseudo-élément ::after du lien recouvre toute la carte. Le clic fonctionne partout. Le focus clavier reste sur le lien. Les lecteurs d’écran annoncent un seul lien par carte au lieu de trois ou quatre. C’est la solution recommandée par le W3C depuis 2022.
Étape 7 : adapter la carte aux contextes mobile money et tickets
Pour un site qui vend des cours, des billets ou des abonnements payables en Wave ou Orange Money, la carte doit afficher un prix en FCFA et un bouton d’action proéminent. Convertissez les prix EUR en FCFA en multipliant par 655,957 (taux fixe BCEAO). N’arrondissez pas à la dizaine de FCFA : 9,15 EUR donne 6 002 FCFA exactement.
const eurToFcfa = (eur) => Math.round(eur * 655.957);
console.log(eurToFcfa(15));
// Sortie : 9839
La fonction est pure et testable. Pour 15 EUR, le résultat est 9 839 FCFA. Affichez ensuite le montant avec un séparateur des milliers : new Intl.NumberFormat('fr-FR').format(9839) renvoie « 9 839 ». L’espace insécable est conforme à la typographie française et facile à lire pour un visiteur ouest-africain.
Étape 8 : tester l’accessibilité et le contraste
Une carte mal contrastée disparaît au soleil de Dakar à 14 h. Visez un ratio WCAG AA minimum (4,5:1 pour le texte courant, 3:1 pour les gros titres). Utilisez l’outil Lighthouse ou l’extension axe DevTools pour mesurer. Évitez le gris clair sur blanc en dessous de #595959 ; cela passe rarement les seuils.
# Audit Lighthouse en ligne de commande
npx lighthouse https://votre-site.tld --only-categories=accessibility --view
Le rapport HTML s’ouvre automatiquement. Visez un score d’accessibilité supérieur à 95. Les erreurs courantes sur les cartes sont les images sans alt, les boutons sans texte visible, et les contrastes insuffisants sur les badges colorés.
Sur le même thème, lisez notre tutoriel WooCommerce qui montre comment intégrer ces cartes dans une boutique, et notre guide HTTP/3 pour optimiser le chargement des images de cartes.
Étape 9 : préparer les variantes thématiques (sombre, clair, daltonien)
Une carte doit fonctionner en mode clair et en mode sombre sans intervention. Utilisez les variables CSS et la requête média prefers-color-scheme. Pour un visiteur daltonien, ne reposez jamais l’information uniquement sur la couleur (un badge rouge « Complet » doit aussi avoir un texte explicite).
:root { --card-bg: #ffffff; --card-fg: #0f172a; --card-muted: #475569; }
@media (prefers-color-scheme: dark) {
:root { --card-bg: #1e293b; --card-fg: #f1f5f9; --card-muted: #94a3b8; }
}
.card { background: var(--card-bg); color: var(--card-fg); }
Le navigateur applique automatiquement le bon thème selon le réglage système du visiteur. Sur Android 14 et iOS 17, le mode sombre est activé par défaut le soir, ce qui réduit la fatigue visuelle et la consommation de batterie sur les écrans OLED des smartphones modernes.