Inline Style & Scripts
Introduction
The <style>
, <script>
and <noscript>
tags are unique in HTML as they can contain inner content that directly affects how your page behaves and appears. Unhead provides powerful utilities to manage this inner content safely and efficiently.
Unlike most other HTML tags which primarily use attributes, these special tags rely on their content to function. With Unhead, you can manipulate this content programmatically while benefiting from the library's deduplication and optimization features.
Inner Content Options
When working with the inner content of a tag, Unhead gives you two options for setting the content that appears between the opening and closing tags:
textContent
: Treats the content as plain text, escaping any HTML charactersinnerHTML
: Interprets the content as HTML, which allows for structured content but requires security considerations
The choice between these properties depends on your specific needs and security requirements:
import { useHead } from '@unhead/svelte'
useHead({
script: [
{
innerHTML: 'window.analytics = window.analytics || []',
},
],
style: [
{
textContent: 'body { background: salmon; color: cyan; }',
},
]
})
This example demonstrates adding:
- An inline script that initializes an analytics array
- An inline style that sets background and text colors
innerHTML
Security Considerations with
Setting inner content using textContent
is the safest approach for untrusted content. However, in some cases you might need to use innerHTML
, particularly when working with rich content or third-party scripts that require HTML structure.
innerHTML
, the content is not automatically sanitized. You must sanitize any user input or third-party content to prevent cross-site scripting (XSS) vulnerabilities that could compromise your application's security.For dealing with external content, consider:
- Using a sanitization library like DOMPurify
- Applying framework-specific sanitization utilities
- Using the useHeadSafe() composable instead
Example of Unsafe Usage
import { useHead } from '@unhead/svelte'
// Don't do this!
const someUserScript = await loadUserProvidedScript()
useHead({
script: [
{
// ❌ Dangerous - could contain malicious code!
innerHTML: someUserScript
},
],
})
Example of Safe Usage
import { useHead } from '@unhead/svelte'
import DOMPurify from 'dompurify'
// Do this instead
const userProvidedContent = await loadUserProvidedContent()
useHead({
script: [
{
// ✅ Safe - content is sanitized
innerHTML: DOMPurify.sanitize(userProvidedContent)
},
],
})
Shorthand String Syntax
For ease of use, Unhead provides a convenient shorthand syntax where you can simply provide a string as the array entry instead of an object with textContent
or innerHTML
.
import { useHead } from '@unhead/svelte'
useHead({
script: [
'window.analytics = window.analytics || []',
],
style: [
'body { background: salmon; color: cyan; }',
]
})
How It Works
Behind the scenes, Unhead automatically determines the appropriate property to use:
- For
<style>
tags: Content is applied astextContent
(safer option) - For
<script>
and<noscript>
tags: The appropriate property is selected based on content
Best Practices
When working with inner content for style and script tags, follow these best practices to ensure security, performance, and maintainability:
Security
textContent
over innerHTML
whenever possible for security reasons.- Sanitize All External Content: Always sanitize any user-generated or third-party content
- Consider useHeadSafe: For untrusted content, prefer the useHeadSafe() composable
- Validate Input: Check content before including it in your head tags
Performance
- Balance Inline vs. External: While inline scripts and styles eliminate network requests, they can increase HTML size
- Use Critical CSS: For critical above-the-fold styles, inline CSS can improve perceived performance
- Defer Non-Critical Scripts: Use the
defer
attribute for non-essential scripts
import { useHead } from '@unhead/svelte'
// Example of critical CSS with non-critical scripts
useHead({
style: [
// Critical CSS inline for faster rendering
'header, nav, .hero { /* Critical styles */ }',
],
script: [
{
src: '/assets/analytics.js',
defer: true, // Load after page rendering
}
]
})
Maintainability
- Keep It Simple: For complex scripts or styles, use external files with
src
orhref
- Use Keys: Add
key
attributes to easily identify and update specific tags - Consider the Alternatives:
- For scripts, use the dedicated useScript() composable
- For complex styling needs, use external stylesheets
Common Use Cases
Critical CSS
import { useHead } from '@unhead/svelte'
useHead({
style: [
{
key: 'critical-css',
textContent: `
/* Only include truly critical styles here */
body { font-family: system-ui, sans-serif; }
.hero { height: 100vh; display: flex; align-items: center; }
`,
}
]
})
Inline JSON Configuration
import { useHead } from '@unhead/svelte'
const siteConfig = {
apiEndpoint: '/api/v1',
features: { darkMode: true, comments: false },
}
useHead({
script: [
{
id: 'site-config',
type: 'application/json',
textContent: JSON.stringify(siteConfig),
}
]
})