Éléments interactifs

Popup, Tooltip, Accordion, Tabs et Slider. Tous les éléments sont emboîtables (nestable) et initialisés automatiquement au chargement.

Popup / Modal

Système de popup/modal avec overlay, fermeture par clic extérieur, touche Escape et bouton. Les popups sont empilables (nestable).

Structure HTML

<button data-popup-target="demo">Ouvrir le popup</button>

<div class="popup" data-popup="demo">
  <div class="popup__overlay"></div>
  <div class="popup__content">
    <button class="popup__close" data-popup-close>&times;</button>
    <h2>Titre du popup</h2>
    <p>Contenu du popup.</p>
  </div>
</div>

Attributs

AttributRôle
data-popup-target="id"Bouton qui ouvre le popup correspondant
data-popup="id"Identifiant du popup
data-popup-closeBouton de fermeture (dans le popup)

Fermeture

  • Clic sur .popup__overlay
  • Clic sur [data-popup-close]
  • Touche Escape (ferme le dernier ouvert)

Popups imbriqués

Les popups peuvent être imbriqués. Le z-index est géré automatiquement par CSS (.popup .popup → z-index supérieur). La touche Escape ferme toujours le dernier popup ouvert.

Variantes de position

Ajoutez data-popup-position sur le .popup pour changer l'animation et la disposition :

ValeurComportement
(aucune)Centré (défaut) — animation scale + fade
rightPanneau latéral droit — pleine hauteur, max 480px, glisse depuis la droite
leftPanneau latéral gauche — pleine hauteur, max 480px, glisse depuis la gauche
bottomBottom sheet — pleine largeur, max 80vh, glisse depuis le bas
topPanneau supérieur — pleine largeur, max 80vh, glisse depuis le haut

Popup centré (défaut)

<button data-popup-target="demo">Ouvrir</button>
<div class="popup" data-popup="demo">
  <div class="popup__overlay"></div>
  <div class="popup__content">
    <button class="popup__close" data-popup-close>&times;</button>
    <h2>Titre</h2>
    <p>Contenu du popup.</p>
  </div>
</div>

Panneau droit

<button data-popup-target="menu">Menu</button>
<div class="popup" data-popup="menu" data-popup-position="right">
  <div class="popup__overlay"></div>
  <div class="popup__content">
    <button class="popup__close" data-popup-close>&times;</button>
    <h2>Menu</h2>
  </div>
</div>

Panneau gauche

<button data-popup-target="sidebar">Sidebar</button>
<div class="popup" data-popup="sidebar" data-popup-position="left">
  <div class="popup__overlay"></div>
  <div class="popup__content">
    <button class="popup__close" data-popup-close>&times;</button>
    <h2>Sidebar</h2>
  </div>
</div>

Bottom sheet

<button data-popup-target="sheet">Bottom sheet</button>
<div class="popup" data-popup="sheet" data-popup-position="bottom">
  <div class="popup__overlay"></div>
  <div class="popup__content">
    <button class="popup__close" data-popup-close>&times;</button>
    <p>Contenu en bas.</p>
  </div>
</div>

Panneau haut

<button data-popup-target="top-panel">Panneau haut</button>
<div class="popup" data-popup="top-panel" data-popup-position="top">
  <div class="popup__overlay"></div>
  <div class="popup__content">
    <button class="popup__close" data-popup-close>&times;</button>
    <p>Contenu en haut.</p>
  </div>
</div>

Sur mobile (≤ 767px), les panneaux latéraux passent en pleine largeur automatiquement.

Classes CSS

ClasseDescription
.popupConteneur principal (caché par défaut)
.popup--activePopup visible (ajouté par JS)
.popup__overlayFond semi-transparent
.popup__contentBoîte de contenu (animation scale + fade)
.popup__closeBouton de fermeture (positionné en haut à droite)

Attributs récapitulatifs

AttributRôle
data-popup-target="id"Bouton qui ouvre le popup correspondant
data-popup="id"Identifiant du popup
data-popup-closeBouton de fermeture (dans le popup)
data-popup-position="right|left|bottom|top"Variante de position (optionnel)

Tooltip

Bulle d'information au survol ou au focus. Repositionnement automatique si la bulle déborde de la fenêtre.

Utilisation

<span data-tooltip="Texte de la bulle">Survolez-moi</span>

<!-- Avec position -->
<span data-tooltip="Info" data-tooltip-pos="bottom">En bas</span>
<span data-tooltip="Info" data-tooltip-pos="left">À gauche</span>
<span data-tooltip="Info" data-tooltip-pos="right">À droite</span>

Attributs

AttributDescription
data-tooltip="texte"Texte de la bulle
data-tooltip-posPosition : top (défaut), bottom, left, right

Repositionnement automatique

Si la bulle déborde du viewport, elle se repositionne automatiquement (ex. topbottom si pas de place en haut).

Classes CSS

ClasseDescription
.tooltipAjoutée automatiquement à l'élément parent
.tooltip__bubbleBulle de texte (créée dynamiquement)
.tooltip__bubble--top/bottom/left/rightVariantes de position
.tooltip__bubble--visibleBulle visible (avec transition)

Accordion

Panneaux dépliables avec animation CSS Grid. Support du mode multiple et de l'imbrication.

Contenu du premier panneau. Un seul panneau ouvert à la fois par défaut.
Contenu du deuxième panneau avec un sous-accordion imbriqué :
Contenu imbriqué A.
Contenu imbriqué B (mode multiple).
Contenu du troisième panneau.

Structure HTML

<div class="accordion">
  <div class="accordion__item">
    <button class="accordion__header">Section 1</button>
    <div class="accordion__body">
      <div>Contenu du panneau 1.</div>
    </div>
  </div>
  <div class="accordion__item">
    <button class="accordion__header">Section 2</button>
    <div class="accordion__body">
      <div>Contenu du panneau 2.</div>
    </div>
  </div>
</div>

Mode multiple

Par défaut, un seul panneau est ouvert à la fois. Ajoutez data-accordion-multi pour permettre l'ouverture de plusieurs panneaux simultanément :

<div class="accordion" data-accordion-multi>
  ...
</div>

Accordéon imbriqué

Les accordéons peuvent être imbriqués. Chaque niveau gère ses propres items indépendamment :

<div class="accordion">
  <div class="accordion__item">
    <button class="accordion__header">Parent</button>
    <div class="accordion__body">
      <div>
        <div class="accordion">
          <div class="accordion__item">
            <button class="accordion__header">Enfant</button>
            <div class="accordion__body">
              <div>Contenu imbriqué.</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Classes CSS

ClasseDescription
.accordionConteneur principal (bordure + arrondi)
.accordion__itemUn panneau individuel
.accordion__item--activePanneau ouvert (ajouté par JS)
.accordion__headerEn-tête cliquable (bouton)
.accordion__bodyContenu (animation via grid-template-rows)

Tabs

Système d'onglets avec navigation et panneaux. Support de l'imbrication.

Contenu du premier onglet.

Contenu du deuxième onglet.

Contenu du troisième onglet avec tabs imbriqués :

Contenu imbriqué A.

Contenu imbriqué B.

Scroll automatique

Quand les onglets débordent, la barre de navigation scrolle horizontalement avec des dégradés indicateurs. Le tab actif est automatiquement centré.

Contenu Accueil

Contenu Produits

Contenu Services

Contenu Portfolio

Contenu Témoignages

Contenu Équipe

Contenu Tarifs

Contenu Blog

Contenu Contact

Contenu FAQ

Structure HTML

<div class="tabs">
  <div class="tabs__nav">
    <button class="tabs__tab" data-tab="tab1">Onglet 1</button>
    <button class="tabs__tab" data-tab="tab2">Onglet 2</button>
    <button class="tabs__tab" data-tab="tab3">Onglet 3</button>
  </div>
  <div class="tabs__panel" data-tab-panel="tab1">Contenu 1</div>
  <div class="tabs__panel" data-tab-panel="tab2">Contenu 2</div>
  <div class="tabs__panel" data-tab-panel="tab3">Contenu 3</div>
</div>

Onglet actif par défaut

Par défaut, le premier onglet est actif. Ajoutez data-tab-active pour choisir un autre :

<button class="tabs__tab" data-tab="tab2" data-tab-active>Onglet 2</button>

Attributs

AttributDescription
data-tab="id"Identifiant de l'onglet (sur le bouton)
data-tab-panel="id"Identifiant du panneau associé
data-tab-activeOnglet actif au chargement (optionnel)

Classes CSS

ClasseDescription
.tabsConteneur principal
.tabs__navBarre de navigation (scroll horizontal automatique avec fades indicateurs)
.tabs__nav-wrapperWrapper auto-généré par JS — affiche des dégradés gauche/droite quand la nav déborde
.tabs__tabBouton d'onglet
.tabs__tab--activeOnglet actif (souligné en couleur primaire)
.tabs__panelPanneau de contenu (caché par défaut)
.tabs__panel--activePanneau visible

Slider / Carousel

Carousel avec navigation par boutons, dots, swipe tactile, drag souris, autoplay et boucle. Support multi-slides.

Slide 1
Slide 2
Slide 3
Slide 4
Slide 5
Slide 6

Structure HTML

<!-- Slider basique (1 slide visible) -->
<div class="slider">
  <div class="slider__track">
    <div class="slider__slide">Slide 1</div>
    <div class="slider__slide">Slide 2</div>
    <div class="slider__slide">Slide 3</div>
  </div>
  <button class="slider__prev"></button>
  <button class="slider__next"></button>
  <div class="slider__dots"></div>
</div>

<!-- Slider responsive multi-slides -->
<div class="slider"
     data-slider-per-view="3 2 2 1"
     data-slider-loop="true"
     data-slider-drag="true"
     data-slider-gap="md">
  <div class="slider__track">
    <div class="slider__slide">Slide 1</div>
    <div class="slider__slide">Slide 2</div>
    <div class="slider__slide">Slide 3</div>
    <div class="slider__slide">Slide 4</div>
    <div class="slider__slide">Slide 5</div>
    <div class="slider__slide">Slide 6</div>
  </div>
  <button class="slider__prev"></button>
  <button class="slider__next"></button>
  <div class="slider__dots"></div>
</div>

Le format data-slider-per-view="3 2 2 1" définit le nombre de slides visibles par breakpoint : desktop tablette mobile-paysage mobile. Les valeurs cascadent : "3" = 3 slides sur tous les écrans, "3 2" = 3 desktop + 2 pour le reste.

Attributs

AttributValeurDescription
data-slider-per-view"3" ou "4 3 2 1"Slides visibles par breakpoint : desktop [tablet] [mobile-landscape] [mobile]. Cascade auto si moins de 4 valeurs.
data-slider-looptrueBoucle infinie
data-slider-auto3000Défilement auto en ms (pause au survol)
data-slider-dragtrueDrag à la souris (en plus du swipe tactile)
data-slider-gapxs | sm | md | lg | xlEspacement entre les slides
data-slider-dotsfalseMasquer les dots de navigation
data-slider-arrowsfalseMasquer les flèches de navigation

Personnalisation des flèches

Les flèches utilisent par défaut les icônes chevron. Personnalisez-les via ces attributs sur le .slider :

AttributValeurDescription
data-slider-arrow-prevNom d'icôneIcône du bouton précédent (ex: arrow-left)
data-slider-arrow-nextNom d'icôneIcône du bouton suivant (ex: arrow-right)
data-slider-arrow-typeoutline | solidType d'icône (défaut : outline)
data-slider-arrow-sizeNombre en pxTaille de l'icône SVG (défaut : 20)
Slide 1
Slide 2
Slide 3
Slide 4
<div class="slider"
     data-slider-arrow-prev="arrow-left"
     data-slider-arrow-next="arrow-right"
     style="--slider-arrow-color: #fff; --slider-arrow-bg: var(--color-primary);">
  ...
</div>

Les icônes sont chargées depuis le système d'icônes (icons.js). Les styles peuvent aussi être définis via les CSS custom properties --slider-arrow-* directement en CSS.

CSS custom properties

VariableDescription
--slider-arrow-sizeTaille du bouton
--slider-arrow-colorCouleur de l'icône
--slider-arrow-hover-colorCouleur au survol
--slider-arrow-bgFond du bouton
--slider-arrow-hover-bgFond au survol
--slider-arrow-borderCouleur de bordure

Navigation

  • Boutons : .slider__prev et .slider__next (optionnels)
  • Dots : .slider__dots (générés automatiquement par JS, optionnel)
  • Swipe : tactile natif (seuil 50px)
  • Drag souris : activé via data-slider-drag="true"

Exemple complet

<div class="slider"
     data-slider-per-view="2"
     data-slider-loop="true"
     data-slider-auto="4000"
     data-slider-drag="true"
     data-slider-gap="md"
     data-slider-arrow-prev="arrow-left"
     data-slider-arrow-next="arrow-right"
     style="--slider-arrow-color: #fff; --slider-arrow-bg: var(--color-primary);">
  <div class="slider__track">
    <div class="slider__slide"><img src="img/1.jpg" alt=""></div>
    <div class="slider__slide"><img src="img/2.jpg" alt=""></div>
    <div class="slider__slide"><img src="img/3.jpg" alt=""></div>
    <div class="slider__slide"><img src="img/4.jpg" alt=""></div>
  </div>
  <button class="slider__prev"></button>
  <button class="slider__next"></button>
  <div class="slider__dots"></div>
</div>

Classes CSS

ClasseDescription
.sliderConteneur principal (overflow: hidden)
.slider__trackPiste flex (translateX pour la navigation)
.slider__slideUn slide individuel
.slider__prev, .slider__nextBoutons flèches (positionnés en absolu)
.slider__dotsConteneur des points de navigation
.slider__dotPoint individuel (créé par JS)
.slider__dot--activePoint actif

API JavaScript

FonctionFichierDescription
initElements(root)elements.jsInitialise popups, tooltips, accordions, tabs, sliders dans root (défaut : document).
initAnimations(root)animations.jsInitialise les animations scroll + clic dans root.
initIcons(root)icons.jsCharge les icônes SVG [data-icon] dans root.
initForms(root)forms.jsInitialise formulaires, validation, multi-steps dans root.
renderComponents(root)components.jsRend les [data-component] dans root.
showToast(message, type, duration)forms.jsAffiche une notification toast. Types : 'success', 'error', 'warning', 'info'.
toggleTheme()darkmode.jsBascule entre light et dark mode.
openCookieSettings()cookies.jsOuvre le panneau de gestion des cookies.
getUrlParams()params.jsRetourne un objet avec tous les paramètres URL.
getUTMs()params.jsRetourne un objet avec les UTMs persistants.
fetchIconSvg(type, name, cb)icons.jsRécupère le SVG brut d'une icône via callback.
registerComponent(name, fn)components.jsEnregistre un composant. fn(slots) retourne du HTML.
escapeSlotHtml(str)components.jsÉchappe les caractères HTML (anti-XSS pour les slots texte).

Toutes ces fonctions sont appelées automatiquement au DOMContentLoaded. Appelez-les manuellement après avoir injecté du HTML dynamique :

// Après injection de HTML dynamique
initElements(monConteneur);
initAnimations(monConteneur);
initIcons(monConteneur);

Inclure dans une page

<link rel="stylesheet" href="core/css/elements.css">
<script src="core/js/elements.js" defer></script>
Problèmes courants
  • Le slider ne fonctionne pas : vérifiez que elements.js est chargé avec defer. La classe .slider doit être présente sur le conteneur.
  • Le popup ne s'ouvre pas : le data-popup-target du bouton doit correspondre exactement au data-popup du popup.
  • Les tabs ne changent pas : chaque data-tab doit avoir un data-tab-panel correspondant avec la même valeur.
  • L'accordion ne se déplie pas : l'attribut data-accordion-multi est nécessaire pour permettre l'ouverture simultanée de plusieurs panneaux.
  • Le slider drag ne marche pas sur mobile : ajoutez data-slider-drag="true" au conteneur.

Accessibilité

  • Les popups se ferment avec la touche Escape.
  • Les accordions s'ouvrent/ferment au clic.
  • Les tooltips apparaissent au focus clavier en plus du hover.
  • Les tabs changent de panneau au clic.
  • Les sliders se contrôlent via les boutons, le drag tactile et l'autoplay.
  • Toutes les animations respectent prefers-reduced-motion.