Portal Rendering: Breaking Free from the DOM Hierarchy
If you’ve ever tried to build a modal, tooltip, dropdown, or floating panel in React, you’ve probably run into layout or z-index headaches.
React Portals are designed to solve those problems by letting you render a component outside of its normal DOM hierarchy while keeping it fully connected to React’s component tree.
This article walks through what portal rendering is, why it exists, how to use it, and some best practices and pitfalls to watch out for.
What Is a Portal in React?
In a typical React app, components render into a single root DOM node, for example:
<div id="root"></div>Your entire React tree lives under this element. However, there are many UI patterns where you want part of your UI to live elsewhere in the DOM:
- A modal that must be a direct child of <body> to escape overflow/positioning constraints.
- A tooltip that needs to overlay the whole page, not just a specific component.
- A dropdown that should not be clipped by overflow: hidden or stacking contexts.
A portal lets you render a part of your React tree into a different DOM node:
- Logically: the component still belongs to the same React tree, with the same props, state, and context.
- Physically: the resulting DOM nodes are mounted somewhere else in the document.
React exposes this via ReactDOM.createPortal, Ref for more
Basic Example of a Portal
Even though the Modal is used inside App, its DOM elements are actually mounted under #modal-root. Yet, the modal still has full access to its props, state, and inherited context.
Why Use Portals?
- Escaping Overflow and Positioning Constraints
- Cleaner DOM Structure for Overlays
- Despite living elsewhere in the DOM, Still Part of the Same React Tree
How createPortal Works
The API is simple:
ReactDOM.createPortal(child, container);- child: Any renderable React node (JSX, string, fragment, etc.).
- container: A DOM element where the content should be mounted.
Under the hood, React keeps the reconciliation logic (diffing, updates) connected to the original component tree, while delegating the final DOM insertion to the container.
Common Use Cases
- Modals and Dialogs
- Tooltips and Popovers
- Dropdowns and Menus
Event Bubbling and Portals
One of the most important things to understand: events in portals still bubble through the React tree, not just the DOM tree.
Even though your modal’s DOM is outside #root, a click inside the portal will still propagate through React’s event system as if it were rendered inside its logical parent.
NOTE: Clicking the button in the modal will still trigger handleClick on App. This is by design and can be very useful, but be aware of it when handling global click handlers (e.g., click-outside behaviors).
Similarly, Portals do not break context. If a portal is rendered from within a context provider, it can still consume that context.
Even though the modal DOM is outside the provider in the DOM tree, it is still inside in the React tree, so useContext works as expected.
Best Practices for Portal Rendering
- Use a dedicated root: Create specific DOM nodes (#modal-root, #tooltip-root) to keep things organized.
- Handle accessibility: For modals and dialogs, add ARIA roles (role=”dialog”), aria-modal=”true”, and implement focus trapping and keyboard support (Esc to close).
- Clean up dynamically created containers: If you create container elements in code, remove them on unmount to avoid memory leaks.
- Avoid overusing portals: Not every overlay needs a portal. Use them when you truly need to escape layout/stacking constraints.
- Be mindful of scroll and focus: When a modal opens, consider locking background scroll and moving focus into the modal. Restore focus on close.
Common Pitfalls
- Forgetting the container element: If document.getElementById(‘modal-root’) returns null, the portal will fail. Always ensure the container exists.
- Z-index confusion: Portals don’t magically fix all z-index problems. You still need a coherent layering strategy in your CSS.
- Server-Side Rendering (SSR): When using SSR, guard any direct document or window access to avoid errors during initial server render.
- Click-outside behaviors: Since events bubble through the React tree, global click handlers may fire for portal clicks too. Use stopPropagation or precise target checks where needed.
Conclusion
Portal rendering in React gives you a powerful way to:
- Visually decouple parts of your UI from the main DOM hierarchy,
- While logically keeping them in the same React tree with shared state and context.
Before You Go…
If this deep dive on React Portals helped you level up, don’t let the learning stop here.
- Stay ahead of the curve — Follow me on medium to receive the deep dives directly into your inbox for fresh, and practical insights.
- Let’s connect on LinkedIn.
If you like the technical and insight full discussions/deep dives make sure to subscribe my YouTube channel for more amazing stuff.
