---
title: "Inline Style & Scripts"
description: "Add inline scripts, styles, JSON data, and noscript content with textContent and innerHTML."
canonical_url: "https://unhead.unjs.io/docs/head/guides/core-concepts/inner-content"
last_updated: "2026-08-06T14:23:42.781Z"
---

Use `textContent` or `innerHTML` to set inline content on `script`, `style`, and `noscript` entries. Neither property makes untrusted JavaScript, CSS, or HTML safe.

## Inline content

```ts
import { useHead } from '@unhead/dynamic-import'

useHead({
  script: [
    { textContent: 'window.analytics = window.analytics || []' }
  ],
  style: [
    { textContent: 'body { background: salmon; color: cyan; }' }
  ]
})
```

On the client, `textContent` is assigned through the DOM property while `innerHTML` is assigned through the corresponding HTML property. During SSR, both values are serialized as raw-element content. Unhead escapes closing `script`, `style`, and `noscript` sequences so the content cannot terminate its element early, but it does not sanitize the JavaScript, CSS, or HTML itself.

<warning>

Treat both `textContent` and `innerHTML` as trusted-code APIs for scripts and styles. Safety depends on the parsing context: `textContent` is a safe sink for ordinary page text, but text inside `<script>` or `<style>` is still executable code. OWASP classifies direct script and style content as [dangerous contexts](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#dangerous-contexts), and MDN documents `innerHTML` as an [HTML injection sink](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML#security_considerations). HTML sanitizers do not make arbitrary JavaScript or CSS safe to execute.

</warning>

For a `title`, Unhead HTML-escapes the text during SSR. For JSON-like script types, it serializes object values and escapes `<` as `\u003C`.

## String shorthand

A string entry is shorthand for `innerHTML` on `script`, `style`, and `noscript` tags:

```ts
import { useHead } from '@unhead/dynamic-import'

useHead({
  script: ['window.analytics = window.analytics || []'],
  style: ['body { background: salmon; color: cyan; }']
})
```

Use the object form when you need attributes, a custom deduplication key, or an explicit content property.

## JSON data

JSON-like script types accept an object in `textContent` or `innerHTML`. Unhead sets `type="application/json"` when an object is provided without a type.

```ts
import { useHead } from '@unhead/dynamic-import'

useHead({
  script: [
    {
      id: 'site-config',
      type: 'application/json',
      textContent: {
        apiEndpoint: '/api/v1',
        features: { darkMode: true, comments: false }
      }
    }
  ]
})
```

JSON-LD, import maps, and speculation rules receive the same JSON escaping during tag resolution.

## JSON accepted by useHeadSafe

[`useHeadSafe()`](/docs/head/api/composables/use-head-safe) accepts JSON script content only when the script type ends in `json`. It parses and serializes the JSON again, removes prototype-pollution keys, and rejects invalid JSON. It removes executable scripts, inline style content, noscript content, and every `innerHTML` value.

## External files

Use an external script or stylesheet when the content is large, cacheable, or maintained separately:

```ts
import { useHead } from '@unhead/dynamic-import'

useHead({
  link: [{ rel: 'stylesheet', href: '/assets/app.css' }],
  script: [{ src: '/assets/analytics.js', defer: true }]
})
```

For loading triggers, API readiness, and callbacks, use [`useScript()`](/docs/head/api/composables/use-script).

## See Also

- [Loading Scripts](/docs/head/guides/core-concepts/loading-scripts): Script management
- [useHeadSafe() API](/docs/head/api/composables/use-head-safe): Restricted input handling
- [useScript() API](/docs/head/api/composables/use-script): Managed script loading
