Index of every page on this site: llms.txt
TypeScript
Core Concepts

Class & Style Attributes

Use htmlAttrs and bodyAttrs to set attributes on <html> and <body>. Class and style values can be strings, arrays, or objects.

The class and style attributes accept strings, arrays, and objects for static or reactive values.

Static classes and styles

If your classes or styles aren't going to change, you can provide them as a string.

import { useHead } from 'unhead'

// useHead: /docs/head/api/composables/use-head
useHead(unheadInstance, {
  htmlAttrs: {
    class: 'my-class my-other-class',
    style: 'background-color: red; color: white;'
  }
})

Array values

Use arrays to supply classes or declarations without joining them into a string:

import { useHead } from 'unhead'

useHead(unheadInstance, {
  htmlAttrs: {
    class: [
      'my-class',
      'my-other-class'
    ],
    style: [
      'background-color: red',
      'color: white'
    ],
  }
})

Dynamic classes and styles

Use an object or array when class values need to update reactively or merge with another entry.

Conditional classes

With the object form, each key is a class name and its value controls whether Unhead includes that class.

import { useHead } from 'unhead'

const colorMode = useColorMode()

useHead(unheadInstance, {
  htmlAttrs: {
    class: {
      // rendered when colorMode is dark
      dark: () => colorMode.value === 'dark',
      // rendered when colorMode is not dark
      light: () => colorMode.value !== 'dark'
    }
  }
})

Reactive styles

Style objects can contain reactive values too:

import { useHead } from 'unhead'

const colorMode = useColorMode()

useHead(unheadInstance, {
  bodyAttrs: {
    style: {
      // conditional style that only applies when darkMode is true
      'background-color': () => colorMode.value === 'dark' ? 'rgba(0, 0, 0, 0.9)' : false,
      // reactive style that always applies with current value
      'font-size': () => fontSize.value,
    }
  }
})

Merging classes across entries

When several entries set classes on the same element, Unhead merges them into a single tag and combines all class names. Conflicting utility classes, such as two Tailwind background colors from app.vue and a page, are kept side by side because Unhead does not know they conflict.

// app.vue
useHead(unheadInstance, { bodyAttrs: { class: 'bg-red-500' } })

// pages/index.vue
useHead(unheadInstance, { bodyAttrs: { class: 'bg-green-500' } })
// <body class="bg-red-500 bg-green-500">

Use the tags:afterResolve hook with a class merge tool such as tailwind-merge to resolve conflicts yourself.

import { twMerge } from 'tailwind-merge'
import { injectHead } from 'unhead/vue'

const head = injectHead()

head.hooks.hook('tags:afterResolve', ({ tags }) => {
  for (const tag of tags) {
    if (tag.tag !== 'bodyAttrs' || !tag.props.class)
      continue
    // resolved classes are an iterable of class names
    const merged = twMerge([...tag.props.class].join(' ')).trim()
    tag.props.class = merged ? merged.split(/\s+/) : []
  }
})
// <body class="bg-green-500">

See Also

Did this page help you?