/ x / clazzx@0.0.2

src3 KB
mod.ts80 B
.github2 MB
.gitignore12 B



ClazzX is a small (< 1kb gzipped) typesafe utility library for composing HTML classes. Unlike Vanilla Extract, Stitches, or CVA (all fantastic options) ClazzX takes a different approach, using state rather than variants to compose styles.

The classic approach is to create a series of variants that can be selected:

className={myButton({size: "small", intent="primary"})}
// AND
<Button size="small" intent="primary" />

In comparison, ClazzX models combinations of styles based on state.

className={myButton.classes({small: true, primary: true})}
// AND
<Button small primary />

This simplifies the logic of tying the styling of a component to complex state. Instead of a series of nested ternary operators, simple logical operators can be used to clearly define the appropriate styles.

    primary: true,
    loading: isLoading,
    error: isError 
<Button primary loading={isLoading} error={isError}>

// Versus

intent=isLoading ? "loading" 
: isError ? "error" 
: "primary"
// AND
<Button intent={isLoading ? "loading" : isError ? "error" : "primary"}>


// Deno
import {Style, clx} from ""
// NPM
npm i 'clazzx'
// Yarn
yarn add 'clazzx'

Getting Started

A basic component

import { Style } from 'clazzx'

const MyCustomStyle exends Style {
    // the base class will always be applied
    base = "border rounded-md font-sans"

    small = "px-2 py-1 text-sm"
    md = "px-3 py-2 text-base"
    lg = "px-4 py-3 text-lg"

    // you can use both strings and string arrays freely
    primary = [
    secondary = [

const input = new MyCustomStyle()

function MyCustomComponent(){
    return <input className={input.classes({ md: true, secondary: true })}/>

Default Classes

You can set default classes that are applied if nothing is passed th the classes method.

default = [, this.secondary, "hover:scale-105"]


If you want to conditionally apply styles when two or more states are true, you can create compound states.

compounds = [
        state: ["primary", "large"],
        classes: "shadow-md" // will only be applied if both states are true

Constructor options

The constructor takes in an options object with the following properties:

  • before: string | string[]: Classes to be applied before the conditional classes.
  • after: string | string[]: Classes to be applied after the conditional classes.


Classes are applied in the order of the states.

className={btn.classes({rounded: true, square: true})}
// className="border-md border-none"
<Button primary secondary small medium>
// className="bg-primary bg-secondary text-sm text-md"

The order of classes works like this:

  1. Base
  2. Constructor before
  3. ...order based on state || default classes
  4. Compounds
  5. Constructor after


StyleProps is an exported type that gives you access to the parameters of the style class. You can use this to strongly type components.

function MyButton({...props}: StyleProps<MyStyleClass>){}



import {Style, StyleProps} from "clazzx"

class LinkStyles extends Style {
    base: "font-link no-underline transition duration-200"

    primary: "text-link hover:text-link-hover"
    secondary: "text-secondary hover:text-secondary-hover"
    active: "text-active hover:text-active-hover underline"

    default = this.primary
const link = new MyCustomLink()

interface Link {
    children: ReactNode 
    props: StyleProps<MyCustomLink> & HTMLAttributes<HTMLAnchorElement>

function Link({children, ...props}: Link){
    return <a {...props} className={link.classes({...props})}>{children}</a>

function App(){
    const router = useRouter()
    // ...
    return (
        // ...
        <Link href="/about" secondary active={router.isCurrentPage}>
            My Link
        // ...

... more coming soon

ClazzX is a small typesafe utility library for composing HTML classes.
GitHub RepositoryB3nten/clazzx
GitHub Stars

Version Info

Tagged at
2 months ago