---
area: "Learn"
parent: "Learn"
url: "https://unpoly.com/learn/overlays"
---
<nav aria-label="Unpoly docs">[All docs](https://unpoly.com/index.md) · [Learn](https://unpoly.com/learn.md)</nav>

# Overlays

Unpoly can open any URL in an overlay, like a modal dialog or a drawer. An overlay can show a single fragment or host an interaction that spans multiple pages. When it closes, an overlay can pass a result value back to the layer that opened it.

<nav aria-label="Contents">

#### Contents

- [Opening an overlay](#opening-an-overlay)
- [Layers are isolated](#layers-are-isolated)
- [Layer modes](#layer-modes)
- [Closing overlays](#closing-overlays)
- [Subinteractions](#subinteractions)
- [Changing an overlay's appearance](#changing-an-overlays-appearance)
- [See also](#see-also)

</nav>

## Opening an overlay {#opening-an-overlay}

Any link can open its destination in a new overlay:

```html
<a href="/users/new" up-layer="new">Add user</a>
```

The server renders `/users/new` as a full HTML page, the same way it would for a regular page load. Unpoly extracts the page's [main fragment](https://unpoly.com/api/main.md) and shows it in a modal overlay. The user can dismiss the overlay by pressing `Escape`, by clicking the backdrop, or with its close button.

The link stays a standard hyperlink. When the user opens it in a new tab, or when JavaScript is unavailable, the browser loads `/users/new` as a full page.

Forms, your JavaScript and the server can open overlays too.

<nav aria-label="Read more">

- [More: Opening overlays](https://unpoly.com/learn/opening-overlays.md)

</nav>

## Layers are isolated {#layers-are-isolated}

Links and forms always update fragments within their own layer. A form in an overlay re-renders inside that overlay, even when the page behind it contains an element with the same selector. JavaScript functions like [`up.fragment.get()`](https://unpoly.com/api/up.fragment.get.md) also match in the current layer only.

Because of this isolation, you can write a screen once and open it as a full page or in an overlay, without the screen knowing the difference.

A link can still update another layer by targeting it explicitly. For example, a link inside an overlay can update the root layer:

```html
<a href="/users" up-layer="root">Show all users</a>
```

See [Targeting other layers](https://unpoly.com/learn/targeting-other-layers.md) for all ways to address another layer.

## Layer modes {#layer-modes}

The appearance and behavior of a layer is called its _mode_. The root layer's mode is always `root`. For overlays, these modes are available:

| Mode | Description |
| --- | --- |
| `modal` | A box centered over a dimmed backdrop |
| `drawer` | A drawer sliding in from the side |
| `popup` | A popup menu anchored to a link |
| `cover` | An overlay covering the entire screen |

When no mode is given, a new overlay opens as a `modal`. To choose a different mode, append it to the `[up-layer]` attribute:

```html
<a href="/menu" up-layer="new drawer">≡ Menu</a>
```

You can change the default mode in [`up.layer.config.mode`](https://unpoly.com/api/up.layer.config.md#config.mode).

## Closing overlays {#closing-overlays}

There are many ways to close an overlay. The user can press `Escape`, click the backdrop or use the close button. A button, link or form inside the overlay can close it, and so can your JavaScript or the server.

Every close has an intent: an overlay is _accepted_ when the user completed their task, or _dismissed_ when they canceled. An accepted overlay can pass a result value back to the layer that opened it, like the ID of a newly created record:

```html
<button up-accept="{ id: 5 }">Choose user #5</button>
```

<nav aria-label="Read more">

- [More: Closing overlays](https://unpoly.com/learn/closing-overlays.md)

</nav>

## Subinteractions {#subinteractions}

The link that opens an overlay can also decide when the overlay's task is done, like when it reaches a URL, emits an event or renders a fragment. The overlay then closes automatically, and a callback on the link receives the result value.

With this, you can embed any existing screen as a step of a larger interaction. A user filling in a project form can create a missing company in an overlay, without leaving the half-completed form. The project form opens the company form, waits for the new record, and selects it:

```html
<fieldset>
  <label for="company">Company</label>
  <select id="company" name="company">...</select>
</fieldset>

<a href="/companies/new"
  up-layer="new"
  up-accept-location="/companies/$id"
  up-on-accepted="up.validate('select', { params: { company: value.id } })">
  New company
</a>
```

The company form has no idea it is part of a project form. It is the same screen the user would see when creating a company on its own.

<nav aria-label="Read more">

- [More: Subinteractions](https://unpoly.com/learn/subinteractions.md)

</nav>

## Changing an overlay's appearance {#changing-an-overlays-appearance}

Overlays ship with minimal styling. When opening an overlay, you can pick a size and assign your own CSS classes to style it:

```html
<a href="/terms" up-layer="new" up-size="large" up-class="legal">Show terms</a>
```

Drawers and popups can be positioned, and opening and closing can be animated.

<nav aria-label="Read more">

- [More: Customizing overlays](https://unpoly.com/learn/customizing-overlays.md)

</nav>

## See also {#see-also}

To address a layer other than the current one, like the page behind an overlay, see [Targeting other layers](https://unpoly.com/learn/targeting-other-layers.md).

To keep state for the lifetime of an overlay, like the record a reused screen is picking for, see [Layer context](https://unpoly.com/learn/layer-context.md).

To control whether an overlay's location shows in the address bar, see [History in overlays](https://unpoly.com/learn/history-in-overlays.md).

To ask for confirmation in an overlay instead of the browser's native dialog, see [styled confirmation dialogs](https://unpoly.com/learn/confirmation-dialogs.md#styled).

<nav aria-label="In this chapter">

## In this chapter {#children-index-title}

- [Opening overlays](https://unpoly.com/learn/opening-overlays.md)
- [Closing overlays](https://unpoly.com/learn/closing-overlays.md)
- [Subinteractions](https://unpoly.com/learn/subinteractions.md)
- [Customizing overlays](https://unpoly.com/learn/customizing-overlays.md)
- [Targeting other layers](https://unpoly.com/learn/targeting-other-layers.md)
- [Layer context](https://unpoly.com/learn/layer-context.md)
- [History in overlays](https://unpoly.com/learn/history-in-overlays.md)

</nav>

<nav aria-label="Reading order">

- [Previous: Watch options](https://unpoly.com/learn/watch-options.md)
- [Next: Opening overlays](https://unpoly.com/learn/opening-overlays.md)

</nav>

