DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
World desk3 min

React Modal Component Example: Build One Inline or with a Portal

A practical React modal example shows when to use a portal and what focus and keyboard behavior you still need to implement.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Here is a working React modal you can adapt, plus the key choice behind it: render it inline when the surrounding layout allows, or use a portal when an ancestor clips or constrains the overlay. A portal only changes where the dialog appears in the DOM; it does not provide keyboard focus management or accessibility behavior.

Choose inline rendering or a portal

A modal can render in its ordinary place in the component tree. That is the simplest option when ancestor layout and stacking styles do not interfere. If a parent’s styles—such as overflow: hidden—clip the overlay, render the modal through a portal into an existing DOM node, often document.body or a dedicated overlay root.

As an Amazon Associate I earn from qualifying purchases.

React’s createPortal(children, domNode) changes the physical DOM placement while preserving the component’s place in the React tree. Context remains available, and events from portal content can still bubble to React ancestors. If an ancestor has a click handler, account for that behavior where needed. React: createPortal

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Approach When it fits What to check
Inline rendering The surrounding layout does not clip or obscure the overlay. Ancestor overflow and stacking styles.
Portal rendering The dialog needs to escape a constrained ancestor. The target DOM node exists when the portal renders; React event bubbling still follows the React tree.

Neither approach supplies modal focus behavior or makes a dialog accessible by itself.

A basic React modal component example

This rendering skeleton keeps open state in the owning component, mounts the modal only while open, names the dialog through its visible heading, and uses a portal to place it under document.body.

import { useState } from 'react';
import { createPortal } from 'react-dom';

function Modal({ onClose }) {
  return createPortal(
    <div className="backdrop" onMouseDown={onClose}>
      <section
        role="dialog"
        aria-modal="true"
        aria-labelledby="example-modal-title"
        onMouseDown={event => event.stopPropagation()}
      >
        <h2 id="example-modal-title">Example dialog</h2>
        <p>Dialog content goes here.</p>
        <button type="button" onClick={onClose}>Close</button>
      </section>
    </div>,
    document.body
  );
}

export default function App() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button type="button" onClick={() => setOpen(true)}>Open dialog</button>
      {open && <Modal onClose={() => setOpen(false)} />}
    </>
  );
}

The example stops a mouse-down inside the dialog from reaching the backdrop handler. For a real interface, decide deliberately whether clicking the backdrop dismisses the dialog; if it does, distinguish a backdrop click from interaction with dialog content. The skeleton does not implement keyboard focus management or other production modal behavior.

Complete the modal’s keyboard and assistive-technology behavior

A modal dialog creates a separate interaction context while it is open. The WAI-ARIA Authoring Practices describe the expected pattern: move focus into the dialog, keep keyboard navigation within it, support Escape dismissal where appropriate, and return focus to the control that opened it when it closes. Follow the pattern for focus placement and Tab sequence rather than assuming the portal or dialog role handles them. WAI-ARIA Authoring Practices: Dialog (Modal) Pattern

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Name the dialog: connect its visible heading with aria-labelledby, as in the example.
  • Set modal semantics truthfully: use aria-modal="true" when the background is unavailable for interaction. This communicates that state to assistive technology; it does not itself disable or hide background controls.
  • Manage focus: move focus into the dialog on open, contain Tab and Shift+Tab navigation while it is modal, and restore focus to the opener on close.
  • Handle dismissal: support Escape when appropriate and ensure the close button works with keyboard and pointer input.
  • Keep the dialog exposed: do not apply aria-hidden to an ancestor that also contains the dialog. The dialog must remain available to assistive technology. W3C WAI: Modal Dialog Example

Also consider scroll locking and coordination if dialogs can be stacked. The short example does not implement those behaviors, nor is it a complete focus-management implementation. Test keyboard interaction and assistive-technology behavior in the environments your application supports.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

What a portal does—and does not do

Use a portal to solve a DOM-placement problem, such as clipping by an ancestor. It does not trap focus, provide a dialog’s accessible name, or prevent interaction with the background. Those responsibilities belong to the modal’s semantics and interaction logic. React’s portal documentation also notes that focus management may be necessary. React: createPortal

Because portal events still bubble through the React tree, a click inside a modal can reach a React ancestor’s handler even though the portal’s DOM node is elsewhere. Stop propagation or adjust the ancestor handler if that behavior is inappropriate.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.