Portals

A portal lets a component render its output into a different part of the DOM — typically a node at the bottom of — while keeping it a normal child of your React tree. It's the standard tool for modals, tooltips, toasts, and dropdowns : anything that must visually escape a parent's overflow , z-index , or transform without losing its place in your component logic.

Learn Portals — Modals & Tooltips in our free React course — a beginner-friendly interactive lesson with runnable examples, a practice exercise and a quick…

Part of the free React course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

1️⃣ The Problem Portals Solve

Picture a modal rendered inside a sidebar card that has overflow: hidden . Your full-screen overlay gets clipped to the card's edges . Or a parent has z-index: 1 and your modal can't rise above the header. Portals fix this by moving the DOM output elsewhere:

The demo below models the core idea — a component renders content but the output is placed in a different container:

2️⃣ The createPortal Signature

It's a single function with two arguments: what to render and where to render it.

The domNode must already exist in the page. Most apps add a single to index.html . Your turn — fill in the target container so the tooltip mounts into "tooltip-root" :

3️⃣ Events Bubble Through the React Tree

Here's the detail that trips people up: even though a portal's DOM node lives somewhere else, React events bubble through the React tree — the place where you wrote the portal, not where the DOM ended up. A click inside a portaled modal still reaches an onClick on the component that rendered it.

The demo walks the React bubble path so you can see handlers fire up the tree even though the DOM node is elsewhere:

These lines of a portal-based Tooltip are scrambled. Put them in the correct order:

1) Your modal is being clipped by a parent's overflow: hidden . What's the fix?

Render it through a portal into a node at the end of , so it escapes the clipping ancestor entirely.

2) A button inside a portal is clicked. Will an onClick on the component that rendered the portal fire?

Yes. React events bubble through the React tree, not the DOM tree, so the rendering ancestor still hears the click.

3) What are the two arguments to createPortal ?

The JSX to render, and the existing DOM node to render it into: createPortal(children, domNode) .

📋 Quick Reference

Toasts almost always live in a portal so they float above everything. Model a toast that mounts a message into the "toast-root" container with a level icon — "success" → "✅".

Practice quiz

Which function creates a React portal?

  • ReactDOM.render
  • usePortal
  • createPortal
  • renderInto

Answer: createPortal. createPortal(children, domNode) renders the children into a different DOM node.

Where is createPortal imported from?

  • react-dom
  • react
  • react-router-dom
  • react/portals

Answer: react-dom. createPortal comes from react-dom, not react.

What are the two main arguments to createPortal?

  • A ref and a callback
  • A component and its props
  • A selector string and an event
  • The JSX/children and the target DOM node

Answer: The JSX/children and the target DOM node. createPortal(children, domNode) takes the JSX to render and an existing DOM node to render it into.

A click inside a portal bubbles through which tree?

  • The DOM tree only
  • The React tree (where the portal was rendered)
  • Neither — events don't bubble from portals
  • The CSS cascade

Answer: The React tree (where the portal was rendered). React events bubble through the React tree, so the rendering ancestor still hears the click even though the DOM node is elsewhere.

What problem do portals primarily solve for modals?

  • They escape parent overflow, z-index, and transform clipping
  • They make state global
  • They prevent re-renders
  • They add accessibility automatically

Answer: They escape parent overflow, z-index, and transform clipping. A portal lifts the DOM output out of clipping ancestors so the overlay can cover the screen.

The target DOM node passed to createPortal must…

  • Be created inside the component's JSX
  • Be a React component
  • Already exist in the page (e.g. a div in index.html)
  • Be the document body only

Answer: Already exist in the page (e.g. a div in index.html). The domNode must already exist; most apps add a <div id="modal-root"> to index.html.

Do Context and state still work inside a portal?

  • No, the portal is isolated from the React tree
  • Yes, the portal is a normal child in the React tree
  • Only state works, not Context
  • Only if you pass them as props

Answer: Yes, the portal is a normal child in the React tree. A portal is a real child in the React tree, so it inherits everything its React ancestors provide.

If getElementById returns null when calling createPortal, the likely cause is…

  • The component is memoized
  • createPortal was imported from react
  • The portal has no key
  • The target div doesn't exist yet in the DOM

Answer: The target div doesn't exist yet in the DOM. Calling getElementById before the target div exists returns null; add it to index.html or create it first.

To stop a backdrop click from closing a modal when clicking inside it, you…

  • Remove the onClick
  • Call e.stopPropagation() on the inner box
  • Use a portal
  • Set z-index to 0

Answer: Call e.stopPropagation() on the inner box. stopPropagation on the inner box prevents the click from reaching the backdrop's close handler.

Which is true about a portaled dialog and accessibility?

  • The portal handles focus trapping for you
  • Portals make dialogs inaccessible
  • You still own focus trap, Escape-to-close, and ARIA roles
  • ARIA roles are added automatically

Answer: You still own focus trap, Escape-to-close, and ARIA roles. The portal only moves the DOM; you still need role="dialog", focus trapping, and Escape-to-close.