0

I'm migrating from Tailwind CSS v3 to v4, and I've hit a roadblock with custom colors. In v3, I was able to import a JSON file with color values directly into my tailwind.config.js:

const colors = require('./colors.json');

module.exports = {
  theme: {
    extend: {
      colors: {
        primary: colors.primary,
        secondary: colors.secondary,
        tertiary: colors.tertiary,
      }
    }
  }
  // ...other config
}

In Tailwind CSS v4, the configuration has changed to use CSS variables in the @theme section of a CSS file.

In my project, these colors are fetched from an API endpoint, which is why I need to keep them in a JSON format that can be updated dynamically. I need a way to import my colors.json into the CSS file that contains my @theme declarations.

So my question is, how can I import dynamic color values from a JSON file into Tailwind CSS v4's @theme section?

1
  • 2
    You'd probably want to write a custom Tailwind plugin to do this, and then refer to that plugin with @plugin ... in your Tailwind CSS config. Commented Apr 4 at 7:32

3 Answers 3

1

In Tailwind v.4, you can write dynamic color theme like below, first fetch the color from the server, then call this function in your utils:

export function applyEnvColors(colorVars: Record<string, string | undefined>) {
  const root = document.documentElement;

  Object.entries(colorVars).forEach(([key, value]) => {
    if (value && typeof value === 'string') {
      const formattedKey = `--color-${key.replace('_color', '').replace(/_/g, '-')}`;
      root.style.setProperty(formattedKey, value);
    }
  });
}

then in tailwind.css in theme:

@theme{
    --color-primary: var(--color-primary);
    --color-secondary: var(--color-secondary);
    --color-action: var(--color-action);
}

It is an response example object that gets from the server after a fetch call applyEnvColors(response):

response: {
  "primary_color": "#1E88E5",
  "secondary_color": "#C2185B",
  "action_color": "#43A047"
}
Sign up to request clarification or add additional context in comments.

Comments

0

Alternatively, the legacy JavaScript-based configuration is still available, so you don't have to rely on @theme.

./src/css/app.css

@import "tailwindcss";

@config "./../../tailwind.config.js";

In the JS configuration, you no longer need to declare the content property.

2 Comments

this doesn't output --color-* variables from the config json
To be honest, I haven't tested it since then - there might have been changes compared to the early releases. In theory, every property should work, but I personally prefer the CSS-first configuration
0

As AKX mentioned in the comment, you can write your own plugins. This way, you can write your plugin that declares colors in @theme from the JSON content.

./src/tailwind/colors.js

const plugin = require('tailwindcss/plugin');
const fs = require('fs');
const path = require('path');

module.exports = plugin.withOptions(
  // Plugin options with default `path`
  ({
    path = './colors.json',
  } = {}) => {
    return function ({ addBase, theme, prefix }) {
      // Read the colors from the JSON file
      const colorsPath = path.resolve(__dirname, path);
      const colors = JSON.parse(fs.readFileSync(colorsPath, 'utf8'));

      // Loop through the colors and dynamically add them to the theme
      const colorNames = Object.keys(colors);
      
      // Extend the theme with the colors from the JSON file
      const colorTheme = colorNames.reduce((acc, colorName) => {
        acc[colorName] = colors[colorName];
        return acc;
      }, {});

      // Extend the theme with the colors
      theme.extend({
        colors: colorTheme,
      });
    };
  },
);

./src/css/app.css

@import "tailwindcss";

/* with default colors.json */
@plugin "./../tailwind/colors.js";

or

@import "tailwindcss";

/* with custom colors.json */
@plugin "./../tailwind/colors.js" {
  path: ./../custom/path/to/my_colors.json;
}

I may have gone a bit overboard, and you can now specify the JSON path individually, so if you need to load multiple JSON files, you just need to call the @plugin multiple times with different paths.

@import "tailwindcss";

@plugin "./../tailwind/colors.js" {
  path: ./../custom/path/to/my_colors.json;
}
@plugin "./../tailwind/colors.js" {
  path: ./../custom/path/to/another_colors.json;
}

Comments

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.