---
title: Partials
description: Learn how to refresh named regions of a theme page without a full page reload.
source_url:
  html: https://shopify.dev/docs/storefronts/themes/architecture/partials
  md: https://shopify.dev/docs/storefronts/themes/architecture/partials.md
---

# Partials

***

## Overview

Partials are named regions of server-rendered HTML that JavaScript can refresh independently, without a full page reload. Mark a region with the [`partial` tag](https://shopify.dev/docs/api/liquid/tags/partial), then use `@shopify/partial-rendering` to request and apply its updated HTML.

Partials use the web platform's [Declarative Partial Updates proposal](https://github.com/WICG/declarative-partial-updates) as a reference. For an introduction to the request-and-replace model, see [Declarative partial updates: a new way to build faster web pages](https://developer.chrome.com/blog/declarative-partial-updates).

***

## Mark a partial

Wrap only the region that changes, not the whole page. For example, a collection page can name its product grid so sorting or filtering only refreshes that grid:

## templates/collection.liquid

```liquid
{% partial 'product-grid' %}
  {% for product in collection.products %}
    {% render 'product-card', product: product %}
  {% endfor %}
{% endpartial %}
```

The name links the region to the response that replaces it. A JavaScript request for `product-grid` needs a matching `{% partial 'product-grid' %}` in the rendered page.

***

## Update partials

The `@shopify/partial-rendering` package provides helpers to fetch, apply, and refresh named partials.

### `fetch()` and `apply()`

Use `fetch()` to request fresh HTML for one or more partials. Pass the result to `apply()` to replace the matching regions on the page. This gives you control over the request URL, method, body, and when the update appears.

This example updates the product grid with a new sort order. It starts with the current URL so the request preserves the current locale and query parameters:

```js
import {partials} from '@shopify/partial-rendering';


const url = new URL(window.location.href);
url.searchParams.set('sort_by', 'price-ascending');


const update = await partials.fetch('product-grid', {
  url: url.toString(),
});


partials.apply(update);
```

Build request URLs from the current page URL or the [`routes`](https://shopify.dev/docs/api/liquid/objects/routes) object instead of hardcoding storefront paths. That keeps requests working across locales and markets.

One interaction can change several regions. For example, filtering a collection can update the product grid, result count, and active filters. Fetch them together so one response keeps them in sync:

```js
const update = await partials.fetch(
  'product-grid',
  'product-count',
  'active-filters',
  {url: url.toString()},
);


partials.apply(update);
```

By default, `apply()` swaps content immediately. To animate the swap, call it inside a [View Transition](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API), with a fallback for browsers that don't support transitions:

```js
if (document.startViewTransition) {
  document.startViewTransition(() => partials.apply(update));
} else {
  partials.apply(update);
}
```

### `refresh()`

Use `refresh()` when the request targets the current page URL. It fetches and applies the named partials in one call, so it works well when the browser's back or forward button changes the URL:

```js
await partials.refresh('product-grid', 'product-count');
```

Call `refresh()` with no arguments to update every partial on the page. Pass an element to refresh only the partials inside it:

```js
await partials.refresh();
await partials.refresh(document.querySelector('[data-product-list]'));
```

### `get()` and `getAll()`

Use `get()` or `getAll()` to reference partials already on the page without fetching or replacing them. `get()` returns the first matching partial, and `getAll()` returns every partial in a scope. Each result pairs the partial name with a [`Range`](https://developer.mozilla.org/en-US/docs/Web/API/Range) spanning its content.

```js
const grid = partials.get('product-grid');
const bounds = grid?.range.getBoundingClientRect();


const regions = partials.getAll(document.querySelector('main'));
```

***

## Accessibility and state

A partial update replaces content in place, so the browser doesn't perform the housekeeping of a full page load. `apply()` preserves focus, text selection, form values, and scroll position across the swap.

For the rest, account for the needs of each interaction:

* **Stale responses:** A slow earlier request can resolve after a newer one and overwrite it. Pass an `AbortSignal` to `fetch()` and cancel in-flight requests when a new interaction starts.
* **Loading feedback:** Set `aria-busy` on a region while it updates.
* **Announcements:** Use a live region for meaningful success and error messages that result from a silent DOM swap.
* **Transient UI:** Restore DOM-only state, such as an open disclosure, after the region is replaced.
* **Server-owned values:** `apply()` preserves input, textarea, and select values across a swap. If the server changes a form control, such as a cart quantity after validation or an inventory adjustment, update that control after applying the partial instead of expecting the returned markup to replace its value. For URL state, read `window.location.search` so shared links and browser navigation produce the same result.

***