Tutorials Logic, IN info@tutorialslogic.com

React Portals Modals Tooltips Outside DOM: Tutorial, Examples, FAQs & Interview Tips

React Portals Modals Tooltips Outside DOM

React in React is best learned by connecting the rule to an interactive form or modal. Start with the smallest component or hook, observe the output, and then add one realistic constraint so the concept becomes practical.

The key habit for this lesson is to watch props, state, and rendered JSX as it changes. That makes the topic easier to debug, easier to explain in interviews, and easier to use in real code without memorizing isolated syntax.

What are Portals in React?

Portals let you render part of a React component into a different place in the DOM. Normally, a component renders inside its parent element. A portal allows that same component to stay in the React tree while its HTML is inserted somewhere else, such as directly inside document.body or a separate DOM node like #modal-root.

This is useful when a UI element needs to visually escape its container. For example, a modal should appear above the whole screen, a tooltip should float over other elements, and a dropdown should not be cut off by a parent with overflow: hidden.

Even though the portal content is rendered elsewhere in the DOM, React still treats it as part of the same component tree. That means props, state, context, and event bubbling still work the React way.

Why Portals Are Needed

  • Modals often need to appear above the entire page
  • Tooltips and dropdowns should not be clipped by parent containers
  • Floating UI elements often need a different stacking context
  • Portals help solve z-index and overflow layout problems cleanly
  • They allow better separation between React structure and DOM placement

How createPortal Works

React provides portals through createPortal from react-dom. It takes two main values:

The component is still written and managed in the same React app, but its output is mounted into a different DOM node.

  • The JSX you want to render
  • The DOM node where that JSX should appear

Basic Portal Syntax

Basic Portal Syntax
import { createPortal } from 'react-dom'



function Example() {

    return createPortal(

        <div>This content is rendered somewhere else in the DOM.</div>,

        document.getElementById('portal-root')

    )

}

Portal Mount Points

React portals are easiest to manage when the DOM has a second mount point beside the main root. Keeping modal or tooltip content in a separate container avoids z-index fights and lets the rendered tree stay where React expects it while the element appears elsewhere in the DOM.

index.html Setup

index.html Setup
<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8" />

    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <title>React App</title>

</head>

<body>

    <div id="root"></div>

    <div id="modal-root"></div>

</body>

</html>

Modal Example with a Portal

A modal is the most common portal example. If you render a modal inside a deeply nested component, it may be affected by the parent layout. Rendering it through a portal avoids those problems and lets the modal sit above the whole page.

Modal with createPortal

Modal with createPortal
import { createPortal } from 'react-dom'

import { useEffect } from 'react'



function Modal({ isOpen, onClose, title, children }) {

    useEffect(() => {

        if (!isOpen) return



        const handleKeyDown = (event) => {

            if (event.key === 'Escape') {

                onClose()

            }

        }



        document.addEventListener('keydown', handleKeyDown)

        document.body.style.overflow = 'hidden'



        return () => {

            document.removeEventListener('keydown', handleKeyDown)

            document.body.style.overflow = ''

        }

    }, [isOpen, onClose])



    if (!isOpen) return null



    return createPortal(

        <div className="modal-overlay" onClick={onClose}>

            <div className="modal-box" onClick={(e) => e.stopPropagation()}>

                <div className="modal-header">

                    <h2>{title}</h2>

                    <button onClick={onClose}>Close</button>

                </div>

                <div className="modal-body">{children}</div>

            </div>

        </div>,

        document.getElementById('modal-root')

    )

}



export default Modal

Modal Example with a Portal

Modal Example with a Portal
import { useState } from 'react'

import Modal from './Modal'



function App() {

    const [open, setOpen] = useState(false)



    return (

        <div style={{ overflow: 'hidden', height: '220px' }}>

            <h2>Portal Example</h2>

            <p>This container has limited space, but the modal will still appear correctly.</p>

            <button onClick={() => setOpen(true)}>Open Modal</button>



            <Modal isOpen={open} onClose={() => setOpen(false)} title="Delete Item">

                <p>Are you sure you want to delete this item?</p>

                <button onClick={() => setOpen(false)}>Cancel</button>

                <button onClick={() => setOpen(false)}>Delete</button>

            </Modal>

        </div>

    )

}

Tooltip Example

Tooltips are another great use case for portals. A tooltip often needs to appear above nearby content and ignore clipping from parent elements. With a portal, the tooltip can be positioned visually where it belongs without being trapped by the local layout.

Tooltip with a Portal

Tooltip with a Portal
import { createPortal } from 'react-dom'

import { useRef, useState } from 'react'



function Tooltip({ text, children }) {

    const [visible, setVisible] = useState(false)

    const [position, setPosition] = useState({ top: 0, left: 0 })

    const triggerRef = useRef(null)



    const showTooltip = () => {

        const rect = triggerRef.current.getBoundingClientRect()



        setPosition({

            top: rect.top + window.scrollY - 36,

            left: rect.left + window.scrollX + rect.width / 2

        })

        setVisible(true)

    }



    return (

        <>

            <span

                ref={triggerRef}

                onMouseEnter={showTooltip}

                onMouseLeave={() => setVisible(false)}

            >

                {children}

            </span>



            {visible && createPortal(

                <div

                    style={{

                        position: 'absolute',

                        top: position.top,

                        left: position.left,

                        transform: 'translateX(-50%)',

                        background: '#222',

                        color: '#fff',

                        padding: '6px 10px',

                        borderRadius: '4px',

                        fontSize: '12px',

                        whiteSpace: 'nowrap',

                        zIndex: 9999

                    }}

                >

                    {text}

                </div>,

                document.body

            )}

        </>

    )

}

Important Portal Behavior

One thing that surprises beginners is that a portal changes where content appears in the DOM, but it does not remove it from the React tree. That leads to several important behaviors:

For example, if a button inside a portal is clicked, React event handling can still reach a parent component higher in the React tree even though the DOM nodes are separated.

  • Context still works inside portal content
  • State still belongs to the original component
  • Events bubble through the React tree, not the visual DOM structure
  • Parent components can still control portal children normally with props

Common Use Cases

  • Modal dialogs
  • Tooltips
  • Dropdown menus
  • Hover cards
  • Toast notifications
  • Full-screen overlays
  • Context menus

Best Practices for Portals

  • Use portals only when layout escape is actually needed
  • Keep portal mount points clearly named such as modal-root
  • Clean up event listeners when the portal closes
  • Handle keyboard interactions like the Escape key for modals
  • Prevent background scrolling when full-screen overlays are open
  • Think about accessibility, especially focus management and screen reader support

Common Mistakes

  • Forgetting to create the target DOM node in index.html
  • Assuming the portal is outside the React tree
  • Not removing event listeners when the portal unmounts
  • Ignoring keyboard and focus behavior in modals
  • Using portals for normal layout when plain component structure would be simpler

Summary

React portals solve a visual placement problem. They let you keep a component in the same React hierarchy while rendering its HTML somewhere else in the DOM. This is especially useful for UI elements that must appear above the rest of the page or escape container layout restrictions.

Once you understand createPortal, you can build modals, tooltips, overlays, and other floating UI in a cleaner and more reliable way.

Applied guide for React

Use React when the program needs a clear answer to a specific problem, not because the keyword looks familiar. In a real React task, first name the input, then name the transformation, then name the output. This small discipline shows whether the topic is being used correctly or only copied from an example.

A reliable practice flow is: create the smallest working component or hook, add one normal case, add one edge case such as nested modals and Escape-key closing, and then confirm the result with React DevTools and test output. If the result surprises you, reduce the code until the behavior is visible again.

The most common trap here is moving the DOM node but forgetting focus and cleanup. Avoid it by writing one sentence before the code that explains why React is the right choice. After the code runs, verify the lesson by doing this: inspect the DOM target and tab order.

  • Identify the exact problem solved by React.
  • Trace props, state, and rendered JSX before and after the main operation.
  • Keep one intentionally broken version and explain the fix.
  • Connect the example to an interactive form or modal so the idea feels concrete.
Key Takeaways
  • I can explain where React fits inside an interactive form or modal.
  • I can point to the exact props, state, and rendered JSX affected by this topic.
  • I tested a normal case and an edge case involving nested modals and Escape-key closing.
  • I verified the result with React DevTools and test output instead of assuming it worked.
  • I can describe the main mistake: moving the DOM node but forgetting focus and cleanup.
Common Mistakes to Avoid
WRONG Moving the DOM node but forgetting focus and cleanup.
RIGHT Write the expected behavior first, then make the example prove it.
A one-line expectation turns the code from copied syntax into a testable idea.
WRONG Practicing only the perfect input.
RIGHT Also test nested modals and Escape-key closing before considering the lesson complete.
The edge case is where most interview follow-up questions begin.
WRONG Looking only at the final output.
RIGHT Trace props, state, and rendered JSX through each important step.
Tracing makes debugging faster because you can see the first incorrect state.

Practice Tasks

  • Build one small component or hook that demonstrates React in an interactive form or modal.
  • Change the example to include nested modals and Escape-key closing and record the difference.
  • Break the example by deliberately moving the DOM node but forgetting focus and cleanup, then write the corrected version.
  • Explain the finished example in five bullet points: input, operation, output, failure case, and verification.

Frequently Asked Questions

Use it when the problem matches the behavior shown in the example and when the result can be verified through React DevTools and test output.

Start with a tiny case, then test nested modals and Escape-key closing. The main warning sign is moving the DOM node but forgetting focus and cleanup.

Trace props, state, and rendered JSX, predict the result, run the example, and compare your prediction with the actual output.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.