---
title: Tag Sorting & Placement
description: How tags are positioned in the DOM and how to configure their order and location.
---
## Introduction
By default, tags are rendered in the document `
`{lang="html"} in a [specific order](#sort-order) for optimal performance and compatibility.
However, this is not always useful, say if you need to render a script at the end of the document or have a specific
placement of a tag.
::tip
Proper tag positioning is critical for performance optimization and can significantly impact page load times and user experience.
::
To solve these issues we have three options:
- [Document Placement](#document-placement): To control where the tag is rendered in the document (e.g. `head`{lang="bash"}, `bodyClose`{lang="bash"}, `bodyOpen`{lang="bash"}, etc)
- [Sort Order](#sort-order): To control the order of tags within the document section
- [Hooks](#using-hooks-for-tag-reordering): For advanced use cases, the `tags:afterResolve`{lang="bash"} hook allows programmatic reordering
## Document Placement
For the `
//
```
## Sort Order
All tags are given a weight with the lower the number, the higher the priority.
[Capo.js](https://rviscomi.github.io/capo.js/) weights are automatically applied to tags to avoid [Critical Request Chains](https://web.dev/critical-request-chains/). As
well as default weights to avoid site stability issues:
- **-20**: ``{lang="html"}
- **-10**: ``{lang="html"}
- **0**: ``{lang="html"}
- **10**: ``{lang="html"}
- **20**: ``{lang="html"}
All other tags have a default priority of `100`{lang="bash"}.
Escaping out of these default weights can be accomplished by setting the `tagPriority`{lang="bash"} property.
### Tag Priority
The `tagPriority`{lang="bash"} property can be set to an explicit weight, a string alias or a string to target a specific tag.
#### Sorting with Aliases
Using an alias to set the position of a tag is the best practice as it allows you to retain the existing capo.js weights
that are configured for performance.
- `critical`{lang="bash"}: **-8**
- `high`{lang="bash"}: **-1**
- `low`{lang="bash"}: **2**
```ts
import { useHead } from '@unhead/dynamic-import'
useHead({
script: [
{
src: '/my-lazy-script.js',
tagPriority: 'low',
},
],
})
```
#### Sort by number
When providing a number, refer to the priorities set for critical tags above.
```ts
import { useHead } from '@unhead/dynamic-import'
// some layout we have a js file that is ran
useHead({
script: [
{
src: '/not-important-script.js',
},
],
})
// but in our page we want to run a script before the above
useHead({
script: [
{
src: '/very-important-script.js',
tagPriority: 0,
},
],
})
//
//
```
#### Sort with `before:` and `after:`
If you'd like to place a tag before or after another tag, you can use the optional [Alias Sorting Plugin](/plugins/alias-sorting) which provides a more intuitive way to order your tags relative to each other.
::tip
The Alias Sorting Plugin is particularly useful when you need precise control over tag order but don't want to manage numerical priorities directly.
::
### Hydration Caveats
::warning
When hydrating the state (e.g., SSR or page switch), Unhead replaces existing tags in their current position to avoid a flash of content.
This may cause `tagPriority` to be ignored during hydration. For client-side-only applications or SPAs, this isn't an issue, but for SSR applications, be aware that the initial render positions may be preserved during hydration.
::
## Using Hooks for Tag Reordering
For advanced use cases where you need programmatic control over tag ordering, Unhead provides a powerful hook system.
The `tags:afterResolve`{lang="bash"} hook gives you access to the tags after they've been resolved but before they're rendered to the DOM. This allows for custom ordering logic beyond what's possible with `tagPriority`{lang="bash"}.
```ts
import { injectHead } from '@unhead/dynamic-import'
const head = injectHead()
// Hook into the tags:afterResolve lifecycle
head.hooks.hook('tags:afterResolve', (ctx) => {
// ctx.tags is an array of all tags that will be rendered
// You can reorder, filter, or modify them before they are rendered
// Example: Move all font preloads to the beginning
const fontPreloads = ctx.tags.filter(tag =>
tag.tag === 'link'
&& tag.props.rel === 'preload'
&& tag.props.as === 'font'
)
// Remove the font preloads from their current position
ctx.tags = ctx.tags.filter(tag =>
!(tag.tag === 'link'
&& tag.props.rel === 'preload'
&& tag.props.as === 'font')
)
// Add them to the beginning of the array
ctx.tags = [...fontPreloads, ...ctx.tags]
})
```
::tip
The hooks approach is particularly useful for:
- Complex ordering logic that depends on runtime conditions
- Dynamic reordering based on user preferences or device capabilities
- Implementation of custom sorting algorithms for specific tag types
::