
React Portals Explained

Some React UI problems are not really about React at all. They are about the DOM.
Modals, overlays, tooltips, and dropdown panels often want to appear visually outside the normal layout hierarchy. If we render them exactly where the component sits in the tree, they can end up clipped by overflow, trapped inside stacking contexts, or awkwardly layered under other content.
That is why React Portals exist.
They let us render part of a React subtree into a different place in the DOM while still keeping it inside the same React application.
A Portal Changes DOM Placement, Not React Ownership
This is the most important thing to understand.
With a portal, the element appears elsewhere in the DOM, but it still belongs to the same React tree logically.
That means state, props, and event behaviour still connect back to the component that created it.
In React, that looks like this:
import ReactDOM from 'react-dom';const Modal = ({ children }: { children: React.ReactNode }): JSX.Element => ReactDOM.createPortal( <div className="modal">{children}</div>, document.getElementById('modal-root') as HTMLElement, );The modal content might be rendered under a top‑level #modal‑root element near the end of body, even if the component using it lives much deeper in the interface.
Why This Helps with Overlays
Overlays often need freedom from their parent's layout constraints.
If a modal is rendered inside a container with:
overflow: hidden- complex positioning
- a lower stacking context
then keeping it in that exact DOM branch can make the UI harder to layer correctly.
Portals let the overlay escape that physical DOM location without forcing the whole state model to move somewhere else.
Modals are the Classic Use Case
Imagine a page component rendering a button that opens a dialog:
const ProductPage = (): JSX.Element => { const [isOpen, setIsOpen] = useState(false); return ( <> <button onClick={() => setIsOpen(true)}>Open size guide</button> {isOpen && ( <Modal> <button onClick={() => setIsOpen(false)}>Close</button> </Modal> )} </> );};The open state can still live with the page component, which is where the interaction belongs. The modal itself can render elsewhere in the DOM so the layering stays sane.
The matching DOM target is usually simple as well:
<body> <div id="__next"></div> <div id="modal-root"></div></body>That is often all a portal needs. The React ownership stays with the page component, whilst the final DOM placement moves to a top‑level node better suited to overlays.
Event Bubbling Still Follows the React Tree
This is one of the more interesting details.
Even though the portal content is rendered elsewhere in the DOM, events still bubble through the React component tree rather than becoming disconnected from it.
That means a parent component can still handle events from content rendered in a portal.
This behaviour often surprises people at first, but it is part of what makes portals feel integrated rather than bolted on.
Portals Solve Placement Problems, Not All Modal Problems
This is a good warning to keep in mind.
Rendering a dialog through a portal does not automatically make it accessible or well‑behaved.
You still need to think about:
- keyboard focus
- focus return when closing
- escape‑key handling
- background interaction
- screen‑reader semantics
The portal helps with DOM placement. It does not finish the component design for you.
Tooltips and Dropdowns Can Benefit Too
Modals are the obvious example, but the same principle applies to other floating UI:
- tooltip layers
- context menus
- autocomplete panels
- dropdown menus
Any UI that needs to escape clipping or stacking problems may benefit from portal rendering.
That said, not every dropdown needs a portal. If ordinary DOM placement works cleanly, forcing a portal in too early can make the code more complex than necessary.
Accessibility Still Needs Deliberate Work
This matters enough to say twice in different words.
The portal moves where the node is rendered, but it does not tell assistive technology what the thing is supposed to be.
A real modal still needs a good accessibility story:
- appropriate dialog semantics
- trapped focus while open
- inert or hidden background content where necessary
- a reliable closing mechanism
Without those pieces, a portal‑driven modal can still be a poor modal.
It Helps to Separate Logical Tree from Physical Tree
That is the mental model that makes portals click.
The React tree represents ownership, state, and component relationships.
The DOM tree represents actual document placement.
Most of the time, those structures line up closely enough that we do not think about the distinction. Portals are one of the places where React lets us separate them deliberately.
When Not to Use a Portal
If a component does not have a real placement problem, a portal may be unnecessary.
For example, wrapping every floating box in a portal by default can create extra indirection without solving a real issue. The right test is practical:
Is the UI genuinely fighting layout, overflow, or stacking in its current location?
If yes, a portal may help.
If not, keeping the markup in its ordinary place is often simpler.
Portals are About Escaping DOM Constraints Without Breaking Component Structure
That is why they are useful.
Before portals, developers often had to choose between:
- awkward DOM nesting
- moving state ownership to an unnatural place
Portals reduce that tension. The parent component can still own the interaction, while the DOM output can move to a place better suited to floating UI.
This is a Structural Feature, Not a Visual Trick
Seen properly, portals are not just a hack for modals. They are a way of saying:
"This UI belongs here in the React tree, but it needs to appear elsewhere in the DOM."
Once you understand that sentence, the feature becomes very intuitive.
It is one of React's cleaner answers to a real browser constraint, and it is most valuable when used exactly where the DOM would otherwise get in the way.
Related Articles

Enhancing User Experience with CSS and JavaScript Animations. 
Using Vue's Teleport for Modals and Portals. Using Vue's Teleport for Modals and Portals

Margin Collapse in CSS. Margin Collapse in CSS

The Difference Between == and === in JavaScript. The Difference Between
==and===in JavaScript
10 Essential SEO Tips for Front‑End Developers. 10 Essential SEO Tips for Front‑End Developers

Asynchronous Module Definition (AMD) in JavaScript. Asynchronous Module Definition (AMD) in JavaScript

What is a Static Site Generator? What is a Static Site Generator?

Trigonometric Functions in CSS. Trigonometric Functions in CSS

Array.find(), Array.some(), and Array.every() in JavaScript. Array.find(),Array.some(), andArray.every()in JavaScriptUse CSS to Change the Mouse Cursor. Use CSS to Change the Mouse Cursor

Understanding Arrow Functions in JavaScript. Understanding Arrow Functions in JavaScript

Using Regex to Replace Numbers in a String. Using Regex to Replace Numbers in a String