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

# Target derivation

When Unpoly is given an element instead of a selector, it guesses a CSS selector that [matches that element](https://unpoly.com/learn/targeting-fragments.md). This is called _target derivation_. A good guess needs an identifying attribute like `[id]`, and you can configure how the guess is made.

In the example below, Unpoly derives a target selector for an element that is being reloaded:

```js
let element = document.querySelector('#foo')
up.reload(element) // Derives the target '#foo' from the given element
```

Features that must derive targets include [`[up-poll]`](https://unpoly.com/api/up-poll.md), [`[up-hungry]`](https://unpoly.com/api/up-hungry.md), [`[up-keep]`](https://unpoly.com/api/up-keep.md), [`[up-validate]`](https://unpoly.com/api/up-validate.md), [`[up-viewport]`](https://unpoly.com/api/up-viewport.md), [`up.reload(Element)`](https://unpoly.com/api/up.reload.md) and [`up.render(Element)`](https://unpoly.com/api/up.render.md).

<nav aria-label="Contents">

#### Contents

- [Identifying properties](#identifying-properties)
- [Derivation patterns](#derivation-patterns)
- [Derived target verification](#verification)
- [Deriving a target programmatically](#deriving-a-target-programmatically)

</nav>

## Identifying properties {#identifying-properties}

To build a good selector, the element needs an _identifying property_ that distinguishes it from other elements on the same [layer](https://unpoly.com/api/up.layer.md). The most important properties that Unpoly looks for are:

- The element's `[id]` or [`[up-id]`](https://unpoly.com/api/up-id.md) attribute
- The tag name of a page-unique element (`<html>`, `<head>`, `<body>`, `<main>`)
- The element's `[name]` attribute
- The element's `[class]` names, ignoring [`up.fragment.config.badTargetClasses`](https://unpoly.com/api/up.fragment.config.md#config.badTargetClasses)

When none of these properties are found, Unpoly tries [additional derivation patterns](#derivation-patterns) before giving up.

When Unpoly cannot derive a good target for an element, or when the derived target matches the wrong element, give the element an `[id]` attribute. That is HTML's standard way of identifying an element on the page.

## Derivation patterns {#derivation-patterns}

The patterns for target derivation are configured in [`up.fragment.config.targetDerivers`](https://unpoly.com/api/up.fragment.config.md#config.targetDerivers). Each pattern produces a target selector when it applies to the element. Patterns are tried in order, so earlier entries have priority.

These are the default patterns, with examples of the selectors they produce:

```js
up.fragment.config.targetDerivers = [
  '[up-id]',                     // [up-id="foo"]
  '[id]',                        // #foo
  'html',                        // html
  'head',                        // head
  'body',                        // body
  'main',                        // main
  '[up-main]',                   // [up-main="root"]
  (element) => { ... },          // up-modal (the tag name of <up-*> elements)
  'link[rel][type]',             // link[rel="alternate"][type="application/rss+xml"]
  'link[rel=preload][href]',     // link[rel="preload"][href="/font.woff2"]
  'link[rel=preconnect][href]',  // link[rel="preconnect"][href="https://cdn.example.com"]
  'link[rel=prefetch][href]',    // link[rel="prefetch"][href="/next.html"]
  'link[rel]',                   // link[rel="canonical"]
  'meta[property]',              // meta[property="og:title"]
  '*[name]',                     // input[name="email"]
  'form[action]',                // form[action="/users"]
  'a[href]',                     // a[href="/users"]
  '[class]',                     // .foo.bar (filtered by up.fragment.config.badTargetClasses)
  '[up-flashes]',                // [up-flashes=""]
  'form',                        // form
]
```

A pattern only applies to elements it describes. The pattern `'link[rel]'` only applies to `<link rel="...">` elements and is skipped for anything else.

An attribute in a pattern is expanded to include the element's actual attribute value, so the pattern `a[href]` produces a target like `a[href="/users"]`. An asterisk (`*`) is expanded to the element's tag name. Values are fixed for a few attributes, like `rel=preload`.

To derive targets for elements that none of the patterns describe, push a pattern string of your own:

```js
up.fragment.config.targetDerivers.push('[data-id]') // [data-id="5"]
```

If your deriver can't be expressed in a pattern string, push a function that takes an [`Element`](https://developer.mozilla.org/en-US/docs/Web/API/Element) and returns a selector. A function that cannot handle the given element should return `undefined`, so the next pattern is tried.

## Derived target verification {#verification}

Unpoly verifies that a derived target actually matches the element it was derived from. When another element is matched instead, the next applicable pattern in [`up.fragment.config.targetDerivers`](https://unpoly.com/api/up.fragment.config.md#config.targetDerivers) is tried.

For example, the second card below cannot use its class as a target, since `.card` would match the first card:

```html
<div class="card">...</div>
<div class="card">...</div> <!-- no target can be derived -->
```

Verification rejects `.card` and moves on to the next pattern. If no pattern produces a matching target, an error `up.CannotTarget` is thrown. In such cases, give the element an `[id]` attribute, or configure a new [derivation pattern](#derivation-patterns).

Verification can be [disabled](https://unpoly.com/api/up.fragment.config.md#config.verifyDerivedTarget) with `up.fragment.config.verifyDerivedTarget = false`. Unpoly may then update a different element than the one you passed.

## Deriving a target programmatically {#deriving-a-target-programmatically}

Your JavaScript can use [`up.fragment.toTarget()`](https://unpoly.com/api/up.fragment.toTarget.md) to derive a target from an element:

```js
let element = up.element.createFromHTML('<span class="klass">...</span>')
let selector = up.fragment.toTarget(element) // result: ".klass"
```

Also see the [options for `up.fragment.toTarget()`](https://unpoly.com/api/up.fragment.toTarget.md#parameters).

To test whether a selector can be derived from an element, use [`up.fragment.isTargetable()`](https://unpoly.com/api/up.fragment.isTargetable.md).

<nav aria-label="Reading order">

- [Previous: Targeting fragments](https://unpoly.com/learn/targeting-fragments.md)
- [Next: Handling error responses](https://unpoly.com/learn/error-responses.md)

</nav>

