Skip to content

Feature -> Develop | Primevue Theming Guide #281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 206 additions & 0 deletions content/4.guide/7.primevue-theming-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
---
toc: true
title: PrimeVue Theming Guide
---

## Introduction

This guide outlines a structured approach to applying theming in Vue and Nuxt apps using **CSS custom properties** alongside **Tailwind CSS** and **PrimeVue**. It helps ensure your application is both performant and maintainable with scalable light and dark modes.

📌 **Quick Installation Links**

- **[Install PrimeVue](https://primevue.org/nuxt){:target="_blank"}**

- **[Install Tailwind CSS](https://tailwindcss.nuxtjs.org/getting-started/installation){:target="_blank"}**

## 1. Tailwind Setup

Ensure your project includes Tailwind’s base setup:

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

## 2. Adding Dark Mode Support

PrimeVue uses the `system` as the default `darkModeSelector` in theme configuration. If you have a dark mode switch in your application, set the `darkModeSelector` to the selector you utilize such as `.my-app-dark` in your nuxt config so that PrimeVue can fit in seamlessly with your color scheme.

```js
import PrimeVue from 'primevue/config';
import Aura from '@primeuix/themes/aura';

const nuxtConfig: NuxtConfig = {};

nuxtConfig.primevue = {
options: {
theme: {
preset: Aura,
options: {
darkModeSelector: '.my-app-dark',
}
}
}
}
```

In case you prefer to use dark mode all the time, apply the `darkModeSelector` initially and never change it.

```html
<html class="my-app-dark">
```

It is also possible to disable dark mode completely using `false` or `none` as the value of the selector.

```js
theme: {
preset: Aura,
options: {
darkModeSelector: false || 'none',
}
}
```

## 3. Defining Light and Dark Themes

Use CSS custom properties (`--var-name`) inside `:root` for light theme and a custom class (e.g., `.my-app-dark`) for dark theme overrides. Add the theming vairables in your css file where tailwind is already setup.


### Light Theme

```css
:root {
--pointer-x: 0;
--pointer-y: 0;

/* Core Colors */
--brand-primary: #501D71;
--text-default: #000000;

/* Text Gradients */
--text-gradient-start: #12DBFF;
--text-gradient-end: #BA55FE;

/* Backgrounds */
--surface-background: #EAEAEA;
--element-background: #EAEAEA;
--overlay-weak: #ffffff22;
--brand-accent-dark: #360055;
--card-background: #FAF5FF;
--background-glow: #F6E9FF;

/* Gradients */
--bg-circle-large: linear-gradient(160deg, rgba(255, 255, 255, 0) 30.43%, #ffffff88 54.53%, #ffffff 92.37%);
--bg-circle-subtle: linear-gradient(291deg, #ffffff33 30.43%, #ffffff77 92.37%);
--bg-circle-top-light: linear-gradient(157.91deg, rgba(255, 255, 255, 0) 9.32%, #ffffff55 86.78%);
--bg-circle-highlight: linear-gradient(92.4deg, rgba(255, 255, 255, 0.5) 6.22%, rgba(245, 245, 245, 0.5) 93.78%);
--bg-circle-spotlight: radial-gradient(62.25% 62.25% at 53.43% 51.39%, rgba(255, 255, 255, 0) 0%, #ffffff 100%);
--bg-cms-card: linear-gradient(180deg,#B6A9FF 0%,#8564B3 100%);
--border-cms-card: linear-gradient(180deg,#D3CBF7 0%,#7758AE 100%);
}
```

### Dark Theme

```css
:root.my-app-dark {
--pointer-x: 0;
--pointer-y: 0;

/* Core Colors */
--brand-primary: #AF66E4;
--text-default: #ffffff;

/* Backgrounds */
--surface-background: #190226;
--element-background: #1F0035;
--overlay-weak: #26004988;
--brand-accent-dark: #360055;
--card-background: #08000E;
--background-glow: #22206D;

/* Gradients */
--bg-circle-large: linear-gradient(136.28deg, rgba(51, 4, 79, 0) 30.43%, #26004988 54.53%, #360055 92.37%);
--bg-circle-subtle: radial-gradient(62.25% 62.25% at 53.43% 51.39%, rgba(42, 1, 73, 0) 0%, #0B001344 100%);
--bg-circle-top-light: linear-gradient(0.91deg, rgba(51, 4, 79, 0) 9.32%, #36006F 86.78%);
--bg-circle-highlight: linear-gradient(93.26deg, rgba(18, 2, 44, 0.7) 55.39%, rgba(57, 14, 95, 0.7) 96.74%);
--bg-circle-spotlight: radial-gradient(62.25% 62.25% at 53.43% 51.39%, rgba(42, 1, 73, 0) 0%, #0B0013 100%);
--bg-cms-card: linear-gradient(180deg,#1C173A 0%,#0D0C28 100%);
--border-cms-card: linear-gradient(180deg,#433B6A 0%,#211D52 100%);
}
```

---

## 3. Using CSS Variables with Tailwind CSS

While Tailwind doesn’t directly support variables in all utilities, **arbitrary values** allow us to use CSS variables in most cases:

### Practical Examples

```html
<!-- Background from CSS variable -->
<div class="bg-[var(--color-5)]"></div>

<!-- Gradient Background from CSS variable -->
<div class="bg-[image:var(--bg-circle-subtle)]"></div>

<!-- Text color -->
<p class="text-[var(--primary)]"></p>

<!-- Border color -->
<div class="border border-[var(--color-3)]"></div>

<!-- Box Shadow (if defined in a class or via @layer) -->
<div class="shadow-[var(--custom-shadow)]"></div>
```

> ⚠️ Gradients and background images must be applied using `bg-[image:var(--bg-circle-subtle)]` to render properly.

## 4. Switching Between Light and Dark Themes

Following is a very basic example implementation of a dark mode switch, you may extend it further by involving `prefers-color-scheme` to retrieve it from the system initially and use `localStorage` to make it stateful. See this [article](https://dev.to/abbeyperini/dark-mode-toggle-and-prefers-color-scheme-4f3m){:target="_blank"} for more information.

Use class toggling on the `html` or `body` tag to switch between light and dark themes.

```js
function toggleDarkMode() {
document.documentElement.classList.toggle('my-app-dark');
}
```

```html
<Button label="Toggle Dark Mode" @click="toggleDarkMode()" />
```

## 5. Naming Best Practices

To keep your styles scalable:

* ✅ Prefer semantic names like `--surface-background`, `--brand-accent`, `--overlay-weak`, etc.
* ❌ Avoid non-descriptive names like `--color-1`, `--gradient-1`, etc.

| Old Name | Suggested Semantic Name |
| -------------- | ----------------------- |
| `--color-1` | `--surface-background` |
| `--color-2` | `--element-background` |
| `--color-3` | `--overlay-weak` |
| `--color-4` | `--brand-accent-dark` |
| `--color-5` | `--card-background` |
| `--gradient-1` | `--bg-circle-large` |
| `--gradient-2` | `--bg-circle-subtle` |
| `--gradient-3` | `--bg-circle-top-light` |
| `--gradient-4` | `--bg-circle-highlight` |
| `--gradient-5` | `--bg-circle-spotlight` |

---

## Final Notes

* Use variables for colors, backgrounds, gradients, and even shadows.
* Combine Tailwind's arbitrary values with semantic CSS variables.
* Maintain consistent naming across light/dark modes.
* Document each variable clearly to help future developers.

A scalable theming approach will improve maintainability, accessibility, and performance across your Vue or Nuxt projects.