Turn any website into a shadcn/ui theme
shadcn/ui components read their colors from a fixed set of CSS variables in app/globals.css. Restyling them to match a site you like comes down to one question per variable: which of that site’s colors goes here? This page shows the mapping on a real example, the output Stylasso writes for it, and how to do the same by hand.
How shadcn/ui themes work
From the shadcn/ui theming docs, as of 12 November 2026:
- Colors come in background and foreground pairs.
--primaryis the button fill,--primary-foregroundis the text on it. Surfaces work the same way:--cardand--card-foreground. - The default
:rootblock has 32 variables:--radius, the pairs for background, card, popover, primary, secondary, muted and accent, then--destructive,--border,--input,--ring, five chart colors and eight sidebar variables. - Values are written in
oklch(). Dark mode overrides the same variables inside a.darkselector. - An
@theme inlineblock exposes the variables to Tailwind, which is whybg-backgroundandtext-muted-foregroundwork.
Which site color goes where
Stylasso ran on Northwind Roasters, a fictional coffee shop we built for demos. It found seven colors with roles. This is where its shadcn/ui export puts each one:
| Role on the site | Hex | shadcn/ui variables |
|---|---|---|
| background | #fffaf3 | --background, --popover |
| surface | #f6eadb | --card, --secondary, --muted, --sidebar |
| text | #2b1d14 | --foreground and the -foreground of card, popover, secondary and accent |
| muted | #7a6656 | --muted-foreground |
| primary | #c2410c | --primary, --ring, --chart-1, --sidebar-primary |
| accent | #4d7c5a | --brand-accent (new) and --chart-2 |
| border | #ead8c3 | --border, --input |
Two of these are easy to get wrong by hand:
- shadcn’s
--accentis not a brand color. It is the subtle background of a hovered menu item or ghost button. Putting a site’s green accent there turns every hover green. The export sets--accentto the text color mixed 6% into the background, and keeps the brand green as a separate--brand-accentyou can use asbg-brand-accent. --inputuses the border color. On Northwind that border is 1.34:1 against the background, fine for dividers but faint for the outline of a text field. If your form fields have no other fill, set--inputa few steps darker.
The remaining variables: --primary-foreground is white, --destructive keeps shadcn’s default red, and the chart colors continue with the site’s amber #f59e0b and dark orange #9a3412.
What you paste
The start of Stylasso’s shadcn/ui export for that page, unedited:
@import url("https://fonts.googleapis.com/css2?family=Fraunces:wght@400;600&family=Hanken+Grotesk:wght@400;500;600&family=JetBrains+Mono:wght@400&display=swap");
/* Keep the @import line above every other rule, including @import "tailwindcss". */
/* Northwind Roasters as a shadcn/ui theme: replace the :root and .dark blocks in globals.css. The .dark block keeps the brand colors on shadcn's neutral dark surfaces. */
:root {
--radius: 12px;
--background: oklch(98.7% 0.011 76.6);
--foreground: oklch(24.5% 0.027 53.8);
--card: oklch(94.2% 0.024 73.6);
--card-foreground: oklch(24.5% 0.027 53.8);
--popover: oklch(98.7% 0.011 76.6);
--popover-foreground: oklch(24.5% 0.027 53.8);
--primary: oklch(55.3% 0.174 38.4);
--primary-foreground: oklch(100.0% 0.000 0);
--secondary: oklch(94.2% 0.024 73.6);
--secondary-foreground: oklch(24.5% 0.027 53.8);
--muted: oklch(94.2% 0.024 73.6);
--muted-foreground: oklch(52.5% 0.035 60.6);
--accent: color-mix(in oklab, oklch(24.5% 0.027 53.8) 6%, oklch(98.7% 0.011 76.6));
--accent-foreground: oklch(24.5% 0.027 53.8);
--destructive: oklch(57.7% 0.245 27.3);
--border: oklch(89.1% 0.035 71.6);
--input: oklch(89.1% 0.035 71.6);
--ring: oklch(55.3% 0.174 38.4);
--chart-1: oklch(55.3% 0.174 38.4);
/* ...chart, sidebar, brand accent and font variables (15 more lines) */
}
The whole file is just under 100 lines. After :root comes a .dark block: Northwind is a light site, so the export keeps the brand primary and accent on shadcn’s neutral dark surfaces instead of inventing a dark palette the site never had. Last comes an @theme inline addition with the fonts, the brand accent and the site’s type scale, so text-6xl gives you its 64px, weight 600 heading with -1.28px tracking. For a site that is dark already, the export writes one block for both modes; there is an example on the Tailwind v4 page.
How to use it
- Open the site whose look you want and click the Stylasso icon.
- Pick shadcn/ui in the export bar and press Copy.
- In
app/globals.css, put the font@importline at the very top, replace your:rootand.darkblocks, and add the lines from the@theme inlinepart to your existing@theme inlineblock. - Check a button, a card, a dropdown and an input. Those four touch almost every variable.
Doing it by hand, for free
The shadcn/ui export is part of Stylasso Pro ($9.99 once). The free CSS variables export gives you the same seven colors with their roles, and the table above is the whole mapping. Convert each hex to oklch() (or keep hex: the variables are plain CSS colors), set --accent to a light tint of your text color rather than the brand accent, and copy --destructive and the .dark block from the shadcn/ui docs. It takes ten minutes or so; the export saves those minutes and the chance of a missed variable.
Questions
Does this work with shadcn/ui on Tailwind v3?
The export targets the current setup with Tailwind v4, oklch() values and @theme inline. On an older v3 project, use the color mapping above with your existing variable format.
Do I need every variable?
Components expect all of them. A missing one shows up as a transparent background or invisible text somewhere, often in a popover or the sidebar. The export always writes the full set.
Is anything sent to a server?
No. The page is read in your browser when you click the icon, only in that tab. Nothing leaves your browser unless you publish a share link.