Installation

No package manager needed. Download chai.js and drop one script tag at the end of your body. That's the entire setup.

index.html
<!-- add at the very end of body -->
<script src="chai.js"></script>
Important: Always load chai.js as the last script tag. If you put it in <head>, the DOM won't be ready and nothing will be styled.
Verify it's working: Open DevTools console and run document.querySelectorAll('[style]').length — should return a number greater than 0.

How it works

chai.js runs once on DOMContentLoaded. It walks every element, parses chai-* class names, resolves them against a rules map, and injects inline styles.

chai.js — simplified
// 1. inject keyframes for animate-* utilities
injectKeyframes()

// 2. walk every element
document.querySelectorAll('*').forEach(el => {
  el.classList.forEach(cls => {
    if (!cls.startsWith('chai-')) return

    // 3. parse: chai-p-4 → prop: 'p', val: '4'
    const { prop, val } = parseClass(cls)

    // 4. look up rules map and apply
    const styles = rules[prop](val)
    Object.assign(el.style, styles)

    // 5. clean up the class
    el.classList.remove(cls)
  })
})

Quick start

A complete working example — a card built entirely with chai-* classes.

card.html
<div class="chai-bg-white chai-rounded-xl chai-shadow-lg chai-p-6 chai-w-full">
  <h2 class="chai-text-xl chai-font-bold chai-mb-2">Hello ChaiTailwind</h2>
  <p class="chai-text-sm chai-text-gray chai-mb-4">
    Utility-first CSS at runtime.
  </p>
  <button class="chai-bg-blue chai-text-white chai-px-4 chai-py-2
                  chai-rounded-lg chai-cursor-pointer chai-transition
                  chai-hover-bg-indigo">
    Get started
  </button>
</div>

<script src="chai.js"></script>
output after chai.js runs

Hello ChaiTailwind

Utility-first CSS at runtime.

Spacing

All spacing utilities use a 4px scale — chai-p-4 = padding: 16px. Supports 0–16 and beyond.

ClassCSS output
chai-p-{n}padding: n×4px
chai-px-{n}padding-left: n×4px; padding-right: n×4px
chai-py-{n}padding-top: n×4px; padding-bottom: n×4px
chai-pt/pb/pl/pr-{n}padding-top / bottom / left / right: n×4px
chai-m-{n}margin: n×4px
chai-mx-{n}margin-left: n×4px; margin-right: n×4px
chai-mx-automargin-left: auto; margin-right: auto
chai-my-{n}margin-top: n×4px; margin-bottom: n×4px
chai-mt/mb/ml/mr-{n}margin-top / bottom / left / right: n×4px
chai-gap-{n}gap: n×4px
chai-gap-x-{n}column-gap: n×4px
chai-gap-y-{n}row-gap: n×4px

Colors

Apply background and text colors using named colors or custom hex values.

ClassCSS output
chai-bg-{color}background-color: {value}
chai-text-{color}color: {value}
chai-bg-[#hexcode]background-color: #hexcode
chai-text-[#hexcode]color: #hexcode
chai-bg-[var(--x)]background-color: var(--x)

Named colors: red · blue · green · yellow · orange · purple · pink · gray · white · black · slate · teal · cyan · indigo · lime · amber · rose

Typography

ClassCSS output
chai-text-xsfont-size: 12px
chai-text-smfont-size: 14px
chai-text-basefont-size: 16px
chai-text-lgfont-size: 18px
chai-text-xlfont-size: 20px
chai-text-2xl/3xl/4xlfont-size: 24px / 30px / 36px
chai-font-boldfont-weight: bold
chai-font-semiboldfont-weight: 600
chai-font-normalfont-weight: normal
chai-font-italicfont-style: italic
chai-text-center/left/righttext-align: center / left / right
chai-uppercase/lowercase/capitalizetext-transform
chai-underlinetext-decoration: underline
chai-truncateoverflow: hidden; text-overflow: ellipsis; white-space: nowrap
chai-line-clamp-{n}-webkit-line-clamp: n
chai-tracking-tight/wide/widerletter-spacing
chai-leading-tight/normal/relaxed/looseline-height

Borders

ClassCSS output
chai-borderborder: 1px solid #d1d5db
chai-border-t/b/l/rborder-top / bottom / left / right
chai-border-2 / border-4border: 2px / 4px solid #d1d5db
chai-border-noneborder: none
chai-rounded-smborder-radius: 3px
chai-roundedborder-radius: 6px
chai-rounded-md/lg/xl/2xlborder-radius: 8px / 12px / 16px / 20px
chai-rounded-fullborder-radius: 9999px
chai-outline-noneoutline: none
chai-ringbox-shadow: 0 0 0 3px rgba(59,130,246,0.5)

Layout

ClassCSS output
chai-flexdisplay: flex
chai-block / chai-inline / chai-hiddendisplay: block / inline / none
chai-inline-flex / chai-inline-blockdisplay: inline-flex / inline-block
chai-griddisplay: grid
chai-grid-cols-{n}grid-template-columns: repeat(n, 1fr)
chai-flex-col / chai-flex-rowflex-direction: column / row
chai-flex-wrap / chai-flex-nowrapflex-wrap: wrap / nowrap
chai-flex-1 / chai-flex-auto / chai-flex-noneflex shorthand
chai-items-center/start/end/stretchalign-items
chai-justify-center/between/around/endjustify-content
chai-relative / chai-absolute / chai-fixed / chai-stickyposition
chai-z-{n}z-index: n
chai-inset-0top/right/bottom/left: 0

Hover states new

Since inline styles can't use :hover, chai.js attaches mouseenter/mouseleave event listeners instead. Prefix any utility with hover-.

example
<button class="chai-bg-black chai-text-white
               chai-hover-bg-blue chai-transition
               chai-px-6 chai-py-3 chai-rounded-lg">
  Hover me
</button>
Tip: Combine with chai-transition for smooth color changes on hover.

Group hover new

Mark a parent with chai-group. Any child with chai-group-hover-* will react when the parent is hovered.

example
<div class="chai-group chai-p-6 chai-bg-white chai-rounded-xl chai-cursor-pointer">
  <div class="chai-group-hover-bg-blue chai-rounded-full">
    icon
  </div>
  <h3 class="chai-group-hover-text-blue">
    Title
  </h3>
</div>

Responsive new

Prefix any utility with a breakpoint to apply it only above that width. Recalculates on window resize.

PrefixBreakpointExample
chai-sm-*≥ 640pxchai-sm-p-4
chai-md-*≥ 768pxchai-md-bg-blue
chai-lg-*≥ 1024pxchai-lg-text-xl
chai-xl-*≥ 1280pxchai-xl-hidden
example
<!-- red on mobile, blue at sm, green at md -->
<div class="chai-bg-red chai-sm-bg-blue chai-md-bg-green">
  Responsive background
</div>

Dark mode new

Prefix any utility with dark- to apply it only when the system is in dark mode. Reads prefers-color-scheme: dark on load.

example
<div class="chai-bg-white chai-text-black
           chai-dark-bg-black chai-dark-text-white
           chai-p-6 chai-rounded-xl">
  Adapts to system theme
</div>

Animations new

Keyframes are injected once into <head> by chai.js on load. No separate CSS file needed.

ClassEffect
chai-animate-spincontinuous 360° rotation
chai-animate-pingscale + fade out (like a radar ping)
chai-animate-pulseopacity fade in/out
chai-animate-bouncevertical bounce
chai-animate-fade-infade in from opacity 0
chai-animate-slide-upslide up + fade in
chai-animate-noneremoves animation

Transitions new

ClassCSS output
chai-transitiontransition: all 0.2s ease
chai-transition-colorstransition: color, background-color, border-color 0.2s
chai-transition-transformtransition: transform 0.2s ease
chai-duration-150/200/300/500transition-duration: 150ms / 200ms / 300ms / 500ms
chai-ease-in/out/in-outtransition-timing-function

Custom colors

Use square brackets to pass any hex code or CSS variable directly.

example
<!-- hex codes -->
<div class="chai-bg-[#ff6347] chai-text-[#ffffff]">Tomato</div>

<!-- CSS variables -->
<div class="chai-bg-[var(--brand-color)]">Brand color</div>

Known limitations

No :hover via inline styles — solved with JS event listeners. Works for most cases but won't work if JS is disabled.
No real media queries — responsive utilities use window.innerWidth checks on resize instead. Close enough for most projects.
No pseudo-elements — ::before and ::after can't be styled with inline styles. Use a real stylesheet for those.
Dark mode applies on load only — if the user switches themes mid-session, a page reload is needed to re-apply dark classes.