Retour au catalogue

About Timeline

Timeline de l'histoire de l'entreprise avec milestones.

aboutmedium Both Responsive a11y
corporateeditorialuniversalagencystacked
Theme

Créer une timeline d'histoire d'entreprise en React

Une timeline d'entreprise en React affiche une ligne centrale verticale avec des cartes de jalons en alternance qui apparaissent au scroll via whileInView de Framer Motion, avec un délai décalé basé sur l'index de l'élément. Sur mobile, la mise en page se replie en colonne unique alignée à gauche.

  • Stack : React + Framer Motion + Tailwind v4, ~128 lignes, zéro dépendance supplémentaire.
  • Animation : fade-up au scroll (opacity 0→1, y 24→0) avec un délai décalé de 80 ms par élément.
  • Responsive : mise en page alternée deux colonnes sur md+, colonne unique alignée à gauche sur mobile.
  • Accessible : la ligne verticale et le dot décoratifs portent aria-hidden ; hiérarchie sémantique h2/h3.
  • Thémable via des CSS custom properties, aucune couleur codée en dur.

About Timeline est une section de jalons empilés verticalement qui visualise l'histoire d'une entreprise ou le parcours d'un produit. Chaque jalon apparaît au scroll en fondu, alternant gauche et droite sur desktop pour rompre la monotonie d'une liste plate. Elle se couple naturellement avec une section équipe ou fondateurs plus bas dans la page.

Anatomie

La section centre un conteneur max-w-4xl avec un bloc d'en-tête (badge optionnel, titre h2, paragraphe sous-titre) puis le corps de la timeline. Ce corps est un div relative : une règle verticale de 1px court sur toute sa hauteur (positionnée absolument en left-4 sur mobile, left-1/2 sur desktop). À l'intérieur, les lignes de jalons alternent via un flag isLeft (index pair = carte à gauche, impair = droite). Chaque ligne contient un dot d'accent centré sur la règle et une carte de texte limitée à 50% de largeur sur desktop.

Comment ça marche

Chaque carte de jalon est une motion.div avec initial={{ opacity: 0, y: 24 }} et whileInView={{ opacity: 1, y: 0 }}. Le prop viewport utilise once: true pour que l'animation ne se déclenche qu'une fois, et margin: '-60px' pour que la carte commence à s'animer juste avant d'être pleinement visible. Le délai de transition est i * 0.08 secondes, donc les éléments qui entrent dans le viewport en même temps s'enchaînent tout de même de façon lisible. Le bloc d'en-tête utilise une variante légèrement plus simple (y: 20, pas de délai) pour se stabiliser avant que le corps de la timeline n'entre.

Comment le coder en React

  1. Définis la forme de tes données de jalons

    Commence par une interface typée pour chaque jalon : une chaîne year, un title et une description. Garde le tableau dans mock.ts pour que le composant reste purement présentationnel. Passe-le comme prop obligatoire nommé milestones.

    interface MilestoneItem {
      year: string;
      title: string;
      description: string;
    }
  2. Trace la règle verticale

    Enveloppe la liste de jalons dans un div relative, puis place un div de 1px positionné absolument de top-0 à bottom-0. Utilise left-4 par défaut et md:left-1/2 pour qu'il se déplace au centre sur desktop. Marque-le aria-hidden pour que les lecteurs d'écran l'ignorent.

    <div
      className="absolute left-4 top-0 bottom-0 w-px md:left-1/2"
      style={{ backgroundColor: "var(--color-border)" }}
      aria-hidden
    />
  3. Alterne les cartes et ajoute le dot

    Pour chaque jalon, calcule isLeft = i % 2 === 0. La div de carte prend md:w-[calc(50%-2rem)] plus soit md:mr-auto md:text-right md:pr-8 (côté gauche) soit md:ml-auto md:pl-8 (côté droit). Le dot est un cercle positionné absolument en left-2 sur mobile, md:left-1/2 md:-translate-x-1/2 sur desktop, au-dessus de la règle grâce à z-10.

    const isLeft = i % 2 === 0;
    // card
    className={`md:w-[calc(50%-2rem)] ${
      isLeft ? "md:mr-auto md:text-right md:pr-8" : "md:ml-auto md:pl-8"
    }`}
  4. Connecte les animations au scroll

    Enveloppe chaque ligne de jalon dans une motion.div. Règle initial sur opacity 0 et y 24, whileInView sur opacity 1 et y 0, puis passe viewport={{ once: true, margin: '-60px' }}. Calcule le délai en i * 0.08 pour que les éléments se décalent naturellement même quand ils entrent ensemble dans le viewport.

    <motion.div
      initial={{ opacity: 0, y: 24 }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true, margin: "-60px" }}
      transition={{ delay: i * 0.08, duration: 0.5, ease: [0.16, 1, 0.3, 1] }}
    >

Quand l'utiliser

Utilise-la sur les pages À propos, les sections histoire de marque ou les récits de lancement produit où tu veux transmettre une croissance dans le temps. Elle fonctionne pour toute entreprise ayant quatre jalons ou plus ; en dessous, une liste à puces se lit plus vite. À éviter sur les pages axées conversion où le défilement entre en compétition avec un CTA, et abandonne la disposition alternée sur les timelines à forte densité de données où la lisibilité prime sur le rythme visuel.

Utilisé par

  • Stripe, Utilise une timeline de jalons verticale sur sa page À propos pour raconter l'histoire de l'entreprise année par année.
  • Notion, Présente l'histoire de sa fondation sous forme de timeline déroulante avec des blocs de texte alternés.
  • Linear, S'appuie sur une mise en page de jalons empilée et épurée pour communiquer sa feuille de route et son histoire.

FAQ

Comment contrôler la vitesse du décalage entre les jalons ?

Ajuste le multiplicateur dans le calcul du délai : delay: i * 0.08. Une valeur plus petite comme 0.05 resserre la séquence ; 0.12 l'étale davantage. Si les jalons entrent dans le viewport un par un en raison de la longueur de la page, le délai compte peu, seuls once: true et le margin offset importent.

Peut-on faire animer la ligne verticale au scroll ?

Oui. Remplace le div statique par une motion.div et anime son scaleY de 0 à 1 avec useScroll et useTransform, en réglant transformOrigin sur top. Cela crée une ligne qui se dessine à mesure que l'utilisateur défile dans la section.

La disposition alternée casse-t-elle sur les écrans très étroits ?

Non, en dessous du breakpoint md, la mise en page bascule sur une colonne unique alignée à gauche (pl-12 sur chaque ligne, avec le dot et la règle épinglés à gauche en left-4). Les classes d'alternance ne s'appliquent qu'à partir de md.

Combien de jalons est-ce trop ?

Au-delà de douze éléments, la section devient épuisante à faire défiler. Si tu as plus de données, regroupe-les par décennie ou opte plutôt pour une timeline défilante horizontale. Six à huit jalons est une plage confortable pour une section À propos.

"use client";

import React from "react";
import { motion } from "framer-motion";

interface MilestoneItem {
  year: string;
  title: string;
  description: string;
}

interface AboutTimelineProps {
  badge?: string;
  title?: string;
  subtitle?: string;
  milestones: MilestoneItem[];
}

export default function AboutTimeline({
  badge,
  title,
  subtitle,

Code complet réservé à Pro

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

Passer en Pro, 9,99€/mois

Avis

Section timeline entreprise React, Tutoriel Framer Motion