Mastering Custom Themes in Nuxt UI

Learn how to create a custom theme in Nuxt UI using Tailwind CSS v4, from fonts and dark mode to color tokens and component-level styling. This guide walks you through building a fully branded design system with token-based theming and minimal configuration.

Michael Thiessen
Nuxt 3

The Mastering Nuxt FullStack Unleashed Course is here!

Get notified when we release new tutorials, lessons, and other expert Nuxt content.

Click here to view course

Custom themes in Nuxt UI are one of its best features. While the default look is really good, every brand and app needs its own vibe and unique look.

Let's explore how to create a custom theme in Nuxt UI using Tailwind v4.

Getting Started with Theming

The main place to start is in our main.css file. This is where Tailwind v4 introduces a dedicated theme block.

/* assets/css/main.css */
@import 'tailwindcss' theme(static);
@import '@nuxt/ui';

@theme {
  --font-sans: Inter, system-ui, sans-serif;

  /* More customizations will go here */
}

By defining different CSS variables in this theme block, you can customize how Tailwind works and in turn, how Nuxt UI renders. This is the foundation of custom theming.

Font Customization

Nuxt UI automatically installs Nuxt Fonts, which will download and optimize fonts for us. All we need to do is specify them in our theme block:

@theme {
  --font-sans: Inter, system-ui, sans-serif;
}

That's it! This simple line sets our custom font, and Nuxt Fonts will handle all the downloading, optimization, and caching for us.

Creating a Dark Mode Theme

Next, we can override Nuxt UI-specific CSS variables to create a custom dark mode theme. We'll start with a few basic variables:

:root {
  --ui-primary: var(--color-green-500);
  --ui-bg: var(--color-gray-950);
}

You'll notice that the UI primary token gets overridden here. This overrides any settings we might have in our app.config file from previous setup.

But we need to update many more tokens to create a complete dark theme. Here's a more comprehensive set:

:root {
  --ui-primary: var(--color-green-500);
  --ui-bg: var(--color-gray-950);
  --ui-bg-muted: var(--color-gray-900);
  --ui-bg-elevated: var(--color-gray-800);
  --ui-bg-accented: var(--color-gray-700);
  --ui-bg-inverted: var(--color-white);

  --ui-text: var(--color-gray-100);
  --ui-text-muted: var(--color-gray-200);
  --ui-text-dimmed: var(--color-gray-400);
  --ui-text-highlighted: var(--color-white);

  --ui-border: var(--color-gray-800);
  --ui-border-muted: var(--color-gray-800);
  --ui-border-accented: var(--color-gray-700);
  --ui-border-inverted: var(--color-white);

  --ui-radius: var(--radius-sm);
  --ui-container: var(--container-6xl);
}

This gives us an always-on dark mode with nice green accents.

Custom Color Scales

We can take it a step further and define our own unique color scale in Tailwind. Here's a custom green color gradient:

@theme {
  --color-green-50: #effdf5;
  --color-green-100: #d9fbe8;
  --color-green-200: #b3f5d1;
  --color-green-300: #75edae;
  --color-green-400: #00dc82;
  --color-green-500: #00c16a; /* primary */
  --color-green-600: #00a155;
  --color-green-700: #007f45;
  --color-green-800: #016538;
  --color-green-900: #0a5331;
  --color-green-950: #052e16;
}

These green colors adjust the saturation down just a little bit to give us a more branded app look. Tailwind will instantly expose utilities like bg-green-500 and text-green-900 for you to use.

And that's it! We've customized a nice theme for ourselves.

Component-Specific Customization

We can also customize how specific components work if we want to. We do this in our app.config.ts file under the UI block:

// app.config.ts
export default defineAppConfig({
  ui: {
    button: {
      default: {
        size: 'lg',
        color: 'green',
        variant: 'solid'
      },
      base: 'font-bold',
    }
  }
})

If we save that and refresh our app, we'll see that now all of our buttons have bold text in them.

We can also target specific slots within components:

export default defineAppConfig({
  ui: {
    button: {
      base: 'font-bold',
      leadingIcon: {
        base: 'text-xl'
      }
    }
  }
})

To figure out how to customize different components and what slots and options are available, check out the Nuxt UI component explorer where everything is laid out in great detail.

Benefits of Token-Based Theming

Because Nuxt UI components rely on these tokens and because we've been using these tokens in our own custom CSS throughout the app, it all just works.

This token-based approach gives us several advantages:

  1. A single source of truth - custom CSS and Nuxt UI components read identical variables
  2. Instant multi-theme support - swap a data attribute or load a new stylesheet
  3. Dev-tool superpowers - Chrome DevTools shows live color pickers for rapid iteration
  4. Better performance - Tailwind v4's new engine resolves variables at build time

Resources

For more details on customizing your Nuxt UI theme, check out these resources:

Custom theming in Nuxt UI is powerful yet simple. With just one CSS file and token-based styling, you can transform the look of your entire application to match your brand perfectly.

Michael Thiessen
Michael is a passionate full time Vue.js and Nuxt.js educator. His weekly newsletter is sent to over 11,000 Vue developers, and he has written over a hundred articles for his blog and VueSchool.

Follow MasteringNuxt on