Portails pour les modales et les infobulles
Utilisez ReactDOM.createPortal pour afficher des enfants dans un autre nœud DOM, afin de créer des modales et des infobulles qui s’affranchissent des conteneurs overflow:hidden.
Portails pour les modales et les infobulles est une leçon Frontend Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Frontend Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Frontend Academy comprend 4 leçons au total.
Le problème de l’échappement du conteneur
Les fenêtres modales et les info-bulles doivent être rendues à la racine du DOM afin d’échapper à overflow:hidden, à l’empilement de z-index et aux contextes fondés sur transform de leur parent. La solution : les portails.
API createPortal
createPortal(children, container) effectue le rendu des enfants dans le conteneur (n’importe quel nœud DOM), tout en les maintenant logiquement comme des enfants du composant React pour les événements et le contexte.
import { createPortal } from 'react-dom';
function Modal({ children, onClose }) {
return createPortal(
<div className="modal-backdrop" onClick={onClose}>
<div className="modal-content" onClick={e => e.stopPropagation()}>
{children}
</div>
</div>,
document.body
);
}Conteneurs de portail
Cibles courantes : document.body, une div #modal-root dédiée dans index.html, ou un conteneur référencé par ref et créé à la demande.
<!-- index.html -->
<div id="root"></div>
<div id="modal-root"></div>
// component:
const modalRoot = document.getElementById('modal-root');
return createPortal(<div>...</div>, modalRoot);Pourquoi ne pas effectuer simplement le rendu en ligne ?
Si un parent possède overflow: hidden, une fenêtre modale enfant est tronquée. Si un parent possède transform: scale, le positionnement fixe de la fenêtre modale devient relatif au parent. Les portails évitent tous ces problèmes.
Les événements continuent à remonter
Bien que le rendu soit effectué ailleurs dans le DOM, les événements React remontent dans l’arbre des composants, et non dans l’arbre DOM. Un clic dans le portail remonte toujours jusqu’aux gestionnaires onClick des composants React ancêtres.
Fermer lors d’un clic sur la superposition
Arrêtez la propagation des événements sur le contenu de la fenêtre modale afin que les clics à l’intérieur ne la ferment pas.
function Modal({ onClose, children }) {
return createPortal(
<div className="backdrop" onClick={onClose}>
<div className="content" onClick={e => e.stopPropagation()}>
{children}
</div>
</div>,
document.body
);
}Fermer avec la touche Échap
Ajoutez un écouteur keydown tant que la fenêtre modale est ouverte et supprimez-le lors du démontage.
useEffect(() => {
const onKey = (e) => { if (e.key === 'Escape') onClose(); };
window.addEventListener('keydown', onKey);
return () => window.removeEventListener('keydown', onKey);
}, [onClose]);Gestion du focus dans les portails
Lorsqu’une fenêtre modale s’ouvre : déplacez le focus à l’intérieur, retenez-le jusqu’à la fermeture, puis rétablissez-le sur l’élément qui a ouvert la fenêtre modale. Utilisez une bibliothèque comme focus-trap-react pour éviter de réimplémenter ce mécanisme.
Élément dialog natif
Le <dialog> de HTML gère nativement le positionnement de la fenêtre modale, l’arrière-plan, le confinement du focus et la fermeture avec Échap. Pour la plupart des fenêtres modales, c’est un meilleur point de départ qu’un portail.
function Modal({ open, onClose, children }) {
const ref = useRef(null);
useEffect(() => {
if (open) ref.current?.showModal();
else ref.current?.close();
}, [open]);
return (
<dialog ref={ref} onClose={onClose}>
{children}
</dialog>
);
}Info-bulles et fenêtres contextuelles
Les info-bulles se positionnent par rapport à un élément d’ancrage. Un portail leur permet d’échapper aux contextes d’empilement. Combinez-le avec floating-ui pour la détection des collisions, l’inversion et le positionnement.
import { useFloating, autoUpdate } from '@floating-ui/react';
function Tooltip({ children, content }) {
const { refs, floatingStyles } = useFloating({ whileElementsMounted: autoUpdate });
const [open, setOpen] = useState(false);
return (
<>
<button ref={refs.setReference} onMouseEnter={() => setOpen(true)} onMouseLeave={() => setOpen(false)}>
{children}
</button>
{open && createPortal(
<div ref={refs.setFloating} style={floatingStyles}>{content}</div>,
document.body
)}
</>
);
}Point d’attention concernant SSR
document n’existe pas sur le serveur. Effectuez le rendu uniquement côté client (vérifiez typeof window) ou utilisez le mode dynamique de Next.js avec ssr:false.
Accessibilité : aria-modal
Les conteneurs de fenêtres modales doivent posséder role="dialog", aria-modal="true" et aria-labelledby pointant vers le titre de la fenêtre modale. Vous pouvez aussi utiliser l’élément natif <dialog>.
Vérification rapide
Pourquoi utiliser createPortal pour les fenêtres modales plutôt que d’effectuer leur rendu en ligne dans l’arbre des composants ?
Récapitulatif : portails
createPortal(children, container) effectue le rendu du DOM ailleurs tout en conservant un arbre React logique. Il résout les problèmes liés à l’échappement de overflow, transform et z-index. Les événements continuent à remonter dans l’arbre React. Ajoutez la fermeture avec Échap et la gestion du focus. L’élément natif <dialog> gère une grande partie de ces aspects pour les fenêtres modales. Combinez-le avec floating-ui pour les info-bulles. N’oubliez pas le SSR (vérification de typeof window).
Questions Fréquemment Posées
La leçon « Portails pour les modales et les infobulles » est-elle gratuite ?
Oui — le texte complet de « Portails pour les modales et les infobulles » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Frontend Academy, passe à CoddyKit PRO. Le cours Frontend Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Portails pour les modales et les infobulles » ?
Utilisez ReactDOM.createPortal pour afficher des enfants dans un autre nœud DOM, afin de créer des modales et des infobulles qui s’affranchissent des conteneurs overflow:hidden. Tu pratiques Frontend Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Frontend Academy ?
Aucune expérience préalable n'est requise. Frontend Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.
Combien de temps prend la leçon « Portails pour les modales et les infobulles » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Frontend Academy ?
Oui. Chaque leçon Frontend Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Composants composés avec Context
- Render Props et schémas HOC
- Portails pour les modales et les infobulles
- Frontières d’erreur