Retour au catalogue

Blog Magazine

Layout magazine avec un article featured en grand et une grille d'articles en dessous.

blogmedium Both Responsive a11y
editorialelegantuniversalagencygrid
Theme

Créer une section blog magazine en React avec article featured

Une section blog magazine en React associe un grand article featured en deux colonnes (image + texte) à une grille de cartes responsive en dessous. Framer Motion whileInView déclenche des animations fade-up en cascade au scroll, sans une seule keyframe écrite à la main.

  • Stack : React + Framer Motion 11 + Lucide React, ~150 lignes, zéro dépendance supplémentaire.
  • Layout : CSS Grid, 1fr/1fr pour le bloc featured, repeat(auto-fill, minmax(280px, 1fr)) pour la grille de cartes.
  • Thème : 100% CSS custom properties (--color-background, --color-accent, --radius-lg), zéro couleur codée en dur.
  • Accessible : hiérarchie sémantique h2/h3/h4, icône Calendar décorative, liens en éléments <a> natifs.
  • Point mobile : la grille 2 colonnes du featured ne se replie en 1 colonne qu'avec une media query ajoutée manuellement, non incluse dans la base de 150 lignes.

Blog Magazine est une section React qui donne à votre contenu une hiérarchie de type presse : un article phare occupe toute la largeur à gauche, son texte éditorial à droite, et trois à six cartes secondaires remplissent une grille fluide en dessous. La lecture est immédiate, le layout supporte de trois à une douzaine d'articles sans toucher au code, et l'ensemble s'anime à l'entrée dans le viewport via quelques appels Framer Motion whileInView.

Anatomie

La section se divise en trois zones empilées. En haut, un en-tête avec titre h2 et sous-titre s'anime en fade-up au premier scroll. En dessous, une grille CSS à deux colonnes fait office d'article featured : la cellule gauche est un placeholder coloré en rapport 16/10, la cellule droite est une colonne flex avec badge de catégorie, titre h3, extrait et une ligne de date avec l'icône Calendar de Lucide. La zone basse est une grille CSS repeat(auto-fill, minmax(280px, 1fr)) qui mappe le tableau articles en petites cartes, chacune avec une miniature 16/9, catégorie, titre h4 et date. Un lien "voir tous les articles" centré avec une flèche ArrowRight ferme la section.

Comment ça marche

Chaque bloc visuel est une motion.a ou motion.div avec initial={{ opacity: 0, y: 16 }} et whileInView={{ opacity: 1, y: 0 }}. Le viewport est configuré avec once:true pour que l'animation ne se déclenche qu'une fois. La grille de cartes décale chaque élément en multipliant son index par 0.06 secondes dans le délai de transition. Une constante EASE partagée ([0.16, 1, 0.3, 1]) donne aux reveals un feeling éditorial vif plutôt qu'un fondu générique. Le composant est purement présentationnel : il accepte un objet d'article featured et un tableau d'articles en props, avec des valeurs par défaut inline si aucun n'est fourni.

Comment le coder en React

  1. Définir les interfaces de données et les props

    Crée une interface Article (title, excerpt, date, category, imageColor) et une interface BlogMagazineProps qui encapsule sectionTitle, sectionSubtitle, featured et articles. Garde imageColor comme chaîne CSS pour pouvoir passer n'importe quelle custom property ou valeur hex depuis le parent.

    interface Article {
      title: string;
      excerpt: string;
      date: string;
      category: string;
      imageColor: string;
    }
    
    interface BlogMagazineProps {
      sectionTitle?: string;
      featured?: Article;
      articles?: Article[];
    }
  2. Construire l'article featured avec une grille CSS 2 colonnes

    Utilise une motion.a qui enveloppe un div avec gridTemplateColumns:'1fr 1fr'. La cellule gauche est un div avec aspectRatio:'16/10' et une couleur de fond semi-transparente. La cellule droite est une colonne flex avec le badge de catégorie, le titre h3, le paragraphe d'extrait et une ligne Calendar + date.

    <motion.a
      initial={{ opacity: 0, y: 20 }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true }}
      transition={{ duration: 0.6, delay: 0.08, ease: EASE }}
      style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '2rem' }}
    >
  3. Afficher la grille de cartes avec délais en cascade

    Mappe le tableau articles et enveloppe chaque carte dans une motion.a. Utilise i * 0.06 comme délai de transition pour que les cartes se révèlent de gauche à droite. La grille utilise repeat(auto-fill, minmax(280px, 1fr)) pour refluer automatiquement d'une à quatre colonnes.

    {articles.map((article, i) => (
      <motion.a
        key={i}
        initial={{ opacity: 0, y: 16 }}
        whileInView={{ opacity: 1, y: 0 }}
        viewport={{ once: true }}
        transition={{ duration: 0.45, delay: i * 0.06, ease: EASE }}
      >
        ...
      </motion.a>
    ))}
  4. Utiliser les CSS custom properties pour toutes les couleurs et espacements

    Ne code jamais une valeur hex en dur. Utilise var(--color-background), var(--color-foreground), var(--color-accent), var(--color-border), var(--radius-lg) et var(--section-padding-y) partout. N'importe quel preset de thème parent peut ainsi changer l'apparence sans toucher au source du composant.

Quand l'utiliser

Ce layout convient quand votre site a un vrai programme de contenu : blog, salle de presse, changelog ou hub de ressources avec au moins quatre à six articles. Il fonctionne surtout au milieu d'une landing page comme signal de confiance, ou comme template principal d'index blog. A éviter quand le blog est secondaire avec un ou deux articles, ou quand il faut un feed masonry ou infini. La grille suppose un nombre prévisible d'éléments. Sur mobile, ajoutez une media query pour passer le bloc featured de deux colonnes à une ; la grille de cartes reflue seule.

Utilisé par

  • Stripe, Un grand article hero au-dessus d'une grille de publications récentes, application directe de cette hiérarchie magazine.
  • Vercel, Index blog avec un article featured épinglé en haut et une grille d'articles secondaires en dessous.
  • Linear, Index blog en style magazine : une grande carte featured, puis une grille deux ou trois colonnes d'entrées récentes.
  • Liveblocks, Article featured sur toute la largeur en haut, cartes d'articles plus petites dans une grille responsive en dessous.

FAQ

Comment faire s'empiler le bloc featured verticalement sur mobile ?

Le bloc featured utilise une CSS Grid avec gridTemplateColumns:'1fr 1fr' défini en style inline. Ajoute une media query (ou une classe responsive Tailwind si tu passes en className) qui remplace cela par gridTemplateColumns:'1fr' sous ton breakpoint mobile. La grille de cartes en dessous reflue déjà automatiquement grâce à auto-fill.

Puis-je remplacer les placeholders imageColor par de vraies images ?

Remplace le div coloré par un élément img ou next/image avec objectFit:'cover' et le même style aspect-ratio. Remplace imageColor dans l'interface Article par une chaîne imageUrl, et c'est tout.

Pourquoi chaque carte s'anime-t-elle séparément plutôt que toutes en même temps ?

L'expression delay: i * 0.06 décale les cartes de 60ms par index. Cela donne à la grille un effet cascade qui paraît intentionnel plutôt qu'un pop-in en masse, rendant le layout plus aérien et éditorial.

Le composant fonctionne-t-il sans articles passés en props ?

L'article featured se replie sur un objet par défaut inline, la section affiche donc toujours quelque chose. Le tableau articles a pour défaut un tableau vide, la grille de cartes ne rend rien sans planter. Passez au moins trois articles pour que le layout soit visuellement cohérent.

"use client";

import { motion } from "framer-motion";
import { Calendar, ArrowRight } from "lucide-react";

interface Article {
  title: string;
  excerpt: string;
  date: string;
  category: string;
  imageColor: string;
}

interface BlogMagazineProps {
  sectionTitle?: string;
  sectionSubtitle?: string;
  featured?: Article;
  articles?: Article[];
}

const EASE = [0.16, 1, 0.3, 1] as const;

Code complet réservé à Pro

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

Passer en Pro, 9,99€/mois

Avis

Layout blog magazine React, une du + grille, Tutoriel