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

cssfun

v0.0.13

Published

Near-zero runtime CSS-in-JS library

Downloads

215

Readme

Write modular CSS within your JavaScript code with built-in themes and SSR support.

npm version npm package minimized gzipped size npm downloads jsDelivr hits (npm)

Key Features

  • Near-Zero Runtime
    Styles are generated when the module is initialized, rather than during component rendering. This eliminates runtime style generation, improving performance and reducing complexity.

  • Component-Scoped Styles
    CSSFUN scopes styles to the component, preventing style leakage and promoting modularity. It keeps both logic and styling in the same file for easier management.

  • Framework-Agnostic and Lightweight 🌐
    CSSFUN is compatible with any environment. At just 1.7KB, it adds minimal overhead to your projects.

  • No Build Tools Required 🛠️
    CSSFUN can be used directly in the browser, eliminating the need for complex build tools or configurations.

  • Server-Side Rendering (SSR) Support 🚀
    CSSFUN supports server-side rendering out of the box, optimizing initial load times without duplicating styles.

  • Built-in Theme Management 🎨
    With built-in theme support, CSSFUN uses CSS variables to manage light and dark color schemes. Themes update automatically based on user preferences, no re-renders needed.

Getting Started

Installing via npm

$ npm install cssfun
import { css } from 'cssfun';

Using ES modules

import { css } from 'https://esm.run/cssfun';

Using <script> tag

<script src="https://cdn.jsdelivr.net/npm/cssfun"></script>
const { css } = CSSFUN;

Create your styles

const { classes } = css({
    button : {
        backgroundColor : 'blue',
        color : 'white',
        padding : '10px',
        borderRadius : '5px'
    }
});

Apply the styles to your components:

const Button = () => <button className={classes.button}>Click me</button>;

Renderers

Renderers are functions that transform style objects into CSS strings.
These are the built-in renderers transformations:

Note: All examples below show class names generated in development mode.
In production, class names are optimized for smaller bundle size:

  • Development: .fun-9qkk9s-root { color: red; } (full prefix + class name)
  • Production: .f-9qkk9s-1{color:red;} (first letter of prefix + index)

Customize via options.generateClassName or by extending the class.

Camelized keys will be transformed to dashed keys

css({
    root : {
        backgroundColor : 'black'
    }
}).toString();
Renders to:
<style data-fun-uid="uwitok">
    .fun-uwitok-root {
        background-color: black;
    }
</style>

Nested selectors will be expanded

  • Use & to reference the selector of the parent rule

    css({
        button : {
            backgroundColor : 'white',
            '&:hover' : {
                backgroundColor : 'black'
            },
            '& span' : {
                color : 'blue'
            }
        }
    }).toString();
    Renders to:
    <style data-fun-uid="1pxyvx7">
        .fun-1pxyvx7-button {
            background-color: white;
        }
        .fun-1pxyvx7-button:hover {
            background-color: black;
        }
        .fun-1pxyvx7-button span {
            color: blue;
        }
    </style>
  • Deep nesting

    css({
        button : {
            backgroundColor : 'white',
            '&:active' : {
                backgroundColor : 'black',
                '&:hover' : {
                    backgroundColor : 'blue'
                }
            }
        }
    }).toString();
    Renders to:
    <style data-fun-uid="169vukw">
        .fun-169vukw-button {
            background-color: white;
        }
        .fun-169vukw-button:active {
            background-color: black;
        }
        .fun-169vukw-button:active:hover {
            background-color: blue;
        }
    </style>

Class references will be replaced by the generated class name

  • Use $ to reference a local class within the same StyleSheet instance

    css({
        button : {
            backgroundColor : 'white'
        },
        '$button:hover' : {
                backgroundColor : 'black'
            },
        '$button span' : {
            color : 'blue'
        }
    }).toString();
    Renders to:
    <style data-fun-uid="2xfpy0">
        .fun-2xfpy0-button {
            background-color: white;
        }
        .fun-2xfpy0-button:hover {
            background-color: black;
        }
        .fun-2xfpy0-button span {
            color: blue;
        }
    </style>

Global selectors will be rendered as global styles

  • Global block

    css({
        '@global' : {
            body : {
                backgroundColor : 'black'
            }
        }
    }).toString();
    Renders to:
    <style data-fun-uid="ml03n3">
        body {
            background-color: black;
        }
    </style>
  • Nested global block

    css({
        root : {
            '@global' : {
                a : {
                    color : 'black'
                }
            }
        }
    }).toString();
    Renders to:
    <style data-fun-uid="1eia2eq">
        .fun-1eia2eq-root a {
            color: black;
        }
    </style>
  • Global prefix

    css({
        '@global body' : {
            backgroundColor : 'black'
        }
    }).toString();
    Renders to:
    <style data-fun-uid="1p1av20">
        body {
            background-color: black;
        }
    </style>
  • Nested global prefix

    css({
        root : {
            '@global a' : {
                color : 'black'
            }
        }
    }).toString();
    Renders to:
    <style data-fun-uid="xvd6jj">
        .fun-xvd6jj-root a {
            color: black;
        }
    </style>

When composed, the first renderer receives the styles object, and the final one outputs the resulting CSS string.

Custom Renderers

You can customize the renderers by setting the renderers array on the StyleSheet instance. If passed via options.renderers, they will be automatically added to the instance.

Elements in the renderers array can be either functions or strings that reference methods of the StyleSheet instance. These methods will be bound to the instance before they are invoked.

By default, StyleSheet are rendered using the built-in renderers: [this.renderStyles, this.parseStyles].

Themes

A theme is a StyleSheet that provides access to CSS variables for consistent styling across your application. It supports multiple color schemes, including light, dark, light dark (default, adapts to system preferences), and normal. Themes allow your components to automatically adapt to changes in the user's system preferences or use a fixed color scheme.

The createTheme function generates a theme StyleSheet instance. It accepts a themes object, which defines variables for the specified color schemes, and an options object to customize the theme generation.
Each key in the themes object corresponds to a color scheme (light, dark, normal), and its value is an object of key-value pairs that will be converted into CSS variables.

Creating a Theme

Define styles for light and dark color schemes using the createTheme function.

const theme = createTheme({
    light : {
        colorPrimary : 'black',
        backgroundLevel1 : 'white'
    },
    dark : {
        colorPrimary : 'white',
        backgroundLevel1 : 'black'
    }
});

Customizing the Theme

Color Scheme

The options.colorScheme parameter specifies which color scheme(s) to use. Possible values are:

  • light: Uses the light theme only.
  • dark: Uses the dark theme only.
  • light dark (default): Supports both light and dark themes, adapting to system preferences. You can override the system preference by setting the data-color-scheme attribute to light or dark on a parent element.
  • normal: Uses the normal theme only.

CSS Variables Prefix

The options.cssVarsPrefix parameter allows you to customize the prefix for the generated CSS variables. By default, the prefix is fun. For example, a key colorPrimary in the theme will generate a CSS variable like --fun-colorPrimary.

Applying the Theme Class

The generated theme includes a root class, which exposes all the theme's CSS variables to any element that uses this class and its descendants. You can apply this class to the body element to style the entire application, or to the root element of a specific component to apply the theme to just part of your UI.

// Add theme class to the body
document.body.classList.add(theme.classes.root);

Using Theme Variables in Styles

The themes object is automatically converted into CSS variables. For example:

{ backgroundLevel1 : 'black' }

is converted into the CSS variable --fun-backgroundLevel1.

Nested structures like:

{
    palette : {
        common : { 
            black : '#000'
        }
    }
}

are converted into --fun-palette-common-black.

You can use these variables in your component styles, even before the theme is applied. Your components will automatically update when the theme or system color scheme changes.

const { classes } = css({
    button : {
        color : 'var(--fun-colorPrimary)',
        backgroundColor : 'var(--fun-backgroundLevel1)'
    },
});

const Button = ({ label }) => <button className={classes.button}>{label}</button>;

Server-Side Rendering (SSR)

Easily add your styles to the server-rendered HTML by embedding the StyleSheets as a string within the <head> of your page.

import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { StyleSheet, createTheme } from 'cssfun';
import App from './App.js';

// Create a theme with light and dark modes
const theme = createTheme({
    light : {
        bg : '#fff',
        color : '#000'
    },
    dark : {
        bg : '#000',
        color : '#fff'
    }
});

const app = express();

app.get('*', (req, res) => {
    // Render the app
    const html = renderToString(<App />);

    // Get generated styles as string
    const styles = StyleSheet.toString();
    
    // Get theme root class
    const cls = theme.classes.root;

    const template = `
        <!DOCTYPE html>
        <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>SSR App</title>
                ${styles}
            </head>
            <body class="${cls}">
                <div id="root">${html}</div>
                <script src="/bundle.js"></script>
            </body>
        </html>
    `;

    res.send(template);
});

When the app is hydrated on the client side, the styles are preserved and won’t be recreated.

API Documentation

Complete API documentation can be found here.

Examples

The examples folder contains various sample projects demonstrating how to use CSSFUN in different environments and frameworks. Each example is a standalone project that you can run locally to see CSSFUN in action.

Available Examples

  • React Example: A basic React application demonstrating the use of CSSFUN for styling React components. Try it.
  • Rasti Example: A simple Rasti application illustrating how to apply CSSFUN to style Rasti components. Try it.
  • Vanilla JS Example: A straightforward JavaScript example showing how to use CSSFUN for styling HTML components. Try it.

License

CSSFUN is open-source and available under the MIT License.

Contributing

Contributions are welcome! Share feature ideas or report bugs on our GitHub Issues page.