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

# Following links

Any link can update a fragment of the current page, instead of loading a full new document. When Unpoly handles a link's click this way, we say the link is _followed_.

<nav aria-label="Contents">

#### Contents

- [Following a link](#following-a-link)
- [Updating a specific fragment](#targeting)
- [Navigation defaults](#navigation-defaults)
- [Acting on press](#instant)
- [Links that are never followed](#unfollowable)
- [Following links from JavaScript](#scripting)

</nav>

## Following a link {#following-a-link}

To have Unpoly handle a link, set an [`[up-follow]`](https://unpoly.com/api/up-follow.md) attribute:

```html
<a href="/posts/5" up-follow>Read post</a>
```

When the user clicks, Unpoly requests `/posts/5`. The server responds with a full HTML page, the same way it would for any browser request. Unpoly extracts the response's [main fragment](https://unpoly.com/api/main.md) and replaces the main fragment on the current page. Elements outside the updated fragment keep their state, like unsaved input in other forms.

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

> #### Tip
>
> Instead of annotating individual links, you can also configure Unpoly to [follow all links on the page](https://unpoly.com/learn/handling-all-links.md).

## Updating a specific fragment {#targeting}

To update an element other than the main fragment, set an [`[up-target]`](https://unpoly.com/api/up-follow.md#up-target) attribute with a CSS selector:

```html
<a href="/posts/5" up-target=".content">Read post</a>

<div class="content">
  Old content
</div>
```

Unpoly finds the `.content` element in the server response and swaps it into the current page.

An `[up-target]` attribute already implies [`[up-follow]`](https://unpoly.com/api/up-follow.md), so you don't need to set both. The same goes for other rendering attributes like `[up-layer]` or [`[up-transition]`](https://unpoly.com/api/up-transition.md).

A target can also address multiple fragments, append to an existing element, or resolve relative to the clicked link. See [Targeting fragments](https://unpoly.com/learn/targeting-fragments.md) for everything a target selector can express.

## Navigation defaults {#navigation-defaults}

Following a link is considered [navigation](https://unpoly.com/learn/navigation-defaults.md) by default. When a link updates the layer's main fragment, Unpoly behaves like a full page load would: the browser URL and history are updated, and the page scrolls to the top. Focus moves to the new fragment.

See [Navigation defaults](https://unpoly.com/learn/navigation-defaults.md) for all navigation defaults and how to customize them.

## Acting on press {#instant}

A standard link activates on `click`, when the mouse button is released. Set an [`[up-instant]`](https://unpoly.com/api/up-instant.md) attribute to act on `mousedown` instead:

```html
<a href="/users" up-follow up-instant>User list</a>
```

This saves the time the user takes to release the mouse button. Because the request is sent that much earlier, the interaction feels faster.

Users can still activate an instant link with the keyboard. They can no longer cancel a click by dragging the pressed mouse away from the link, so reserve [`[up-instant]`](https://unpoly.com/api/up-instant.md) for navigation, where a stray click has no severe effect. See [`[up-instant]`](https://unpoly.com/api/up-instant.md) for details.

## Links that are never followed {#unfollowable}

Some links are always handled by the browser, even when they match an [`[up-follow]`](https://unpoly.com/api/up-follow.md) selector:

- Links with an `[up-follow=false]` attribute. Also see [boolean attributes](https://unpoly.com/learn/attributes-and-options.md#boolean-attributes).
- Links with a [`[download]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-download) attribute.
- Links with a [`[target]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-target) attribute (to target an iframe or open new browser tab).
- Links with a `javascript:`, `mailto:` or `tel:` scheme.
- Links with a cross-origin `[href]`.
- Links with an `[href]` that only contains a `#hash` (like `#` or `#section`) and don't also have local HTML in an `[up-document]`, `[up-fragment]`, or `[up-content]` attribute.
- Any additional exceptions configured in [`up.link.config.noFollowSelectors`](https://unpoly.com/api/up.link.config.md#config.noFollowSelectors).

Clicking such a link falls back to default browser behavior.

## Following links from JavaScript {#scripting}

To follow a link element programmatically, pass it to [`up.follow()`](https://unpoly.com/api/up.follow.md):

```js
let link = document.querySelector('a.featured')
up.follow(link)
```

The link's `[up-...]` attributes are honored, as if the user had clicked the link. You can pass additional [render options](https://unpoly.com/api/up.render.md#parameters) to supplement or override the link's attributes:

```js
up.follow(link, { target: '.sidebar' })
```

To update fragments without a link element, use [`up.render()`](https://unpoly.com/api/up.render.md).

<nav aria-label="Reading order">

- [Previous: Links](https://unpoly.com/learn/links.md)
- [Next: Handling all links](https://unpoly.com/learn/handling-all-links.md)

</nav>

