Document head
The title and tags of the page, set from a component.
useHead() sets document.title, <meta>
and <link> tags for as long as the current owner lives.
Call it in setup(). When the component unmounts, the page goes
back to what it was.
class Inbox extends Component {
setup() {
useHead({
title: 'Inbox',
meta: [{ name: 'description', content: 'Your messages' }],
link: [{ rel: 'canonical', href: '/inbox' }],
});
}
}
Each tag is a plain object of attributes. A value of undefined
or null leaves that attribute out.
Following signals
Pass a function and it re-runs when a signal it read changes. Only what changed is written to the page.
The button builds the child through a function,
children: () => html`...`, so the head entry belongs to that
branch and goes when it is removed. A child written directly between the
Show tags is built when the parent renders, and its
useHead() would stay.
Layouts and pages
Calls stack. The latest entry wins for the title and for each tag, and when it is removed the one before it comes back. A layout sets defaults, a page overrides them, and leaving the page restores the layout's values.
class Layout extends Component {
setup() {
useHead({ titleTemplate: '%s - Signy',
meta: [{ name: 'description', content: 'A UI framework' }] });
}
}
class Pricing extends Component {
setup() {
useHead({ title: 'Pricing', meta: [{ name: 'description', content: 'Plans' }] });
}
}
// On the pricing page: "Pricing - Signy", description "Plans".
// After leaving it: the title from your HTML file, description "A UI framework".
Title template
titleTemplate wraps the winning title. It is a string with
%s, or a function. It can come from a different entry than the
title, so a layout can set it once. A template alone does nothing: there
has to be a title.
useHead({ titleTemplate: (title) => `${title} | Signy` });
Which tag replaces which
Two entries that describe the same tag share it. Anything without a key is added once per call.
| Tag | Matched by |
|---|---|
meta | The first of name, property, http-equiv, itemprop or charset that it has, and its value. |
link with rel="canonical" or rel="manifest" | rel alone, so there is only one. |
Other link | rel, href and hreflang. |
| Anything else | Not matched. Each call adds its own tag. |
A tag that is already in the page, such as the description in your HTML
file, is taken over while an entry covers it and restored afterward. Tags
that useHead() adds carry data-signy-head and are
removed when the entry goes.
With the router
A route component runs setup() when the route is entered and
unmounts when it is left, so the stacking above gives every route its own
title with no extra code. A title from the route's data works the same way.
class UserPage extends Component {
setup() {
const params = useParams(this);
useHead(() => ({ title: `User ${params.value.id}` }));
}
}
Safety
Attributes go through the same check as bindings. A javascript:
URL in href, or an on* attribute, is not written,
and a development build logs a warning.
Limits
- It runs in the browser. A crawler or a link preview that does not run scripts sees the tags in your HTML file, not the ones set here.
- Outside an owner, such as top level code, nothing removes the entries. Call it in
setup()or insidecreateRoot(). <html>and<body>attributes, such aslang, are not managed.