npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tailwind-to-style

v4.0.1

Published

Zero-build runtime Tailwind CSS engine. Convert utility classes to real CSS with variants, slots, tokens, and React bindings. SSR-ready, tree-shakeable.

Downloads

985

Readme

tailwind-to-style

npm version bundle size license

Zero-build runtime Tailwind CSS engine. Convert utility classes to real CSS — with variants, slots, design tokens, and React bindings. No build step, no PostCSS, no config file. Just works.


Why tailwind-to-style?

| Feature | tailwind-to-style | Tailwind CSS | Stitches | CVA | |---------|:---:|:---:|:---:|:---:| | Zero build step | ✅ | ❌ | ✅ | ❌ | | Tailwind syntax | ✅ | ✅ | ❌ | ✅ | | Runtime variants | ✅ | ❌ | ✅ | ✅ | | Slots (multi-part) | ✅ | ❌ | ❌ | ❌ | | Design tokens | ✅ | ❌ | ✅ | ❌ | | Inline style output | ✅ | ❌ | ❌ | ❌ | | SSR support | ✅ | ✅ | ✅ | ✅ | | React bindings | ✅ | ❌ | ✅ | ❌ | | Framework agnostic | ✅ | ✅ | ❌ | ✅ | | Tree-shakeable | ✅ | N/A | ✅ | ✅ |


Installation

npm install tailwind-to-style
pnpm add tailwind-to-style
yarn add tailwind-to-style

Or use a CDN:

<script src="https://unpkg.com/tailwind-to-style"></script>

Quick Start

import { tw, tws, cx } from 'tailwind-to-style';

// Generate atomic CSS classes (auto-injected into DOM)
document.body.className = tw('flex items-center justify-center min-h-screen bg-gray-100');

// Convert to inline styles
element.style.cssText = tws('bg-blue-500 text-white p-4 rounded-lg');

// Conditional class merging
const classes = cx('base', isActive && 'ring-2', { 'opacity-50': disabled });

Examples

Want to try the library with real demos?

  • examples/basic/ — runtime tws() examples for inline conversion and custom values.
  • examples/react-demo/ — full React showcase with components, variants, tokens, and theme switching.
  • examples/twsx-classname-app/ — Vite-based runtime tw() v4 demo with variant and slots components.

Run the demos by opening examples/README.md or using the commands below:

cd examples/react-demo
npm install
npm run dev
cd examples/twsx-classname-app
npm install
npm run dev

API Reference

tw() — The Main Function

One function, four modes:

Mode 1: String → Atomic Classes

tw('flex items-center gap-4 hover:bg-gray-100')
// → "tw-flex tw-items-center tw-gap-4 tw-hover-bg-gray-100"
// CSS is auto-injected with full pseudo-class support

Mode 2: Named Class

tw('sidebar', 'w-64 h-screen bg-white border-r border-gray-200')
// → "sidebar"
// Generates .sidebar { ... } with all the Tailwind styles

Mode 3: Variants

const button = tw({
  name: 'btn',
  base: 'px-4 py-2 rounded-lg font-medium transition-all',
  variants: {
    color: {
      primary: 'bg-blue-600 text-white hover:bg-blue-700',
      danger: 'bg-red-600 text-white hover:bg-red-700',
      ghost: 'bg-transparent text-gray-700 hover:bg-gray-100',
    },
    size: {
      sm: 'text-sm px-3 py-1.5',
      md: 'text-base px-4 py-2',
      lg: 'text-lg px-6 py-3',
    },
  },
  defaultVariants: { color: 'primary', size: 'md' },
});

button({ color: 'danger', size: 'lg' })
// → "btn btn--color-danger btn--size-lg"

Mode 4: Slots (Multi-Part Components)

const card = tw({
  name: 'card',
  slots: {
    root: 'bg-white rounded-xl shadow-lg overflow-hidden',
    header: 'px-6 py-4 border-b border-gray-100',
    body: 'px-6 py-4',
    footer: 'px-6 py-4 bg-gray-50',
  },
});

card()
// → { root: "card__root", header: "card__header", body: "card__body", footer: "card__footer" }

Utility Methods

tw.extractCSS()  // Get all generated CSS as string (SSR)
tw.clearCache()  // Clear internal caches
tw.config({ prefix: 'my', hash: false }) // Configure globally

tws() — Inline Styles

Convert Tailwind classes directly to CSS styles. No DOM injection needed.

// Returns CSS string
tws('bg-blue-500 p-4 rounded-lg')
// → "background-color: rgb(59,130,246); padding: 1rem; border-radius: 0.5rem;"

// Returns JSON object (for React style prop, etc.)
tws('flex items-center gap-4', true)
// → { display: 'flex', alignItems: 'center', gap: '1rem' }

cx() — Conditional Class Names

A lightweight clsx alternative built-in.

cx('base-class', isActive && 'active-class', { 'disabled': isDisabled })
// → "base-class active-class"

// Arrays work too
cx(['p-4', 'bg-white'], condition && ['ring-2', 'ring-blue-500'])

// Create pre-filled cx
const btnClass = cx.with('px-4 py-2 rounded font-medium');
btnClass('bg-blue-500') // → "px-4 py-2 rounded font-medium bg-blue-500"

React Bindings

import { styled, ThemeProvider, useTheme, useTws } from 'tailwind-to-style/react';

styled() — Create Styled Components

import { styled } from 'tailwind-to-style/react';

const Button = styled('button', {
  name: 'btn',
  base: 'px-4 py-2 rounded-lg font-medium transition-colors',
  variants: {
    color: {
      primary: 'bg-blue-600 text-white hover:bg-blue-700',
      secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300',
    },
    size: {
      sm: 'text-sm px-3 py-1.5',
      lg: 'text-lg px-6 py-3',
    },
  },
  defaultVariants: { color: 'primary', size: 'sm' },
});

// Variant props are type-safe and stripped from DOM
<Button color="primary" size="lg" onClick={handleClick}>
  Click Me
</Button>

ThemeProvider & useTheme

import { ThemeProvider, useTheme } from 'tailwind-to-style/react';

const theme = {
  colors: { primary: '#3b82f6', danger: '#ef4444' },
  radius: { sm: '0.25rem', md: '0.5rem' },
};

function App() {
  return (
    <ThemeProvider theme={theme}>
      <MyComponent />
    </ThemeProvider>
  );
}

function MyComponent() {
  const { theme, setTheme } = useTheme();
  // Access tokens via CSS variables: var(--tws-colors-primary)
}

useTws() — Inline Style Hook

import { useTws } from 'tailwind-to-style/react';

function Box({ classes }) {
  const style = useTws(classes); // memoized style object
  return <div style={style}>Content</div>;
}

Design Tokens

import { createTheme, tokenRegistry, token } from 'tailwind-to-style/tokens';

createTheme()

createTheme({
  colors: {
    primary: '#3b82f6',
    secondary: '#8b5cf6',
    success: '#10b981',
  },
  spacing: { sm: '0.5rem', md: '1rem', lg: '1.5rem' },
  radius: { sm: '0.25rem', md: '0.5rem', lg: '1rem' },
}, { selector: ':root' });
// Injects CSS variables on :root:
// --tws-colors-primary: #3b82f6;
// --tws-colors-secondary: #8b5cf6;
// ...

tokenRegistry

tokenRegistry.get('colors.primary')    // → '#3b82f6'
tokenRegistry.set('colors.primary', '#2563eb')
tokenRegistry.toCSS()                  // → full :root CSS string
tokenRegistry.subscribe((tokens) => { /* react to changes */ })

token() — CSS Variable Reference

token('colors.primary')           // → "var(--tws-colors-primary)"
token('colors.primary', '#000')   // → "var(--tws-colors-primary, #000)"

Animations

import { animate, defineAnimation, getAnimationNames } from 'tailwind-to-style/animations';

Built-in Presets

element.className = animate('fadeIn');
element.className = animate('slideInUp', { duration: '500ms', delay: '100ms' });
element.className = animate('bounce');
element.className = animate('spin');  // infinite

Available presets: fadeIn, fadeOut, slideInUp, slideInDown, slideInLeft, slideInRight, scaleIn, scaleOut, bounce, shake, pulse, spin, ping

Custom Animations

defineAnimation('wiggle', {
  keyframes: [
    { transform: 'rotate(0deg)' },
    { transform: 'rotate(-3deg)' },
    { transform: 'rotate(3deg)' },
    { transform: 'rotate(0deg)' },
  ],
  duration: '300ms',
  easing: 'ease-in-out',
});

animate('wiggle'); // works!

SSR (Server-Side Rendering)

import { tw, createSSRCollector } from 'tailwind-to-style';

// Collect all CSS generated during render
const collector = createSSRCollector();

const html = renderToString(<App />);
const css = collector.extract();

// Inject into HTML head
const fullHtml = `
  <html>
    <head><style>${css}</style></head>
    <body>${html}</body>
  </html>
`;

Tree-Shakeable Imports

Import only what you need for minimal bundle size:

| Import Path | What You Get | ~Size | |---|---|---| | tailwind-to-style | tw, tws, cx | Full engine | | tailwind-to-style/react | styled, ThemeProvider, useTheme, useTws | +2KB | | tailwind-to-style/tokens | createTheme, tokenRegistry, token | +1KB | | tailwind-to-style/animations | animate, defineAnimation | +1.5KB | | tailwind-to-style/cx | cx only | ~300B | | tailwind-to-style/tws | tws only | Subset |


Framework Support

Works with any framework or vanilla JS:

  • React — Full bindings via tailwind-to-style/react (example available in examples/react-demo)
  • Vanilla JS — Direct DOM usage with tw() and tws()
  • Node.js / SSRtws() for inline styles + createSSRCollector() for CSS extraction
  • Vue / Svelte — supported in runtime with tw() / tws(), examples can be added in future releases

License

MIT © Bigetion