What are React Portals used for?
By FrontendPro Editorial Team Updated 9/26/2026
Answer
A portal renders a component's DOM output somewhere else in the document, while keeping it in the React tree where you wrote it. You use it for anything that must visually escape its parent's box: modals, dropdowns, tooltips, and toasts.
import { createPortal } from 'react-dom';
function Modal({ children, onClose }) {
return createPortal(
<div className="overlay" onClick={onClose}>{children}</div>,
document.body // lands here in the DOM
);
}
The problem it solves
CSS traps children. A parent with overflow: hidden clips them, z-index only competes within a stacking context, and a transform or filter on an ancestor creates a new containing block that position: fixed is then measured against. A modal nested six levels deep inside a scrollable card cannot get out of that by styling alone.
Rendering to document.body sidesteps all of it — no ancestor overflow, no inherited stacking context.
The part people find surprising
The portal moves the DOM node, not the React relationship. So inside the portal you still have:
- The same context from the providers above it.
- The same props and state from the parent.
- Events that bubble to the React parent, not to the DOM parent. A click inside a portal fires a handler on the ancestor component that rendered it, which is usually what you want — and occasionally a surprise, because it means
stopPropagationon an outer wrapper still applies.
That is the whole point: visually detached, logically attached.
What a portal does not give you
Accessibility is still yours to handle. A portal is a positioning tool, not a dialog implementation. For a modal you still need focus to move in on open and back on close, focus trapped while open, Escape to dismiss, aria-modal and a label, and the background made inert.
Which is why the modern answer to "how do I build a modal" is usually not a portal at all:
<dialog ref={ref}>...</dialog> // ref.current.showModal()
The native <dialog> element renders in the top layer, above every stacking context, and gives you focus trapping, Escape, and inertness for free. popover does the same for dropdowns and tooltips. Portals remain useful for toasts, for wrapping a third-party widget, and wherever you need the React tree and the DOM tree to differ for other reasons.
One SSR note
createPortal needs a DOM node, so it cannot run during server rendering. Guard it — render nothing until mounted, or use a client-only boundary — otherwise document is undefined on the server.
