---
title: "Styling"
description: "How to style your OG Images."
canonical_url: "https://nuxtseo.com/docs/og-image/guides/styling"
last_updated: "2026-09-07T10:25:34.310Z"
---

Nuxt OG Image supports modern CSS via Tailwind v4, [UnoCSS](https://unocss.dev), and standard CSS. Your level of CSS support depends on the chosen renderer.

## Layout Support

| Feature               | [Takumi](/docs/og-image/renderers/takumi) | [Satori](/docs/og-image/renderers/satori) | [Browser](/docs/og-image/renderers/browser) |
| --------------------- | ----------------------------------------- | ----------------------------------------- | ------------------------------------------- |
| **Flexbox**           | ✅                                         | ✅                                         | ✅                                           |
| **CSS Grid**          | ✅                                         | ❌                                         | ✅                                           |
| **Block/Inline**      | ✅                                         | ❌                                         | ✅                                           |
| **Position Absolute** | ✅                                         | ✅                                         | ✅                                           |

**Satori constraints:** the [Satori](/docs/og-image/renderers/satori) renderer treats everything as a flexbox with `flex-direction: column` by default. It lacks support for `display: grid`, `display: block`, and `display: inline`.

**Takumi & Browser:** the recommended [Takumi](/docs/og-image/renderers/takumi) and [Browser](/docs/og-image/renderers/browser) renderers offer much broader CSS support, including CSS Grid and standard block/inline layouts.

## Build-time Transformations

Nuxt OG Image performs "automagic" CSS transformations during the build process to ensure cross-renderer compatibility.

### CSS Downleveling & Polyfills

The module uses [Lightning CSS](https://lightningcss.dev/) to process styles for simpler renderers like Satori:

- **Color Downleveling:** Automatically converts modern colors (`oklch()`{lang="ts"}, `lab()`{lang="ts"}, `p3`) to standard hex or `rgba()`{lang="ts"}.
- **Logical Properties:** Expands properties like `padding-inline` and `margin-block` to physical counterparts.
- **Individual Transforms:** Merges `translate`, `rotate`, and `scale` into a single `transform` shorthand.
- **Color Mix:** Evaluates and replaces `color-mix()`{lang="ts"} functions with static color values.
- **Calc Evaluation:** Resolves simple `calc()`{lang="ts"} expressions at build time.

### Unsupported Classes

The build process filters out utility classes that static renderers don't support, such as animations, transitions, and z-index, to prevent rendering errors.

## Tailwind CSS & UnoCSS

Use Tailwind/UnoCSS classes directly in your templates without extra configuration.

```html
<div class="bg-blue-500 text-white p-12 flex flex-col items-center justify-center">
  <h1 class="text-6xl font-bold shadow-xl">Hello World</h1>
</div>
```

The module extracts classes from your OG components at build time and compiles them using your project's CSS engine.

### Theme Customizations

The module automatically resolves custom theme values, including Tailwind v4 variables defined in your `@theme` block:

```css [assets/css/main.css]
@import "tailwindcss";

@theme {
  --color-brand: #ff6600;
}
```

```html
<template>
  <div class="bg-brand text-white">
    Custom Theme Classes!
  </div>
</template>
```

### Auto-detection

The module automatically detects your CSS framework:

- **Tailwind v4:** Active if you install `tailwindcss` and use `@import "tailwindcss"` in your CSS.
- **UnoCSS:** Active if you enable `@unocss/nuxt`.
- **Nuxt UI v3:** Automatically imports colors and theme variables.

## Theme Switching (`data-theme`)

By default, OG images render with dark-mode semantic tokens (e.g. Nuxt UI's `bg-inverted`, `text-default`). To opt into theme-aware token resolution, set `data-theme` on the **root element** of your component. Tailwind v4 only.

### Static `data-theme`

Hard-code a theme on the root element:

```vue [components/OgImage/MyImage.satori.vue]
<template>
  <div data-theme="light" class="w-full h-full bg-default text-default p-10">
    <div class="bg-inverted text-inverted p-6 rounded-lg">
      Light mode tokens
    </div>
  </div>
</template>
```

Semantic tokens like `bg-inverted`, `text-muted`, `border-accented` resolve against the chosen theme: `data-theme="light"` produces light-mode values, `data-theme="dark"` produces dark-mode values.

### Dynamic `data-theme` (per-image color mode)

Bind `:data-theme` to a prop to swap themes per OG image:

```vue [components/OgImage/MyImage.satori.vue]
<script lang="ts" setup>
defineProps<{ colorMode?: 'light' | 'dark' }>()
</script>

<template>
  <div :data-theme="colorMode" class="w-full h-full bg-default text-default p-10">
    <div class="bg-inverted text-inverted p-6 rounded-lg">
      hello {{ colorMode }}
    </div>
  </div>
</template>
```

```vue [pages/light.vue]
<script setup lang="ts">
defineOgImage('MyImage', { colorMode: 'light' })
</script>
```

```vue [pages/dark.vue]
<script setup lang="ts">
defineOgImage('MyImage', { colorMode: 'dark' })
</script>
```

When the build detects a `:data-theme` binding on the root element, it resolves classes for both themes at build time and emits paired `bg-[#...] dark:bg-[#...]` arbitrary classes. The renderer then picks the correct value based on the `colorMode` prop you pass to `defineOgImage`.

::note
The dynamic binding only works on the **root element** of the OG component. Nested elements inherit the resolved theme from the build pass.
::

::tip
Templates that don't set `data-theme` keep the existing dark-mode default; this feature is opt-in and non-breaking.
::

## Inline Styles

Use the `:style` binding for dynamic values that change based on props.

```html
<template>
  <div :style="{ backgroundColor: themeColor }" class="w-full h-full flex items-center justify-center">
    <h1 style="color: white; font-size: 80px;">
      {{ title }}
    </h1>
  </div>
</template>
```

## `<style>`{lang="html"} tag support

You can use scoped or global `<style>`{lang="html"} tags within your components. The module processes and applies these directly to the rendered image.

::note
Standard CSS selectors work across all renderers, though Satori has limited support for advanced selectors like `:nth-child` or complex combinators.
::