Using Radix Colors with Tailwind CSS

Radix Colors makes light and dark mode effortless in Tailwind CSS with automatic theming, better contrast, and semantic color scales. Learn how to integrate it and define custom colors.

Radix Colors is an accessible color system that provides a well-structured and easy-to-use scale. By integrating it with Tailwind CSS, you can achieve:

  • Consistent theming across light and dark modes.
  • Automatic dark mode, reducing the need for the dark: variant in most cases.
  • Good contrast ratios between text and background colors.
  • A semantic color scale, where each color has a specific purpose.

With recent release of Tailwind CSS v4, using Radix Colors has become even easier. When combined with next-themes it's almost seamless.

In this guide, I will use .dark class selector for dark mode. You can use other selectors or media queries. I find this easy to implement while using next-themes.

To enable .dark class as dark mode switch, you need to configure a custom selector in your CSS file:

@custom-variant dark (&:where(.dark, .dark *));

Once this is set up, you’re ready to define colors.

Defining Colors with Radix

Instead of using descriptive color names like blue, sky or early-spring-night-grass-under-full-moon, I prefer semantic naming, ensuring 2 key variants are always present:

  • Primary - the main theme color.
  • Neutral - a grayscale palette for backgrounds and texts.

Here’s an example of how to define colors in Tailwind CSS using Radix:

@theme {
  --color-*: initial;

  --color-surface: #fff;

  --color-primary-1: #fdfdfe;
  --color-primary-2: #f7f9ff;
  --color-primary-3: #edf2fe;
  --color-primary-4: #dfeaff;
  --color-primary-5: #d0dfff;
  --color-primary-6: #bdd1ff;
  --color-primary-7: #a6bff9;
  --color-primary-8: #87a5ef;
  --color-primary-9: #3d63dd;
  --color-primary-10: #3657c3;
  --color-primary-11: #395bc7;
  --color-primary-12: #1d2e5c;

  --color-primary-contrast: #fff;
  --color-primary-surface: #f5f8ffcc;
  --color-primary-indicator: #3d63dd;
  --color-primary-track: #3d63dd;

  --color-neutral-1: #fcfcfd;
  --color-neutral-2: #f9f9fb;
  --color-neutral-3: #eff0f3;
  --color-neutral-4: #e7e8ec;
  --color-neutral-5: #e0e1e6;
  --color-neutral-6: #d8d9e0;
  --color-neutral-7: #cdced7;
  --color-neutral-8: #b9bbc6;
  --color-neutral-9: #8b8d98;
  --color-neutral-10: #80828d;
  --color-neutral-11: #62636c;
  --color-neutral-12: #1e1f24;

  --color-neutral-contrast: #ffffff;
  --color-neutral-surface: #ffffffcc;
  --color-neutral-indicator: #8b8d98;
  --color-neutral-track: #8b8d98;
}

By setting --color-*: initial;, you remove default colors, keeping only the scales you define. --color-surface serves as the beackground color for the body.

Adding Dark Mode Colors

Unlike Tailwind’s color scale, which requires separate class names for light and dark modes, Radix uses the same class name in both themes. For instance, bg-primary-1 will display an almost white blue in light mode and an almost black blue in dark mode.

To define the reversed scale for dark mode, use @layer theme along with the .dark selector. Since CSS variables are overridden, there’s no need to reset colors manually:

@layer theme {
  .dark {
    --color-surface: #111;

    --color-primary-1: #0c111c;
    --color-primary-2: #111725;
    --color-primary-3: #172448;
    --color-primary-4: #1d2e61;
    --color-primary-5: #243974;
    --color-primary-6: #2d4484;
    --color-primary-7: #375098;
    --color-primary-8: #405eb2;
    --color-primary-9: #3d63dd;
    --color-primary-10: #3f5cb0;
    --color-primary-11: #93b4ff;
    --color-primary-12: #d5e2ff;

    --color-primary-contrast: #fff;
    --color-primary-surface: #111d3980;
    --color-primary-indicator: #3d63dd;
    --color-primary-track: #3d63dd;

    --color-neutral-1: #111;
    --color-neutral-2: #191919;
    --color-neutral-3: #222;
    --color-neutral-4: #2a2a2a;
    --color-neutral-5: #313131;
    --color-neutral-6: #3a3a3a;
    --color-neutral-7: #484848;
    --color-neutral-8: #606060;
    --color-neutral-9: #6e6e6e;
    --color-neutral-10: #7b7b7b;
    --color-neutral-11: #b4b4b4;
    --color-neutral-12: #eee;

    --color-neutral-contrast: #ffffff;
    --color-neutral-surface: rgba(0, 0, 0, 0.05);
    --color-neutral-indicator: #6e6e6e;
    --color-neutral-track: #6e6e6e;
  }
}

Simplified Component Styling

That's all. Now instead of using

bg-sky-100 dark:bg-sky-900 text-slate-900 dark:text-slate-100

You can simply use:

bg-primary-1 text-gray-12

Both will achieve the same effect—apply blue background and light-colored text.

Example: Styling a Card Component

Here’s how a card component looks before and after implementing Radix Colors:

--- a/card-tailwind.html
+++ b/card-radix.html
@@ -1,4 +1,4 @@
-<div class="rounded-lg border border-blue-200 bg-white p-5 dark:border-blue-700 dark:bg-gray-800">
-  <h2 class="mb-5 text-xl font-bold text-gray-900">Hello There!</h2>
-  <p class="mt-4 text-gray-700">General Kenobi!</p>
+<div class="rounded-lg border border-primary-4 bg-surface p-5">
+  <h2 class="mb-5 text-xl font-bold text-neutral-12">Hello There!</h2>
+  <p class="mt-4 text-neutral-11">General Kenobi!</p>
 </div>

Custom Palette Generator

Radix provides a custom palette generator you can find at https://www.radix-ui.com/colors/custom. It allows you to create your own light and dark mode color scales. Copy them in CSS format and integrate directly into your project. The generator ensures proper contrasts and accessibility.