Skip to content

React Portals

Portals render children into a DOM node outside the parent hierarchy — typically document.body. Modals, tooltips, and dropdowns use portals to escape overflow:hidden containers and z-index stacking issues.

createPortal API

createPortal(child, domNode) renders React tree into another DOM node while preserving React event bubbling through the React component hierarchy.

The modal JSX lives logically under <App /> but physically mounts in #modal-root in index.html.

import { createPortal } from 'react-dom';

function Modal({ open, onClose, children }) {
  if (!open) return null;
  return createPortal(
    <div className="overlay" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>{children}</div>
    </div>,
    document.getElementById('modal-root')
  );
}

Add <div id="modal-root"></div> to index.html for portal targets.

Portal Use Cases

createPortal(<Tooltip />, document.body)
createPortal(<DropdownMenu />, menuRoot)
  • Events bubble in React tree, not DOM tree — onClick on overlay still works.
  • Use for modals, drawers, popovers, and full-screen overlays.
  • Manage focus trap and aria for accessible modals.
  • Clean up portal target or leave persistent root in HTML.

Portal Patterns

Common portal applications.

Use Case Target Node
Modal dialog #modal-root or body
Tooltip body
Dropdown menu Near trigger or body
Toast notifications #toast-root
Full-screen loader body

Portal Accessibility

Modals need focus trap, role="dialog", aria-modal="true", Escape to close, and return focus to trigger on close. Libraries like Radix UI and Headless UI handle this.

Portals and SSR

Ensure portal target exists before createPortal — check typeof document !== 'undefined' in SSR or render portal only after mount with useEffect.

Common Mistakes

  • Missing portal root element in HTML.
  • No focus management in modal portals.
  • Assuming DOM parent affects React event handlers — it doesn't.
  • Creating new portal root on every render.

Key Takeaways

  • Portals render UI into external DOM nodes.
  • Ideal for modals, tooltips, and overlays.
  • React events still bubble through component tree.
  • Implement focus trap and ARIA for modals.

Pro Tip

Reach for Radix Dialog or Headless UI Modal before building portal + focus trap from scratch.