Learn Placeholders

Placeholders are temporary spinners or UI skeletons shown within a fragment while it is loading. They appear instantly after the user's interaction and are replaced by the server response.

In a demo app, the user clicks "Projects" in the navigation bar. While the list is loading, gray bars in the shape of a heading, a button and table rows take the place of the content. Then the user clicks "New project". A modal overlay opens with the skeleton of a form, which the real form replaces when it has loaded.

By providing clues for how the page will ultimately look, placeholders make long-loading interactions feel more responsive.

Basic placeholders

To show a placeholder while a link is loading, set an [up-placeholder] attribute with the placeholder's HTML as its value:

<a href="/path" up-target="#target" up-placeholder="<p>Loading…</p>">Show story</a> <!-- mark: up-placeholder="<p>Loading…</p>" -->

<div id="target">
  Old content
</div>

When the link is clicked, the targeted fragment's content is hidden. In its place the placeholder is inserted as the only visible child of #target:

<div id="target">
  <up-wrapper hidden>Old content</up-wrapper>
  <p>Loading…</p> <!-- mark-line -->
</div>

When the response is received, #target is updated with new HTML from the server:

<div id="target">
  New content from server
</div>

Like all preview effects, a placeholder only temporarily displaces a fragment. When the request ends for any reason, the placeholder is removed and the original content is restored before the response is processed. This also happens when the server responds with an error, or when the request is aborted.

Placeholders are not shown when content is rendered from the cache. See using previews with caching.

Forms can show placeholders the same way, by setting [up-placeholder] on the <form> element. When targeting multiple fragments, the placeholder is shown in the first fragment.

From JavaScript

In your scripts you may pass a { placeholder } option to most rendering functions:

up.navigate({
  url: '/path',
  target: '#target',
  placeholder: '<p>Loading…</p>' // mark-line
})

Instead of passing an HTML snippet you may also pass an Element or a template reference.

Placeholders from templates

Instead of passing the placeholder HTML directly, you can refer to any template by its CSS selector. This is useful when you don't want to set a long HTML string as an attribute value, or when you want to reuse the same placeholder many times:

<a href="/path" up-target="#target" up-placeholder="#loading-template">Show story</a> <!-- mark: up-placeholder="#loading-template" -->

<div id="target">
  Old content
</div>

<template id="loading-template"> <!-- mark: id="loading-template" -->
  <p>
    Loading…
  </p>
</template>

Dynamic templates

You may need to customize placeholder markup to better fit the targeted fragment. For example, a spinner animation should be larger when updating a larger content area. Also when building a UI skeleton, its shapes must resemble the eventual screen state to be believable.

To limit the proliferation of template variants, you can make a few templates that are customizable with variables. When referring to a template, append the variables as a data object after the template selector:

<a
  href="/path"
  up-target="#target"
  up-placeholder="#loading-template { size: 'xl', message: 'Please wait' }"> <!-- mark: #loading-template { size: 'xl', message: 'Please wait' } -->
  Show story
</a>

The template can then use the variables:

<script id="loading-template" type="text/minimustache">
  <p class="{{size}}">
    {{message}}
  </p>
</script>

Tip

This example uses the minimal text/minimustache templating function that you can copy into your project. See Dynamic templates for different strategies to build customizable templates.

Placeholders for new overlays

You can use placeholders with links that open an overlay:

<a href="/path" up-follow up-layer="new" up-placeholder="<p>Loading…</p>">Open overlay</a> <!-- mark: up-placeholder="<p>Loading…</p>" -->

This opens a temporary overlay with the same visual style and open animation as the link's overlay would have shown.

When the server response is received, the temporary overlay is closed and another overlay is opened with the response content. The close and open animations are disabled for this switch.

When the response ends up not opening an overlay (e.g. the server responds with an error code), the placeholder overlay is closed.

If the user dismisses the placeholder overlay before the server responds, the request is aborted.

Arbitrary placeholder logic

Sometimes you need more than templates and variables can give you:

  • Complex placeholder construction logic
  • Showing a placeholder in a fragment that wasn't targeted
  • Placeholders that affect multiple fragments

In such cases you can define a preview, which describes arbitrary loading state in JavaScript. A preview can show a placeholder in any element with up.Preview#showPlaceholder(). For example, this preview shows a loading message in a #sidebar element while the targeted fragment is loading:

up.preview('sidebar-loading', function(preview) {
  preview.showPlaceholder('#sidebar', '<p>Loading…</p>') // mark: showPlaceholder
})

The placeholder is removed when the preview ends, just like a placeholder set with [up-placeholder].