99

Is it possible to use CSS variables with Tailwind CSS? For instance, let's say I have these variables:

--primary-color: #fff;
--secondary-color: #000;

And I would like to use them in Tailwind like so:

<div class="bg-primary-color">
  <h1>Hello World</h1>
</div>

How can I achieve that?

1
  • From TailwindCSS v4 can use CSS-first configuration what is very much in line with native CSS variable management and var(). Commented Mar 31 at 19:24

13 Answers 13

103

Armando's answer didn't work for me but with this change it did work.

global.css:

no need to target a class or id. you can target the root itself using the Pseudo-Selector https://www.w3schools.com/cssref/sel_root.asp

@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
  --primary-color: #fff;
  --secondary-color: #000;
}

as for tailwind.config.js:

module.exports = {
  theme: {
    extend: {
      colors: {
        "primary-color": "var(--primary-color)",
        "secondary-color": "var(--secondary-color)"
      },
    },
  },
};
Sign up to request clarification or add additional context in comments.

2 Comments

It took me a minute to realize that var in also inside the string.
This won't work if you try to change the color opacity. Example: bg-primary/50
100

Now Tailwind supports CSS custom properties as arbitrary values since v3.0.

:root {
  --text-color: red;
  --text-size: 5rem;
}
<script src="https://cdn.tailwindcss.com"></script>

<span class="text-[color:--text-color] text-[length:--text-size] font-bold">
  Hello world!
</span>

6 Comments

Annoying thing is I have to define the data type every time which also makes it look really bloated but yeah at least it works.
@Thielicious you can use a media query on the root element to support media dark mode, which would accomplish the same thing. You can also use a class on the :root element if youre using the .dark approach.
version 3.4.3 use this syntax: text-[var(--my-var)]
@SafwatFathi it doesn't work play.tailwindcss.com/5tPMAgIfyh
check linter message 'text-[var(--text-color)]' applies the same CSS properties as 'text-[var(--text-size)]'.(cssConflict)'
|
36

Assuming you have already added TailwindCSS to your project and that your CSS file is called global.css.

First, you need to edit global.css to look like this:

@tailwind base;
@tailwind components;
@tailwind utilities;

.root,
#root,
#docs-root {
  --primary-color: #fff;
  --secondary-color: #000;
}

And then, in order to be able to use them, you need to update tailwind.config.js with the new CSS variables like so:

module.exports = {
  theme: {
    extend: {
      colors: {
        "primary-color": "var(--primary-color)",
        "secondary-color": "var(--secondary-color)"
      },
    },
  },
};

You can now use these variables as desired:

<div class="bg-primary-color">
  <h1>Hello World</h1>
</div>

3 Comments

This is my preferred solution, but it does have a downside: it doesn't automatically integrate with Tailwind's Dark Mode support. You have to add a media query (or class if you're using class-based dark mode) around the root rule to get that.
in my case I had to add :root selector to the global css for the variables
Tailwind 4.0 deprecated the tailwind.config.js file. Now you add them to the .css file under an @theme {} section; --color-primary: #fff;. You can then use these with the built in classes text-primary, bg-primary, etc.
13

If you want your variables to work with the opacity modifier syntax, you'll need to defined them as follows:

:root {
  --color-primary: 255 115 179;
  --color-secondary: 111 114 185;
}

Then use them in your config:

/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    colors: {
      // Using modern `rgb`
      primary: 'rgb(var(--color-primary) / <alpha-value>)',
      secondary: 'rgb(var(--color-secondary) / <alpha-value>)',

      // Using modern `hsl`
      primary: 'hsl(var(--color-primary) / <alpha-value>)',
      secondary: 'hsl(var(--color-secondary) / <alpha-value>)',
    }
  }
}

Basically, you'll need to convert your hex colors to rgb before you use them. Otherwise, they won't work properly. Here's the link to the documentation: https://tailwindcss.com/docs/customizing-colors#using-css-variables

4 Comments

that's so unpractical, is there a way to get around this?
Does <alpha-value> gets injected automatically when defining a classname color with an opacity? it isn't clear at all from the answer
Yes, <alpha-value> is replaced automatically to var(--tw-<property>-opacity) depending on the class, to have a better control. When bg-opacity-50 or bg-primary/50 is applied, --tw-bg-opacity is set to 0.5
Also have at look at stackoverflow.com/a/78651221/10594268. I've ended up with something like rgb(from var(--some-variable) r g b / <alpha-value>). Thanks!
10

While the other answers are probably valid as well. I noticed that you can use vars even easier by now.

At least with "tailwindcss": "3.4.3" and react this works fine as well:

<span className="text-[--text-color] font-bold">
  Hello world!
</span>

3 Comments

I hope this answer rises up since is the cleanest one by far, and works like a charm, current version ^3.4.7
This has nothing do to with react, it's a css class name
In React, you need to use className instead of class to define the style. In html you want <span class="text-[--text-color]">
6

You can easily configure it using this plugin. (supports darkMode) https://github.com/mertasan/tailwindcss-variables

npm install -D @mertasan/tailwindcss-variables

Usage:

// tailwind.config.js

module.exports = {
  theme: {
    colors: {
        red: {
            50: 'var(--colors-red-50)'
        }
    }
    variables: {
      DEFAULT: {
        sizes: {
          small: '1rem',
          button: {
            size: '2rem'
          }
        },
        colors: {
          red: {
            50: '#ff3232',
          },
        },
      },
      '.container': {
        sizes: {
          medium: '1.5rem',
        },
      },
    },
  },
  plugins: [
    require('@mertasan/tailwindcss-variables')
  ]
}

Output:

:root {
  --sizes-small: 1rem;
  --sizes-button-size: 2rem;
  --colors-red-50: #ff3232
}

.container {
  --sizes-medium: 1.5rem
}

1 Comment

I'm guessing that css variables was not built into tailwind at some point. I'm using [email protected] and I'm able to reference css variables without this plugin.
2

TailwindCSS v4

Since TailwindCSS v4, the legacy JavaScript-based configuration has been removed, and by default, a CSS-first configuration is available, where custom styles can be specifically declared in the CSS using the @theme { ... } syntax.

<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<style type="text/tailwindcss">
@theme {
  --color-primary: #fff;
  --color-secondary: #000;
  --color-primary-500: #0e70ed;
  --color-primary-600: #0552b3;
}
</style>

<div class="bg-secondary text-primary">
  Lorem Ipsum
</div>
<div class="bg-primary-500 text-white">
  Lorem Ipsum
</div>
<div class="text-primary-600">
  Lorem Ipsum
</div>

And with pre-declared CSS variables:

:root {
  --primary: #fff;
  --secondary: #000;
  --blue-1: #0e70ed;
  --blue-2: #0552b3;
}
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<style type="text/tailwindcss">
@theme inline {
  --color-primary: var(--primary);
  --color-secondary: var(--secondary);
  --color-primary-500: var(--blue-1);
  --color-primary-600: var(--blue-2);
}
</style>

<div class="bg-secondary text-primary">
  Lorem Ipsum
</div>
<div class="bg-primary-500 text-white">
  Lorem Ipsum
</div>
<div class="text-primary-600">
  Lorem Ipsum
</div>

And TailwindCSS color reference using var():

<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<style type="text/tailwindcss">
@theme {
  --color-primary: #fff;
  --color-secondary: #000;
  --color-primary-500: #0e70ed;
  --color-primary-600: #0552b3;
}

div {
  background-color: var(--color-secondary);
  color: var(--color-primary);
}

button {
  color: var(--color-primary-600);
}
</style>

<div>
  Lorem Ipsum
</div>
<div style="background-color: var(--color-primary-600);">
  Lorem Ipsum
</div>
<button>
  Lorem Ipsum
</button>

Related for v4 theme handling:

TailwindCSS v3

With TailwindCSS v3, if you only use the variables natively, the alpha-value that ensures transparency cannot take effect.

tailwind.config = {
  theme: {
    extend: {
      colors: {
        background: "var(--background)",
        foreground: "var(--foreground)",
      }
    }
  }
}
:root {
  --background: oklch(1 0.37 29.23);
  --foreground: oklch(0.89 0.0691 52.94);
}
<script src="https://cdn.tailwindcss.com"></script>

<div class="bg-background text-foreground h-10 w-10 border-2 border-black inline-block">A</div>
<div class="bg-background/50 text-foreground/50 h-10 w-10 border-2 border-black inline-block">A</div>

That's why a color declaration like this is needed:

tailwind.config = {
  theme: {
    extend: {
      colors: {
        background: "color-mix(in hsl, var(--background) calc(100% * <alpha-value>), transparent)",
        foreground: "color-mix(in hsl, var(--foreground) calc(100% * <alpha-value>), transparent)",
      }
    }
  }
}
:root {
  --background: oklch(1 0.37 29.23);
  --foreground: oklch(0.89 0.0691 52.94);
}
<script src="https://cdn.tailwindcss.com"></script>

<div class="bg-background text-foreground h-10 w-10 border-2 border-black inline-block">A</div>
<div class="bg-background/50 text-foreground/50 h-10 w-10 border-2 border-black inline-block">A</div>

Comments

1

You can use font family CSS variables with Tailwind CSS by following these steps:

Define your font family CSS variables in a global CSS file, such as global.css, and target the root element or a custom selector. For example:

:root {
  --font-sans: "Helvetica", "Arial", sans-serif;
  --font-serif: "Georgia", "Times New Roman", serif;
}

Update your tailwind.config.js file to include the font family CSS variables under the theme.fontFamily property. For example:

module.exports = {
  theme: {
    fontFamily: {
      sans: "var(--font-sans)",
      serif: "var(--font-serif)",
    },
  },
};

Use the font family CSS variables as desired in your HTML elements with Tailwind classes. For example:

<div className="font-sans">
  <h1>Hello World</h1>
</div>

Comments

1

You can use theme() function provided by tailwind. You can use it in this way:

:root{
  --primary: theme(colors.primary);
  --secondary: theme(colors.secondary);
}

Comments

1

A bit late but, apart from other answers, for example let's say we want to create a basic theming for an application using css variables with tailwind, what we can do is:

  • Create some variable(s) that should be adjusted according to specified theme mode
    :root {
        --color-theme: 245, 245, 245
    }
    
    [data-theme="dark"] {
        --color-theme: 4, 4, 4
    }
    
  • Reference them in your tailwind.config.[cjs,mjs, js] file
    module.exports = {
        theme: {
            extend: {
                colors: {
                    base: "rgb(var(--color-theme), <alpha-value>)"
                }
            },
        },
    }
    

You can also create --color-theme-100 and --color-theme-200etc and reference them in your tailwind.config file with this syntax

module.exports = {
    theme: {
        extend: {
            colors: {
                base: {
                    100: "rgb(var(--color-theme-100), <alpha-value>)",
                    200: "rgb(var(--color-theme-200), <alpha-value>)",
                    300: "rgb(var(--color-theme-300), <alpha-value>)"
                }
            }
        },
    },
}

Segment <alpha-value> will come in handy when you want to use base-300/opacity-percentage as a classname, if you are sure anyone won't need that feature, you can opt-out that part

Comments

1

First part: Create the CSS variables

I generate CSS color variables (custom properties) which are defined in a javascript file and inject them (in my case using a custom Vite plugin) in a <style> HTML tag inside the head tag (of my app).

I create the most fundamental "layer" of colors-variables for both light & dark theme. Below is a very simplified example of the injected CSS which includes dark-mode override for the base-colors:

:root {
  --gray-100: #141414;
  --gray-200: #292929;
  --gray-800: #525252;
  --gray-900: #666666;

  --green-200: #308730;
  --green-500: #4CAF50;
  --green-700: #9BFFB6;
  ...
}

.dark {
  --gray-100: #e0e0e0;
  --gray-200: #c2c2c2;
  --gray-800: #292929;
  --gray-900: #141414;

  --green-200: #9BFFB6;
  --green-500: #43a15c;
  --green-700: #308730;
}

And then a second layer of abstraction which is more generalized:

:root {
  --palette-primary: var(--gray-100);
  --palette-secondary: var(--gray-800);
  --palette-success: var(--green-200);
}

Second part: Extend Tailwind colors config

Tailwind does not magically knows about CSS variables, and the color variables created earlier need to be hand-fed to the tailwind.config file, for example:

module.exports = {
  ...
  theme: {
    extend: {
      colors: {
        gray: {
          "100": "color-mix(in srgb, var(--gray-100) calc(<alpha-value> * 100%), transparent)",
          "200": "color-mix(in srgb, var(--gray-200) calc(<alpha-value> * 100%), transparent)",
        },
        // and so on...
        // custom-named palette layer:
        primary: "color-mix(in srgb, var(--palette-primary) calc(<alpha-value> * 100%), transparent)",
        secondary: "color-mix(in srgb, var(--palette-secondary) calc(<alpha-value> * 100%), transparent)",
      },
    },
  },

Use color-mix (learn about it) to allow opacity for the CSS color variables.

Clearly extending Tailwind's colors is a tedious task and should be done programmatically to generate the above core.

References:

Comments

0

Alternatively, use CSS var's with a JS framework:

When I was working with Tailwind and Svelte for the first time, I was looking for a solution to this, and I found that you can use the style attribute:

<script>
let cssVariables = {
  'primary-color': "#ffffff", 
  'secondary-color': "#000"
}

let styleValues = Object.entries(cssVariables)
.map(([key, value]) => `--${key}:${value}`)
.join(';')
</script>

<p style={styleValues} 
class="text-center text-[4vmax] text-[color:var(--primary-color)]">
  Hello World
</p>

The code above makes a object, this object is converted to a string that works like pure CSS, every property is joined to that string. This works, assuming that you're in Svelte, although, in HTML doesn't. If you want to use Tailwind with HTML, you must write the whole string:

<p style="--primary-color:#ffffff;--secondary-color:#000"
class="text-[4vmax] text-center text-[color:var(--primary-color)]">
  Hello World
</p>

So, I recommend you use a framework that help you use data binding. Also, there're other things that you can do with this trick, like reactive CSS (below, in the Svelte way):

<script>
$: changingHue = 0
setInterval(() => changing_hue++, 250)
$: cssVariables = {
  'primary-color': `hsl(${changingHue} 100% 70%)`, 
  'secondary-color': "#000"
}

$: styleValues = Object.entries(cssVariables)
.map(([key, value]) => `--${key}:${value}`)
.join(';')
</script>

<p style={styleValues} 
class="text-center text-[4vmax] text-[color:var(--primary-color)]">
  Hello World
</p>

In conclusion, you don't need another library to make Tailwind use CSS variables, just Javascript and even HTML is enough.

2 Comments

mixing the CSS and the JS should be a least resort since it's doable with css only
@petitkriket Yes, in a simple project, CSS and it's variables would be enough
0

Just put it inside calc

<element class="property-[calc(var(--variable))]">

1 Comment

This way you don't have to specify the type specifier

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.