Tutorials Logic, IN info@tutorialslogic.com
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Website Development
Practice
Quiz Challenge Interview Questions Certification Practice
Tools
Online Compiler JSON Formatter Regex Tester CSS Unit Converter Color Picker
Compiler Tools

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

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 JSX you want to render
  • The DOM node where that JSX should appear
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')

    )

}

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

Portal Mount Points

Many React projects add one or more extra mount points in index.html. A common pattern is to keep the main app inside #root and reserve another element such as #modal-root for portal content.

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
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
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
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:

  • 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

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.

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.

Key Takeaways
  • Portals let a React component render into a different DOM node.
  • They are useful for modals, tooltips, dropdowns, and overlays.
  • Portals solve layout issues such as overflow clipping and z-index conflicts.
  • Portal content still belongs to the same React tree.
  • Context, props, state, and event bubbling still work normally in portals.
  • createPortal is imported from react-dom.
  • A portal usually renders into a separate DOM node like modal-root.
  • Good portal components should handle cleanup and accessibility concerns.

Ready to Level Up Your Skills?

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