Navigation✨ Premium

Tabs Animated

Un indicateur pill gradient glisse entre les onglets via translateX — sélection au clic, panneaux avec fadeIn de 0,3 s, zéro dépendance externe.

CSSJSTransition

Vous aurez accès à la démo interactive avec un compte gratuit.

Cet effet fait partie d'Effect.Labs — 811 effets vanilla, une partie gratuite, une partie premium. Navigation comprend 36 effets, dont 4 gratuits. Découvrir la catégorie →

3 exemples d'usage

App mobile — Navigation principale entre sections — Tabs Animated exemple 1

① App mobile — Navigation principale entre sections

QuandL'utilisateur navigue entre les grandes sections d'une app (dashboard, messagerie, profil) via une barre d'onglets en haut de l'écran.
PourquoiL'indicateur glissant signale visuellement la section active sans ambiguïté et donne un retour immédiat au clic — adapté à des parcours rapides sur mobile.
RéglagesTransition à 0,2 s pour plus de réactivité, couleurs brand en place du gradient indigo, max-width: 100% pour une barre full-width.
Documentation technique — Exemples de code par langage — Tabs Animated exemple 2

② Documentation technique — Exemples de code par langage

QuandUne page de doc API propose le même exemple en JavaScript, Python et PHP — l'utilisateur choisit son langage via les onglets.
PourquoiL'indicateur animé confirme le changement de bloc de code sans rechargement de page. Les onglets à largeur égale lisent mieux que des liens soulignés dans un contexte de lecture technique.
RéglagesGradient remplacé par une couleur unie (background: #1e293b) pour un style éditorial sobre, panneaux avec font-family: monospace et background: rgba(0,0,0,.4).
Dashboard analytics — Filtre de période (Jour / Semaine / Mois) — Tabs Animated exemple 3

③ Dashboard analytics — Filtre de période (Jour / Semaine / Mois)

QuandLe haut d'un widget de statistiques propose 3 granularités temporelles — l'utilisateur change la période affichée sans quitter la page.
PourquoiL'indicateur glissant est plus compact et lisible qu'un <code>&lt;select&gt;</code> ou des radio buttons pour 3 options fixes ; il s'intègre élégamment dans un header de carte.
RéglagesTransition à 0,15 s pour une réponse immédiate sur des données chiffrées, max-width: 280px pour tenir dans un widget compact, gradient indigo conservé pour l'accent data.

Comment ça marche

L'indicateur glissant est un <div class="tab-indicator"> positionné en absolute dans le header position: relative. Sa largeur est calc(33.333% - 2.67px) — exactement un tiers du conteneur, les boutons étant en flex: 1 1 0%. Il porte un dégradé linear-gradient(135deg, #6366f1, #8b5cf6) et un border-radius: 8px.

Le déplacement repose sur une seule instruction JS : indicator.style.transform = 'translateX(' + 100 * index + '%)'. La valeur 100 % correspond à 100 % de la largeur de l'indicateur lui-même — soit exactement la largeur d'un onglet. Le navigateur interpole le mouvement via transition: transform .3s cubic-bezier(.4, 0, .2, 1) (courbe Material Design), sans aucun calcul de coordonnées absolues.

Au changement d'onglet, classList.toggle('active', bool) coche le bouton et le panneau correspondants et décoche les autres. Le panneau actif bascule de display: none à display: block et déclenche l'animation CSS fadeIn (opacité 0→1, translateY 10→0 px, durée 0,3 s). La couleur des boutons inactifs transite de rgba(255,255,255,.6) vers #fff sur transition: color .3s.

Les boutons en flex: 1 1 0% occupent tous strictement la même largeur quelle que soit la longueur du label — l'indicateur atterrit toujours juste sous le bon onglet sans calcul supplémentaire. La fonction switchTab(n) est exposée dans la portée globale et peut être appelée programmatiquement depuis n'importe quel script extérieur.

Accessibilité

  • prefers-reduced-motion absent — le code ne contient pas de media query prefers-reduced-motion : la transition de l'indicateur et le fadeIn s'exécutent même si l'OS demande à réduire le mouvement. À ajouter manuellement : @media (prefers-reduced-motion: reduce) { .tab-indicator, .tab-panel { transition: none; animation: none; } }.
  • Les onglets sont des <button> natifs — focusables au clavier (Tab / Shift+Tab) et annoncés par les lecteurs d'écran sans configuration supplémentaire.
  • Pas de rôles ARIA du pattern Tabs (role="tablist", role="tab", aria-selected, role="tabpanel", aria-controls) — à ajouter si la conformité WCAG 1.3.1 est requise.
  • Les panneaux non actifs sont masqués par display: none — retirés de l'arbre d'accessibilité nativement, sans aria-hidden explicite.
  • Contraste du texte actif : #fff sur le gradient indigo (#6366f1) — ratio > 4,5:1, conforme WCAG AA.

Compatibilité navigateur

CSS transition, transform, flexbox et linear-gradient — supportés dans tous les navigateurs modernes. Zéro dépendance externe.

Chrome 36+✓ Complet
Firefox 16+✓ Complet
Safari 9+✓ Complet
Edge 18+✓ Complet
Mobile iOS✓ Touch OK
Android Chrome✓ Complet

Sans JS, les onglets restent visibles mais l'indicateur ne glisse pas et les panneaux ne basculent pas — l'onglet Accueil reste affiché en statique. Sans support <code>flexbox</code>, les boutons s'empilent verticalement mais restent fonctionnels.

Le code

Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :

index.html — structure
<div class="tabs-container">
  <div class="tabs-header">
    <div class="tab-indicator" id="tabIndicator"></div>
    <button class="tab-btn active" onclick="switchTab(0)">Onglet 1</button>
    <button class="tab-btn" onclick="switchTab(1)">Onglet 2</button>
    <button class="tab-btn" onclick="switchTab(2)">Onglet 3</button>
  </div>
  <div class="tabs-content">
    <div class="tab-panel active" data-tab="0">Contenu de l'onglet 1</div>
    <div class="tab-panel" data-tab="1">Contenu de l'onglet 2</div>
    <div class="tab-panel" data-tab="2">Contenu de l'onglet 3</div>
  </div>
</div>
🔒 Débloquer le code complet — à partir de 2,99 € le 1er mois

HTML + CSS + JS complet, prêt à coller — avec des centaines d'effets premium.

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
--primary (CSS :root) #6366f1 Couleur d'accent utilisée par .tab-btn.active { color } — modifiez dans :root ou sur .tabs-container pour un scope plus étroit.
.tab-indicator background linear-gradient(135deg, #6366f1, #8b5cf6) Gradient de l'indicateur pill — remplacez par une couleur unie (#3b82f6) ou votre palette brand.
.tab-indicator transition transform .3s cubic-bezier(.4,0,.2,1) Durée et easing du glissement — .15s ease pour une réponse data immédiate, .5s ease-in-out pour une animation éditoriale plus douce.
.tabs-container max-width 350px Largeur maximale du bloc — supprimez ou passez à 100% pour une barre full-width dans un layout fluide.
.tab-btn color (inactif) rgba(255,255,255,.6) Opacité du texte des onglets inactifs — augmentez à rgba(255,255,255,.85) pour plus de lisibilité sur fond clair.
.tab-panel animation fadeIn .3s ease Animation du contenu au basculement — raccourcissez à fadeIn .1s ease pour un affichage quasi-instantané, ou supprimez animation pour un simple swap.
switchTab(n) — JS global Appel programmatique pour changer d'onglet sans clic — switchTab(2) active le 3ᵉ onglet. Déclenchez depuis un timer, un événement métier ou un lien externe.

FAQ

Oui, mais deux valeurs doivent être mises à jour. Dans le CSS, remplacez width: calc(33.333% - 2.67px) par calc(100% / N - gap) (ex. calc(25% - 3px) pour 4 onglets). Dans les appels JS, le décalage reste translateX(100 * index %) — il n'y a rien d'autre à modifier côté logique.
Non. Les boutons sont en flex: 1 1 0% : ils partagent la largeur du conteneur à parts strictement égales, indépendamment du texte. L'indicateur hérite de cette largeur fixe et atterrit toujours exactement sous le bon onglet.
Copiez le HTML, le CSS et le JS dans un composant. Dans React, remplacez les onclick="switchTab(n)" inline par onClick={() => switchTab(n)} et déclenchez switchTab(defaultTab) dans un useEffect(() => {}, []) côté client. Dans Vue, utilisez @click="switchTab(n)" et mounted() { switchTab(0); }. L'effet ne touche pas au DOM en dehors de son conteneur.