Skip to Content
Back

Access to your Tailwind theme on the go!

Hey, today I'd like to share a new tool I've developed: tailwindcss-expose-colors. It's a useful piece of code that I think many of you will appreciate for its practicality and simplicity.

Contents

An Open-Source Beginning

This journey started with a simple Gist, but as I delved deeper, I saw the potential to evolve this snippet into a more robust package, thus tailwindcss-expose-colors was born. This tool is all about bringing a touch of convenience and efficiency to your workflow when working with Tailwind CSS.

The mechanics of tailwindcss-expose-colors

Here's the TL/DR: tailwindcss-expose-colors lets you… Expose selected colors from your Tailwind theme as CSS variables. The idea is simple: to make it easier to use your Tailwind theme colors directly in your CSS and even manipulate them in JavaScript.

Here's a Look at the Code

The plugin is built with TypeScript and hooks into Tailwind's plugin API. Here's a snapshot of the main function:

tailwindcss-expose-colors.ts
export const exposeColors = ({
  colors = ["red"],
  shades = ["500"],
  prefix = "--tw"
}) =>
  function ({ addBase, theme }: PluginAPI) {
    // ...
  }

It then filters and maps your theme's colors based on your configuration (tailwind.config.ts) and injects them as CSS variables into your project.

Customizable, simple, and lightweight

With tailwindcss-expose-colors, you can specify which colors and shades to expose and even set your preferred variable prefix. Here's an example of setting it up in tailwind.config.ts:

Simple Setup

tailwind.config.ts
export default {
  theme: { extend: {} },
  content: ["./src/**/*.{ts,tsx}"],
  plugins: [exposeColors({ colors: ["red", "green", "blue"] })]
}

Advanced Setup

tailwind.config.ts
export default {
  theme: { extend: {} },
  content: ["./src/**/*.{ts,tsx}"],
  plugins: [
    exposeColors({
      colors: ["primary", "success", "error", "base"],
      shades: ["DEFAULT", "500", "700", "900"],
      prefix: "--design-system"
    })
  ]
}

Practical Application

Once everything is set up, you can use these colors in your CSS, like this:

styles.css
body {
  background: rgba(var(--tw-red-500), 0.1);
  border: 1px solid rgb(var(--tw-primary)); /* --tw-primary maps to the `DEFAULT` shade */
}

This integration makes it straightforward to adapt and apply colors to various aspects of your web projects.

In a "real" scenario

This utility began as a simple itch that I had while thinking about how to set a color variable based on a specific condition in JS so that all of the children could be styled accordingly. This is the original snippet:

mdx.tsx
{
  // ...
  blockquote: ({ children, ...props }: any) => (
    <blockquote
      {...props}
      className={cn({
        "blockquote-mask blockquote-safari relative !my-8 p-4": true,
        "[--accent:var(--tw-primary)]": !alert,
        "[--accent:var(--tw-blue-500)]": alert === "NOTE",
        "[--accent:var(--tw-green-500)]": alert === "TIP",
        "[--accent:var(--tw-purple-500)]": alert === "IMPORTANT",
        "[--accent:var(--tw-amber-500)]": alert === "WARNING",
        "[--accent:var(--tw-red-500)]": alert === "CAUTION"
      })}>
      {icon} {children}
    </blockquote>
  ),
},

To clarify, this is a simplified version of the original code running in production. That said, this is the use I have for it:

styles.css
.blockquote-mask {
  border: none;
  background-size: 100%;
  background-repeat: no-repeat;
  background: radial-gradient(
      circle 16px at top left,
      #0000 100%,
      rgba(var(--accent), 0.1)
    ) top left;
}
 
.blockquote-mask::before {
  content: "";
  width: 4px;
  height: calc(100% - 15px); /* The mask -1px for a small overlap */
  position: absolute;
  top: 15px;
  left: 0;
  background: linear-gradient(
    to bottom,
    rgba(var(--accent), 0.8) 0%,
    rgba(var(--accent), 0.8) 50%,
    rgba(var(--accent), 0.1) 100%
  );
}
 
.blockquote-mask svg {
  fill: rgba(var(--accent), 0.8);
}

And that's it, now I have my theme colors matching with the rest of the system even if I change them afterwards, which didn't happen in my last approach .

With this plugin, I extended the original functionality; now we have R, G, B values, so the opacity is also a customizable value for rgba(var(--tw-red-500), 0.5), and scoped the config so the exported variables are only the essentials you'll need, .

Wrapping Up

tailwindcss-expose-colors is a nifty little addition to your Tailwind CSS toolkit. It's about making life a bit easier and your code a bit cleaner. So, give it a whirl in your next project and see how it fits!

I'm open to feedback and suggestions, so feel free to share your thoughts and experiences. Here's to making our development journey a bit more enjoyable, one handy utility at a time!

376
Quix: A Lightning-Fast VTEX IO CLI Experiment

Get notified!

I'll only send updates with the best content. Trust me, I hate writing emails as much as you hate spam.

r19

A dead-simple React 19 "framework" implementation from scratch

#bun#esm#react#rsc

ds

Think "docker stats" but with beautiful, real-time charts into your terminal. 📊

#cli#docker#hacktoberfest#rust#stats

htnx

a htmx like experience in Next.js with RSC and quite a bit of questionable code.

#htmx#nextjs#react#rsc

quix

Supercharge Your VTEX IO Workflow with a Lightning-Fast CLI Alternative. Enhance Developer Experience and Boost Productivity.

#performance-analysis#rust-lang#vtex#vtex-io#wip

tailwindcss-expose-colors

Expose specific colors from your Tailwind CSS theme as CSS variables

#tailwind#tailwindcss#tailwindcss-plugin

nextjs-zustand-setup-ssr

The bare minimum for a Zustand setup with server-side data and client-side hydration in Next.js

#typescript
CC BY-NC 4.0|CMRG©