Solid.js Portals — Rendering Outside the DOM Tree
In this tutorial, you will learn about Solid.js Portals. We cover key concepts, practical examples, and best practices to help you master this topic.
Learn Solid.js portals: render components outside the parent DOM hierarchy for modals, tooltips, and overlays.
In this lesson, you'll use Solid.js portals to render content in a different DOM location while maintaining the component hierarchy.
What You'll Learn
How to use portals, render to different DOM targets, maintain event propagation, and use portals for modals and overlays.
Why It Matters
Portals solve problems where CSS constraints (overflow, z-index) prevent proper rendering: modals, dropdowns, tooltips, and notifications.
Real-World Use
Doda Browser uses a portal for its modal dialog and notification toast system, ensuring they render above all page content.
flowchart TD
A[App Root] --> B[Portal Target]
C[Parent] --> D[Portal]
D --> B
B --> E[Modal Content]
style D fill:#2c4f7c,color:#fff
Basic Portal
import { Portal } from "solid-js/web";
function Modal({ isOpen, onClose, children }) {
return (
<Portal>
<div class="modal-overlay" onClick={onClose}>
<div class="modal-content" onClick={(e) => e.stopPropagation()}>
{children}
</div>
</div>
</Portal>
);
}
The modal renders at the end of document.body, above all other content.
Portal with Target
<Portal mount={document.getElementById("tooltips")}>
<Tooltip>Help text here</Tooltip>
</Portal>
Event Bubbling
Events from portal content bubble up through the React component tree, not the DOM tree:
function App() {
const handleClick = () => console.log("Portal click");
return (
<div onClick={handleClick}>
<Portal>
<button>Click me</button>
{/* Clicking this button triggers handleClick */}
</Portal>
</div>
);
}
Portal for Notifications
function NotificationContainer() {
return (
<Portal>
<div class="notification-container">
<For each={notifications()}>
{(n) => <NotificationItem {...n} />}
</For>
</div>
</Portal>
);
}
Common Mistakes
- Not cleaning up portals: Portals are automatically cleaned up when the component unmounts. No manual cleanup needed.
- Using portals unnecessarily: For simple overlays that don't have z-index issues, regular positioning is simpler.
- Forgetting to stop event propagation: Click handlers on the overlay may conflict with click handlers on the content.
- Mount target doesn't exist: Ensure the
mountelement exists before the portal renders. Create it in a parent component. - Portal inside a portal: Nesting portals works but can be confusing. One portal level is usually sufficient.
Practice Questions
What problem do portals solve? Answer: Rendering content outside DOM ancestors, avoiding CSS constraints like overflow hidden and z-index stacking.
Where does a portal render by default? Answer: At the end of
document.body, unless amounttarget is specified.Do portal events bubble through the React tree? Answer: Yes. Events from portal content bubble through the parent component hierarchy, not the DOM hierarchy.
How do you specify a custom mount target? Answer: Use the
mountprop:<Portal mount={document.getElementById('target')}>.
Challenge
Build a dropdown menu using a portal that renders above all page content. The dropdown should open on click, close on click outside, and handle window resize.
Mini Project
Create a notification toast system using portals: a NotificationProvider that renders a portal container, a useNotifications hook, and toast components for success, error, and info messages.
FAQ
What's Next
Learn about Solid.js Error Boundaries for handling errors in components.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro