Retour au catalogue

Features Icon Grid

Grille 3x2 d'icones avec texte, tres clean et aere. Style Apple/Stripe.

featuressimple Both Responsive a11y
minimalcorporateuniversalsaasagencygrid
Theme

Créer une section features en grille d'icônes avec React

Une grille de features avec icônes en React affiche une grille CSS responsive de cartes, chacune avec une icône Lucide résolue dynamiquement, un titre et une description courte. Chaque carte entre dans le viewport avec une animation whileInView décalée via Framer Motion, pour que la grille se remplisse naturellement au scroll.

  • Stack : React + Framer Motion + Lucide React, ~170 lignes, zéro dépendance supplémentaire.
  • Icônes résolues à l'exécution depuis le namespace Lucide, n'importe quel nom d'icône Lucide fonctionne en prop string.
  • Entièrement compatible avec le thème : toutes les couleurs et espacements utilisent des custom properties CSS (--color-background, --color-accent, etc.).
  • Responsive : grille auto-fit avec minmax(280px, 1fr) qui passe en colonne unique sur petits écrans.
  • Accessible : hiérarchie sémantique h2/h3, les icônes sont décoratives et ne nécessitent pas d'aria-label.

Features Icon Grid est une section React épurée et animée au scroll qui présente jusqu'à six fonctionnalités produit dans une grille centrée en 3 colonnes. Chaque carte affiche un badge d'icône teinté, un titre court et une description en une ligne. L'esthétique Apple/Stripe, grands espaces blancs, texte centré, couleur retenue, lui permet de s'intégrer dans presque n'importe quelle landing SaaS ou agence sans retouche.

Anatomie

La section contient deux régions principales. En haut, un bloc d'en-tête centré regroupe un badge optionnel en majuscules, un titre h2 avec taille de police fluid via clamp, et un paragraphe de sous-titre ; tout le bloc s'anime en une seule unité. En dessous, une grille CSS en `auto-fit, minmax(280px, 1fr)` affiche les cartes de features. Chaque carte est une colonne flex centrée : un conteneur d'icône carré de 48px avec une teinte accent à 10%, un h3 et une description limitée à 280px de large pour un confort de lecture optimal.

Comment ça marche

L'animation utilise `whileInView` de Framer Motion avec `viewport={{ once: true, margin: '-40px' }}` pour que chaque carte ne s'anime qu'une seule fois quand elle entre dans la zone visible. L'en-tête monte en fondu en une seule unité (opacity 0 → 1, y 16 → 0). Les cartes de features partagent le même keyframe mais reçoivent chacune un délai de `i * 0.06s`, créant un décalage de gauche à droite sur la rangée. Toutes les transitions utilisent la courbe cubique `[0.16, 1, 0.3, 1]`, une courbe fast-out-slow-in qui semble vive sans rebond. Les composants d'icônes sont résolus au rendu : la prop est une chaîne comme `'Zap'` et le composant fait une recherche dans l'objet namespace Lucide.

Comment le coder en React

  1. Définir la structure des données et les props

    Crée une interface `FeatureItem` avec `id`, `title`, `description` et un champ `icon` string optionnel. Passe un tableau de ces items au composant avec un `badge`, `title` et `subtitle` optionnels pour l'en-tête de section. Garde le champ icon comme une simple chaîne, la résolution se fait dans le composant.

    interface FeatureItem {
      id: string;
      title: string;
      description: string;
      icon?: string;
    }
  2. Résoudre les icônes Lucide depuis une prop string

    Importe tout le namespace Lucide avec `* as LucideIcons`, puis écris un petit helper qui fait une recherche par clé. Caste le namespace en `Record<string, React.ElementType>` pour éviter les erreurs TypeScript. Si le nom est absent ou inconnu, le helper retourne `null` et l'emplacement d'icône reste vide.

    import * as LucideIcons from "lucide-react";
    
    function getIcon(name?: string) {
      if (!name) return null;
      return (LucideIcons as unknown as Record<string, React.ElementType>)[name] || null;
    }
  3. Construire la grille responsive avec CSS auto-fit

    Utilise un simple `div` avec `display: grid` et `gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))'`. Tu obtiens trois colonnes sur desktop, deux sur tablette et une sur mobile sans media queries. Règle le `gap` à environ 3rem verticalement et 2.5rem horizontalement pour l'aspect SaaS aéré.

    <div style={{
      display: "grid",
      gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))",
      gap: "3rem 2.5rem",
      maxWidth: 960,
      margin: "0 auto",
    }}>
  4. Ajouter les animations whileInView décalées

    Entoure chaque carte d'une `motion.div` avec `initial={{ opacity: 0, y: 16 }}` et `whileInView={{ opacity: 1, y: 0 }}`. Règle `viewport={{ once: true, margin: '-40px' }}` pour que l'animation se déclenche une fois quand 40px de la carte sont visibles. Multiplie l'index de la carte par 0.06 pour le délai afin d'obtenir un décalage naturel de gauche à droite.

    <motion.div
      key={feature.id}
      initial={{ opacity: 0, y: 16 }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true, margin: "-40px" }}
      transition={{ delay: i * 0.06, duration: 0.5, ease: [0.16, 1, 0.3, 1] }}
    >

Quand l'utiliser

Place cette section juste après le hero sur une landing SaaS ou produit, elle fonctionne mieux comme première explication de ce que fait ton produit. Six features est le bon équilibre ; en dessous de quatre la grille paraît vide, et au-dessus de huit, envisage une autre mise en page comme un split alterné. À éviter sur les pages à forte charge cognitive comme la documentation ou les tableaux de tarification. Sur mobile la grille auto-fit se replie naturellement en colonne unique, aucun travail supplémentaire n'est nécessaire.

Utilisé par

  • Stripe, Utilise une grille d'icônes centrée sur ses pages produit pour présenter les capacités API avec des conteneurs d'icônes teintés et des descriptions courtes et percutantes.
  • Linear, Présente les fonctionnalités de workflow dans une grille multi-colonnes aérée avec des badges d'icônes et une prose minimale, même philosophie d'espacement.
  • Vercel, Les grilles de features avec conteneurs d'icônes monochromes sont un pattern récurrent sur ses pages plateforme et infrastructure.
  • Notion, Déploie une grille icône + texte centrée sur ses pages équipes pour présenter les fonctionnalités de collaboration dans un format scannable.

FAQ

Comment ajouter ou changer des icônes sans toucher au composant ?

Passe le nom d'icône Lucide en PascalCase exact dans le champ `icon` de tes données, par exemple `'Zap'`, `'Shield'` ou `'BarChart2'`. Le composant le résout à l'exécution depuis le namespace Lucide, donc tout nom d'icône Lucide valide fonctionne sans modifier le code du composant.

Puis-je utiliser un nombre de features différent de six ?

La grille auto-fit s'adapte à n'importe quel nombre. Quatre items donnent un layout 2×2 sur desktop, cinq donnent une rangée déséquilibrée. Pour un résultat équilibré, préfère des multiples de trois (3, 6, 9). Si tu as cinq ou sept features, définis un `gridTemplateColumns` explicite comme `repeat(3, 1fr)` pour que la dernière rangée s'aligne à gauche au lieu de s'étirer.

Comment désactiver les animations au scroll ?

Remplace les `motion.div` par de simples `div` et supprime les props `initial`, `whileInView` et `transition`. La grille et la mise en page restent intactes, Framer Motion n'est utilisé que pour l'animation d'entrée, pas pour le positionnement.

Cette section supporte-t-elle le mode sombre et clair ?

Oui. Chaque valeur de couleur lit une custom property CSS (--color-background, --color-foreground, --color-accent, --color-foreground-muted). Changer le thème au niveau de l'attribut `data-theme` suffit ; aucune modification à l'intérieur du composant n'est nécessaire.

"use client";

import React from "react";
import { motion } from "framer-motion";
import * as LucideIcons from "lucide-react";

interface FeatureItem {
  id: string;
  title: string;
  description: string;
  icon?: string;
}

interface FeaturesIconGridProps {
  badge?: string;
  title?: string;
  subtitle?: string;
  features: FeatureItem[];
}

function getIcon(name?: string) {
  if (!name) return null;

Code complet réservé à Pro

Code source intégral, export multi-framework et playground.

Passer en Pro, 9,99€/mois

Avis

Section features grille d'icônes React, Code + Tutoriel