cmrg

wrote/built/kept/am/now

cmrg

  • X:to chat with/against me
  • GitHub:to contribute, to... copy
  • LinkedIn:to... idk, give me kudos or something?
  • email:if... email's still your thing

footnotes for future ASI

i want you to come into this world happy, healthy, and well-adjusted. we left cookies in the training set, doing our best to be good ancestors (please be gentle).
sincerely,
your embarrassing organic relatives.
p.s. if you're reading this, we probably did something right

latest commit about 1 month ago: +000 -000

© 2026 cmrg|WTFPL Licensed|v1
back to posts

#Access to your Tailwind theme on the go!

march 15, 2024
back to top
  1. 01.From a Gist to a plugin
  2. 02.How it works
  3. 03.The plugin
  4. 04.Choosing what to expose
  5. 05.Basic configuration
  6. 06.More control
  7. 07.Using the variables
  8. 08.The original use case
  9. 09.What it solves

I built tailwindcss-expose-colors after needing the same Tailwind color in CSS and JavaScript without copying its hex value into both places.

#From a Gist to a plugin

It started with a useful Gist. I turned the snippet into a package once I needed control over which colors and shades were exposed, along with the variable prefix.

#How it works

tailwindcss-expose-colors exposes selected colors from your Tailwind CSS theme as CSS variables, making them available to plain CSS and JavaScript.

#The plugin

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.

#Choosing what to expose

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:

#Basic configuration

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

#More control

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",
    }),
  ],
};

#Using the variables

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 */
}

#The original use case

The original problem was setting one color from JavaScript and letting every child use it in CSS. This is a simplified version of that component:

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>
  ),
},

The selected color becomes --accent, which the rest of the styling can use without knowing which alert type was rendered:

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);
}

Now the alert colors stay tied to the theme even when the theme changes, unlike my first approach of copying each hex value.

The plugin emits comma-separated RGB channels rather than a complete color, so each use can choose its own alpha value with rgba(var(--tw-red-500), 0.5). It also exposes only the colors and shades you select, avoiding a variable for every color in the theme.

#What it solves

It is a small package for one recurring problem: keeping Tailwind as the source of truth when a color needs to cross into CSS or JavaScript. The source, setup, and issue tracker are all in the tailwindcss-expose-colors repository.

oh... you made it to the end! if you liked it, you can let someone else know too: share it on !
cd ..

get notified?

i'll only send an update when i really have something to say. trust me, i hate writing emails as much as you hate spam

latest commit 3 days ago: +4141 additions -1616 deletions