unhead@betaQuick Answer: Use tagPosition: 'head' | 'bodyOpen' | 'bodyClose' to control where tags render. Use tagPriority: 'critical' | 'high' | number | 'low' to control ordering within those positions.
By default, tags are rendered in the document <head> in a specific 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.
To solve these issues we have three options:
head, bodyClose, bodyOpen, etc)tags:afterResolve hook allows programmatic reorderingFor the <script>, <noscript> and <style> tags you may provide an optional tagPosition property with the possible values:
head - Render in the <head> (default)bodyOpen - Render at the start of the <body>bodyClose - Render at the end of the <body>bodyClose for scripts that aren't critical for page rendering can significantly improve page load performance, as these scripts won't block the initial render.bodyClose to avoid impacting page performancehead with high prioritybodyOpen when they need to be loaded early but not block renderingimport { useHead } from '@unhead/vue'
// useHead: /docs/head/api/composables/use-head
useHead({
script: [
{
src: '/my-lazy-script.js',
tagPosition: 'bodyClose',
},
],
})
// renders
// ...
// <script src="/my-lazy-script.js"></script>
// </body>
All tags are given a weight with the lower the number, the higher the priority.
Capo.js weights are automatically applied to tags to avoid Critical Request Chains. As well as default weights to avoid site stability issues:
<meta charset ...><base><meta http-equiv="content-security-policy" ...><title><link rel="preconnect" ...>All other tags have a default priority of 100.
Escaping out of these default weights can be accomplished by setting the tagPriority property.
The tagPriority property can be set to an explicit weight, a string alias or a string to target a specific tag.
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: -8high: -1low: 2import { useHead } from '@unhead/vue'
useHead({
script: [
{
src: '/my-lazy-script.js',
tagPriority: 'low',
},
],
})
When providing a number, refer to the priorities set for critical tags above.
import { useHead } from '@unhead/vue'
// 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,
},
],
})
// <script src=\"/very-important-script.js\"></script>
// <script src=\"/not-important-script.js\"></script>
before: and after:If you'd like to place a tag before or after another tag, you can use the optional Alias Sorting Plugin which provides a more intuitive way to order your tags relative to each other.
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.
For advanced use cases where you need programmatic control over tag ordering, Unhead provides a powerful hook system.
The tags:afterResolve 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.
import { injectHead } from '@unhead/vue'
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]
})
tagPosition to control where tags render (head, bodyOpen, bodyClose)tagPriority for ordering: 'critical', 'high', number, 'low'Titles & Title Templates
Learn how to master page titles using useHead, title templates, and SEO best practices. Includes reactive titles, social sharing, and template params.
Class & Style Attributes
Learn how to dynamically style your HTML and body tags with Unhead's powerful class and style attribute API