Implementing Modal/Popup on Website
Modal windows have many hidden problems: focus management, scroll behind modal, z-index conflicts, animations, mobile keyboard shift. Native <dialog> solves most without JS.
Native <dialog>: Correct Foundation
Modal with showModal() blocks background via ::backdrop. Use createPortal for React. Close on Escape or backdrop click. Focus trap built-in.
import { useEffect, useRef, ReactNode } from 'react'
import { createPortal } from 'react-dom'
export function Modal({
isOpen, onClose, title, children,
size = 'md',
closeOnBackdrop = true,
}: ModalProps) {
const dialogRef = useRef<HTMLDialogElement>(null)
useEffect(() => {
const dialog = dialogRef.current
if (!dialog) return
if (isOpen) {
dialog.showModal()
document.body.style.overflow = 'hidden'
} else {
dialog.close()
document.body.style.overflow = ''
}
}, [isOpen])
return createPortal(
<dialog ref={dialogRef} className={`modal modal--${size}`}>
<div className="modal__content">
{title && <h2 className="modal__title">{title}</h2>}
<div className="modal__body">{children}</div>
</div>
</dialog>,
document.body
)
}
CSS animation for modal entrance and exit with smooth transitions.
Focus Trap
Keep focus inside modal during interaction. Native dialog handles this automatically.
Bottom Sheet for Mobile
Position fixed from bottom with safe-area inset adjustment for iOS.
Timeline
Basic modal with animation — 3–4 hours. React component with portal, focus trap — 1 day. Full system with confirm/alert API, stack support — 1.5–2 days.







