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-runtime

v0.0.1

Published

Tailwind runtime, access values and convert classes to styles

Downloads

1

Readme

Tailwind Runtime

Interact with a tailwindcss 4.x bundle at runtime using the CSS Object Model APIs:

  • Convert tailwind class names to style objects and inline css
  • Substitutes var() and simplifies some calc()
  • Performs calculations without the DOM, never triggers a reflow
  • Supports variants and pseudo classes like hover:, etc
  • Tiny, zero dependencies, typescript support

Note: Tailwind runtime is not a JIT compiler, it uses tailwind's output as its source of knowlege, so any classes or values not being generated by your existing tailwind configuration will not be available.

Install from npm:

npm i tailwind-runtime

Examples

Set up, automatically finding tailwind in the document:

import { TailwindRuntime } from 'tailwind-runtime';

const tw = new TailwindRuntime();

Set up, providing a stylesheet containing a tailwind build:

import { TailwindRuntime } from 'tailwind-runtime';

const tw = new TailwindRuntime({
  tailwind: document.styleSheets[0],
});

Convert class names to a style object or inline css, the order of class names doesn't matter and will be sorted:

tw.toObject('px-8 m-4 scale-50');
// -> {margin: '1rem', scale: '50% 50%', paddingInline: '2rem'}

tw.toCSS('px-8 m-4 scale-50');
// -> 'margin: 1rem; scale: 50% 50%; padding-inline: 2rem;'

Simulate states to get variant styles:

const names = 'text-black m-auto hover:text-white';

tw.toObject(names, []);
// -> {margin: 'auto', color: '#000'}

tw.toObject(names, ['hover']);
// -> {margin: 'auto', color: '#fff'}

Tailwind runtime doesn't care about conditionals like selectors and media queries, all variants are explicit. This is intentional because inline styles can't have variants, and lets you simulate different states for testing. For example here the second rule won't apply unless you tell it to, even though [*] is a variant that should match all elements:

tw.toCSS('p-[1em] [*]:p-[2em]');
// -> 'padding: 1em;'

tw.toCSS('p-[1em] [*]:p-[2em]', ['[*]']);
// -> 'padding: 2em;'

The final boolean parameter for toObject and toCSS will only include classes that explicitly match the given state, useful for seperating class names by state:

const names = 'text-left p-4 hover:text-right';

tw.toCSS(names, ['hover'], true);
// -> 'text-align: right;'

Find theme values:

tw.getValue('--blur-md');
// -> '12px'

tw.getValue('--spacing');
// -> '0.25rem'

Access theme namespaces as objects by creating proxies:

const fonts = tw.themeNamespace('font-weight');
const aspectRatios = tw.themeNamespace('aspect');

Object.keys(fonts);
// -> ['thin', 'extralight', 'light', 'normal', 'medium', 'semibold', 'bold', 'extrabold', 'black']

aspectRatios['video'];
// -> '16 / 9'

Breakpoint and colour namespaces are available through shortcuts:

Object.entries(tw.breakpoints);
// -> [['sm', '40rem'], ['md', '48rem'], ['lg', '64rem'], ['xl', '80rem'], ['2xl', '96rem']]

Object.keys(tw.colors).length;
// -> 244

Find the subset of known breakpoints that are currently active based on the viewport width:

tw.activeBreakpoints;
// -> ['sm', 'md', 'lg']

const names = 'p-[1em] md:p-[2em] lg:p-[3em] ';

tw.toCSS(names, tw.activeBreakpoints);
// -> 'padding: 3em;'

Variables and properties

Tailwind runtime tries to allow weird use cases and has logic for forwarding or removing substituted variable values based on tailwind's custom property definitions. Here are a few edge case examples you shouldn't need to worry about unless you're doing something cursed.

We try to substitute local versions of variables, but keep their definitions in the output unless tailwind defines a property marking them as not inherited:

tw.toCSS('hover:[--color-white:#f00] text-white');
// -> 'color: #fff;'

tw.toCSS('hover:[--color-white:#f00] text-white', ['hover']);
// -> 'color: #f00; --color-white: #f00;'

Notice though how even though tailwind's scale utilities use variables internally, their definitions are removed after substitution because they're marked as not inherited by @property rules:

tw.findUtilityRule('scale-90').cssText;
// -> '.scale-90 { --tw-scale-x: 90%; --tw-scale-y: 90%; --tw-scale-z: 90%; scale: var(--tw-scale-x) var(--tw-scale-y); }'

tw.toCSS('scale-90');
// -> 'scale: 90% 90%;'

As of 4.0, tailwind doesn't generate a @property rule for the --tw-drop-shadow variable used by filter utilities unless drop-shadow utilities are also explicitly used, so even though many other variables get hidden by tailwind runtime, this one will still be forwarded because it could be set elsewhere:

tw.getValue('--blur-md');
// -> '12px'

tw.findUtilityRule('blur-md').cssText;
// -> '.blur-md { --tw-blur: blur(var(--blur-md)); filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); }'

tw.findUtilityRule('grayscale').cssText;
// -> '.grayscale { --tw-grayscale: grayscale(100%); filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); }'

tw.toCSS('blur-md grayscale');
// -> 'filter: blur(12px) grayscale(100%) var(--tw-drop-shadow,);'

Importantly though, all of this information comes from your tailwind build, so any changes to these semantics between versions should be reflected here automatically.