Navigation✨ Premium

Context Menu

Menu contextuel déclenché au clic droit, positionné exactement au curseur et retourné automatiquement quand il déborderait les bords du conteneur.

JSClickPosition

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

Éditeur de contenu — Actions sur élément sélectionné — Context Menu exemple 1

① Éditeur de contenu — Actions sur élément sélectionné

QuandL'utilisateur fait un clic droit sur un nœud, un bloc ou un objet dans un éditeur de design, un rich-text ou un outil de wireframing.
PourquoiLe menu apparaît exactement là où se trouve le curseur et ne sort jamais de la zone d'édition — même dans les coins — grâce à la logique d'inversion automatique. Aucune navigation vers un panneau latéral n'est nécessaire.
RéglagesItems : ✎ Éditer / 📋 Copier / 📄 Dupliquer / [séparateur] / 🗑 Supprimer. Fond #1e1b4b, min-width: 180px, border-radius: 10px.
Dashboard — Actions rapides sur une ligne de tableau — Context Menu exemple 2

② Dashboard — Actions rapides sur une ligne de tableau

QuandClic droit sur une ligne d'un tableau de données (CRM, analytics, gestion de commandes) pour accéder aux actions sans quitter le contexte courant.
PourquoiLe menu contextuel évite d'ouvrir une page de détail pour des actions courantes (exporter, archiver, dupliquer) — gain de temps mesurable sur des workflows répétitifs à fort volume.
RéglagesItems : 👁 Voir le détail / ⬇ Exporter CSV / 📄 Dupliquer / [séparateur] / 🗑 Archiver. Fond #111827, bordure rgba(75,85,99,.3), texte #d1d5db.
Gestionnaire d'assets — Clic droit sur une vignette fichier — Context Menu exemple 3

③ Gestionnaire d'assets — Clic droit sur une vignette fichier

QuandDans un CMS, un gestionnaire de médias ou un explorateur de fichiers intégré, l'utilisateur clic-droite sur une vignette pour accéder aux opérations fichier.
PourquoiL'effet reproduit le comportement attendu d'un explorateur de fichiers OS, ce qui réduit la courbe d'apprentissage — les utilisateurs trouvent les actions sans chercher dans des menus imbriqués.
RéglagesItems : ✎ Renommer / 📁 Déplacer / ⬇ Télécharger / [séparateur] / 🗑 Supprimer. min-width: 160px, séparateur avant Supprimer pour signaler l'action destructive.

Comment ça marche

L'événement contextmenu est capturé via preventDefault() pour neutraliser le menu natif du navigateur. La position d'ouverture est calculée en coordonnées relatives au conteneur : clientX - rect.left / clientY - rect.top — le menu s'ouvre exactement là où le curseur se trouve, quelle que soit la position de défilement de la page.

Le menu est d'abord déplacé hors écran (left: -9999px) pour être rendu visible par le navigateur sans être perceptible. Un requestAnimationFrame attend ensuite que le navigateur calcule ses dimensions réelles via getBoundingClientRect(). Ce délai d'un frame est la condition nécessaire pour connaître la hauteur et la largeur exactes du menu avant de le positionner définitivement.

La logique d'inversion aux bords compare position + largeur (et hauteur) du menu aux dimensions du conteneur. Si le menu déborderait à droite, il est décalé à containerWidth - menuWidth - 8 px ; idem vers le bas. Un plancher à 4 px garantit qu'il ne sort jamais à gauche ni en haut.

La classe .open active l'apparition via une transition CSS (opacity 0→1, scale 0.95→1, 150 ms). La fermeture se déclenche sur tout clic en dehors du menu (listener click sur document) ou sur la touche Escape.

Accessibilité

  • prefers-reduced-motion non géré : la transition d'apparition (opacity + scale, 150 ms) s'applique à tous les utilisateurs, y compris ceux qui ont activé « réduire les animations » dans leur OS. Ajouter @media (prefers-reduced-motion: reduce) { .ctx-menu { transition: none } } si nécessaire.
  • Les items du menu sont des <button> natifs — focusables au clavier et correctement annoncés par les lecteurs d'écran.
  • Aucun rôle ARIA menu / menuitem n'est appliqué, et aucun aria-expanded n'est posé sur la zone déclencheuse — la sémantique de menu contextuel ARIA n'est pas implémentée dans ce code.
  • La fermeture par Escape est implémentée via un listener keydown sur document.
  • Les raccourcis clavier (Ctrl+C, Del…) affichés dans les items sont du texte décoratif — ils ne sont liés à aucun handler dans ce code.

Compatibilité navigateur

Utilise uniquement l'événement contextmenu, getBoundingClientRect et requestAnimationFrame — disponibles dans tous les navigateurs modernes sans polyfill.

Chrome 80+✓ Complet
Firefox 75+✓ Complet
Safari 13+✓ Complet
Edge 80+✓ Complet
iOS Safari✓ Appui long → contextmenu
Android Chrome✓ Appui long → contextmenu

Si JS est désactivé, aucun menu personnalisé n'apparaît et le menu natif du navigateur reste actif — aucune erreur, la page reste fonctionnelle.

Le code

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

index.html — structure
<div class="context-scene" id="contextScene">
  <!-- Contenu de la zone cliquable (texte, image, objets…) -->

  <div class="ctx-menu" id="ctxMenu">
    <button class="ctx-item">
      <span class="ctx-icon">✎</span>
      Éditer
      <span class="ctx-key">Ctrl+E</span>
    </button>
    <button class="ctx-item">
      <span class="ctx-icon">📋</span>
      Copier
      <span class="ctx-key">Ctrl+C</span>
    </button>
    <div class="ctx-sep"></div>
    <button class="ctx-item">
      <span class="ctx-icon">🗑</span>
      Supprimer
      <span class="ctx-key">Del</span>
    </button>
  </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
.ctx-menu { background } #1e1b4b Couleur de fond du menu — remplacez par votre couleur de surface brand (ex. #111827 pour un thème gris sombre, #1c1c1e pour un style macOS).
.ctx-menu { border-color } rgba(99,102,241,.2) Couleur de la bordure et de l'accent hover des items — alignez sur votre couleur primaire.
.ctx-item { color } #c7d2fe Couleur du texte des items au repos. Augmentez le contraste à #e2e8f0 pour un meilleur ratio WCAG.
.ctx-menu { min-width } 170px Largeur minimale du menu — augmentez à 200–220 px si vos libellés sont longs ou si vous ajoutez des icônes plus larges.
.ctx-menu { border-radius } 12px Arrondi des coins du menu. Mettez 6px pour un style compact ou 16px pour un style macOS.
Marge de bord (JS — valeur 8 dans la logique d'inversion) 8 px Distance de sécurité entre le menu et le bord du conteneur lors de l'inversion. Augmentez si votre conteneur a du padding interne.

FAQ

e.preventDefault() dans le handler contextmenu supprime déjà le menu natif sur la zone ciblée (.context-scene). Si vous l'intégrez dans une zone iframe, ajoutez également preventDefault() dans le listener de l'iframe — les événements ne traversent pas les frontières de frame automatiquement.
Ce composant ne gère pas les sous-menus nativement. Pour en ajouter, interceptez mouseenter sur l'item parent, positionnez un second .ctx-menu à droite (ou à gauche si le premier est en bord droit) en réutilisant la même logique de calcul getBoundingClientRect. Le listener click existant sur document fermera naturellement tous les niveaux à la fois.
Sur iOS Safari et Android Chrome, un appui long (long-press) déclenche l'événement contextmenu — le menu personnalisé s'affiche aussi sur mobile. Sur certains navigateurs, le menu natif peut apparaître brièvement avant d'être supprimé ; ajoutez -webkit-touch-callout: none et user-select: none sur la zone cible pour réduire ce comportement.