---
title: Modal Maze
slug: modal-maze
kind: anti-pattern
summary: A modal opens a modal opens a modal — each one blocking the context the next one needs, until nobody can see the record they are supposedly editing.
problem: >-
  You open a record in a modal, click Edit inside it, get a second modal, need
  to pick a client, get a third. The page underneath — the one with the
  information you need to answer the question — has been blocked three times
  over by the software that is asking you the question.
family: [inspect, act]
principles: [orientation, progressive-disclosure]
status: stable
visibility: public
related:
  - title: Drawer vs Modal vs Page
    url: /patterns/drawer-vs-modal-vs-page
    summary: The decision that prevents this — three surfaces, three promises about context.
  - title: Master–Detail Drawer
    url: /patterns/master-detail-drawer
    summary: The usual right answer for the record that got put in a modal.
---

## How you get here

Modals are the cheapest way to add a screen. They need no route, no layout
decision and no thought about where the thing lives. So the first one appears
reasonably — a short confirm, a small form — and then each subsequent need is
solved the same way, because the mechanism is already there.

The second modal is not a new mistake. It is the **first modal admitting it was
carrying too much**.

## How to recognise it

- Two or more overlays stacked, with two dimmed layers behind.
- Escape closes the wrong one, or closes all of them and loses everything typed.
- A modal has grown tabs, or a stepper, or its own scrollbar.
- Someone needs a value from the page behind and has to close, look, reopen, and
  retype.
- The modal cannot be linked to, so "look at this record" is a set of
  instructions rather than a URL.
- The browser Back button leaves the page entirely instead of closing the top
  layer.

## Why it fails

A modal makes exactly one promise: **this is the only thing that matters right
now.** Stacking them breaks the promise on the first repetition — clearly the
thing underneath also mattered, because you are still holding it.

The specific damage is to context. A modal deliberately blocks the page, so
anything you need from that page is unreachable. In a single modal that is an
acceptable trade for a bounded task. In a stack it is the reason the person is
stuck, and it produces the worst workaround in internal software: opening the
same record in a second browser tab to read what the modal is covering.

## The way out

1. **Never open a modal from a modal.** Treat this as a hard rule; it is the one
   that keeps the rest honest.
2. When you want to, **promote the first modal to a page**. It has outgrown the
   surface, and the second modal is the evidence.
3. If the parent list must stay visible, that is a
   [drawer](/patterns/master-detail-drawer), not a modal — and a drawer can host
   a genuine modal above it for a bounded confirm.
4. **Pick one surface per kind of object** and use it everywhere. Most mazes
   grow in products where the same record opens three different ways.
5. **Give anything with depth a URL.** If people need to share it, it was never
   a modal.

## The one legitimate stack

A confirmation over a form — "discard your changes?" — is a genuine second
layer, because it is *about* the first one and it is bounded, immediate and has
one way out. That is the exception, and it is the only one worth allowing.

## The test

Count the dimmed layers on screen. More than one, and something on the stack
deserved a page. Then check whether Escape closes only the top layer and Back
does something sensible — if not, people are already losing work.
