---
name: "[up-defer]"
area: "API"
kind: "HTML attribute"
parent: "up.link module"
url: "https://unpoly.com/api/up-defer"
---
<nav aria-label="Unpoly docs">[All docs](https://unpoly.com/index.md) · [up.link module](https://unpoly.com/api/up.link.md)</nav>

# [up-defer]

A placeholder for content to be loaded later from another URL.

By moving expensive but non-[critical](https://developer.mozilla.org/en-US/docs/Web/Performance/Critical_rendering_path) fragments into partials, you can paint critical content earlier.

<nav aria-label="Guides">

- [Learn: Lazy loading content](https://unpoly.com/learn/lazy-loading.md)

</nav>

## Example {#example}

Identify fragments that are expensive to render on the server, but aren't immediately required. For example, you may have a large navigation menu that only appears once the user clicks a menu icon:

```html
<div id="menu">
  Hundreds of links here
</div>
```

To remove the menu from the initial render pass, extract its contents to its own route, like `/menu`.

In the initial view, only leave a placeholder element and mark it with an `[up-defer]` attribute. Also set an [`[up-href]`](https://unpoly.com/api/up-href.md) attribute with the URL from which to load the deferred content:

```html
<div id="menu" up-defer up-href="/menu">
  Loading...
</div>
```

The placeholder content can display a pending state while the full content is loading.

When the `[up-defer]` placeholder is rendered, it will immediately make a request to fetch its content from `/menu`:

```http
GET /menu HTTP/1.1
X-Up-Target: #menu
```

> #### Note
>
> By default the placeholder is [targeting](https://unpoly.com/learn/targeting-fragments.md) itself (`#menu`). For this the element must have a [derivable target selector](https://unpoly.com/learn/target-derivation.md).

The server is now expected to respond with a page containing `#menu` with content:

```html
<div id="menu">
  Hundreds of links here
</div>
```

The element in the response should no longer have an `[up-defer]` attribute, as this would cause infinite reloading.

The server is free to send additional elements or even a full HTML document. Only `#menu` will be updated on the page. Other elements from the response will be discarded.

---

## Modifying attributes {#attributes}

> #### Info
>
> All modifying attributes for [`[up-follow]`](https://unpoly.com/api/up-follow.md) may also be used.

### Timing {#attributes-timing}

#### [up-defer='insert'] {#up-defer}

(optional)

When to load and render the deferred content.

When set to `'insert'` (the default), the deferred content will load immediately when the `[up-defer]` element is inserted into the DOM.

When set to `'reveal'`, the deferred content will load when the `[up-defer]` placeholder is scrolled into the [viewport](https://unpoly.com/api/up-viewport.md). If the element is already visible when inserted, loading will start immediately. Also see [loading as the placeholder becomes visible](https://unpoly.com/learn/lazy-loading.md#on-reveal).

When set to `'manual'`, the deferred content will not load on its own. You can control the load timing by calling [`up.deferred.load()`](https://unpoly.com/api/up.deferred.load.md) from your own JavaScript.

#### [up-intersect-margin='0'] (Experimental) {#up-intersect-margin}

(optional)

With `[up-defer=reveal]`, this enlarges the viewport by the given number of pixels before computing the intersection.

A positive number will load the deferred content some pixels before it becomes visible.

A negative number will require the user to scroll some pixels into the element before it is loaded.

### Targeting {#attributes-targeting}

#### [up-target=':origin'] {#up-target}

(optional)

A selector for the fragment to render the content in.

By default the `[up-defer]` element itself will be replaced with the loaded content. For this the element must have a [derivable target selector](https://unpoly.com/learn/target-derivation.md).

You may target one or [multiple](https://unpoly.com/learn/targeting-fragments.md#multiple) fragments. To target the placeholder itself, you can use the [`:origin`](https://unpoly.com/api/origin.md) target instead of spelling out a selector.

#### [up-fail] {#up-fail}

(optional)

How to handle [error responses](https://unpoly.com/learn/error-responses.md).

By default, a server response with an error code is not rendered, and the placeholder keeps its fallback content.

Set `[up-fail=false]` to render _any_ response that contains a matching fragment, even with a 4xx or 5xx status code.

#### [up-fail-target] {#up-fail-target}

(optional)

A selector for the fragment to render an [error response](https://unpoly.com/learn/error-responses.md) in.

By default, a server response with an error code is not rendered.

### Request {#attributes-request}

#### [up-href] {#up-href}

(optional)

The URL from which to load the deferred content.

If your `[up-defer]` placeholder is a [standard hyperlink](https://unpoly.com/learn/lazy-loading.md#seo), you can use an `[href]` attribute instead.

#### [up-headers] {#up-headers}

(optional)

A [relaxed JSON](https://unpoly.com/api/relaxed-json.md) object with additional request headers.

#### [up-background='false'] {#up-background}

(optional)

Whether to load the deferred content [in the background](https://unpoly.com/learn/background-requests.md).

Background requests will not show the [global progress bar](https://unpoly.com/learn/progress-bar.md).

### Caching {#attributes-caching}

#### [up-cache='auto'] {#up-cache}

(optional)

Whether to read from and write to the [cache](https://unpoly.com/learn/caching.md).

With `[up-cache=true]` Unpoly will try to re-use a cached response before connecting to the network. To prevent display of stale content, cached responses are [reloaded once rendered](#up-revalidate). If no cached response exists, Unpoly will make a request and cache the server response.

With `[up-cache=auto]` Unpoly will use the cache only if [`up.network.config.autoCache`](https://unpoly.com/api/up.network.config.md#config.autoCache) returns `true` for the request. By default this only caches `GET` requests.

With `[up-cache=false]` Unpoly will always make a network request.

#### [up-revalidate='auto'] {#up-revalidate}

(optional)

Whether to [reload the targeted fragment](https://unpoly.com/learn/caching.md#revalidation) after it was rendered from a cached response.

With `[up-revalidate='auto']`, Unpoly will revalidate [expired](https://unpoly.com/learn/caching.md#expiration) responses. This behavior can be configured with [`up.fragment.config.autoRevalidate(response)`](https://unpoly.com/api/up.fragment.config.md#config.autoRevalidate).

With `[up-revalidate='true']`, Unpoly will always revalidate cached content, regardless of its age.

With `[up-revalidate='false']`, Unpoly will never revalidate cached content.

#### [up-revalidate-preview] (Experimental) {#up-revalidate-preview}

(optional)

The name of a [preview](https://unpoly.com/learn/previews.md) that runs while [revalidating cached content](https://unpoly.com/learn/caching.md#revalidation).

#### [up-expire-cache] {#up-expire-cache}

(optional)

Whether existing [cache](https://unpoly.com/learn/caching.md) entries will be [expired](https://unpoly.com/learn/caching.md#expiration) when this request is sent.

By default a non-GET request will expire the entire cache. Set `[up-expire-cache="false"]` to not expire any cache entries. You may also pass a [URL pattern](https://unpoly.com/api/url-patterns.md) to only expire matching requests.

Also see [`up.request({ expireCache })`](https://unpoly.com/api/up.request.md#options.expireCache) and [`up.network.config.expireCache`](https://unpoly.com/api/up.network.config.md#config.expireCache).

#### [up-evict-cache] {#up-evict-cache}

(optional)

Whether existing [cache](https://unpoly.com/learn/caching.md) entries will be [evicted](https://unpoly.com/learn/caching.md#eviction) when this request is sent.

By default no cache entries are evicted. You may also pass a [URL pattern](https://unpoly.com/api/url-patterns.md) to only evict matching requests.

Also see [`up.request({ evictCache })`](https://unpoly.com/api/up.request.md#options.evictCache) and [`up.network.config.evictCache`](https://unpoly.com/api/up.network.config.md#config.evictCache).

