@chakrabortyrajarshi2005/chai-tailwind-css
v1.0.1
Published
A lightweight utility-class CSS engine. Write chai- classes, get real CSS.
Maintainers
Readme
☕ chai-css
A lightweight, zero-dependency, custom Tailwind-like CSS engine you build yourself. Write
chai-classes in your HTML — get real CSS applied at runtime.
<div class="chai-bg-slate-950 chai-px-24 chai-py-16 chai-rounded-12 chai-text-indigo-400">
Hello from chai ☕
</div>What is chai-css?
chai-css is a DIY utility-class CSS engine inspired by Tailwind CSS. Instead of a build step or a CDN stylesheet, chai works by:
- Scanning the DOM for any element with a
chai-class - Parsing the class name into a
{ property, value }pair - Applying the CSS directly to the element as an inline style
No compiler. No config file. No stylesheet to ship. Just your JavaScript engine + your HTML.
Project Structure
your-project/
├── index.html
├── src/
│ └── main.js ← entry point (run chai here)
└── config/
└── propertyMap.js ← all shorthand keys + color paletteThe engine itself lives in four files:
src/
├── main.js ← entry point: connects everything
├── scanner.js ← finds all chai- elements in the DOM
├── parser.js ← breaks "chai-bg-red-500" into { property, value }
└── apply.js ← sets the actual CSS on the elementHow It Works
1. scanner.js — Find
Walks every element in the DOM and collects any class starting with chai-.
// Returns: [{ element: <div>, className: "chai-bg-red-500" }, ...]
scan()2. parser.js — Parse
Splits the class name into a property key and a value.
"chai-bg-red-500" → { property: "bg", value: "red-500" }
"chai-px-16" → { property: "px", value: "16" }
"chai-rounded-8" → { property: "rounded", value: "8" }
"chai-gridCols-3" → { property: "gridCols", value: "3" }The parser tries each possible split point left-to-right and picks the first one where the property key exists in propertyMap. This correctly handles color names like red-500 that contain a dash.
3. apply.js — Apply
Looks up the CSS property in propertyMap, resolves the value, and sets it.
"bg" → "backgroundColor" → element.style.backgroundColor = "#ef4444"
"px" → ["paddingLeft","paddingRight"] → sets both at once
"text" → "color" → element.style.color = "#3b82f6"Value resolution order:
- Color name? (
red-500) → look up hex incategoryGroups.colors - Already has a unit? (
2rem,50%) → use as-is - Keyword? (
auto,flex,none) → use as-is - Plain number? (
16,8) → appendpxautomatically - Anything else → use as-is (hex codes, CSS vars, etc.)
4. main.js — Run
import { scan } from "./scanner.js";
import { parse } from "./parser.js";
import { applyStyle } from "./apply.js";
function run() {
scan().forEach(item => applyStyle(item.element, parse(item.className)));
}
document.readyState === "loading"
? document.addEventListener("DOMContentLoaded", run)
: run();Class Syntax
chai-{property}-{value}| Part | Example | What it is |
|---|---|---|
| chai- | always | required prefix |
| {property} | bg, px, rounded | key from propertyMap |
| {value} | red-500, 16, auto | color name, number, or keyword |
Property Reference
Spacing
| Class | CSS Property |
|---|---|
| chai-p-{n} | padding |
| chai-px-{n} | paddingLeft + paddingRight |
| chai-py-{n} | paddingTop + paddingBottom |
| chai-pt-{n} | paddingTop |
| chai-pb-{n} | paddingBottom |
| chai-pl-{n} | paddingLeft |
| chai-pr-{n} | paddingRight |
| chai-m-{n} | margin |
| chai-mx-{n} | marginLeft + marginRight |
| chai-my-{n} | marginTop + marginBottom |
| chai-mt-{n} | marginTop |
| chai-mb-{n} | marginBottom |
| chai-ml-{n} | marginLeft |
| chai-mr-{n} | marginRight |
| chai-gap-{n} | gap |
| chai-gapX-{n} | columnGap |
| chai-gapY-{n} | rowGap |
Sizing
| Class | CSS Property |
|---|---|
| chai-w-{n} | width |
| chai-h-{n} | height |
| chai-size-{n} | width + height |
| chai-minW-{n} | minWidth |
| chai-maxW-{n} | maxWidth |
| chai-minH-{n} | minHeight |
| chai-maxH-{n} | maxHeight |
Colors
| Class | CSS Property |
|---|---|
| chai-bg-{color} | backgroundColor |
| chai-text-{color} | color |
| chai-fill-{color} | fill |
| chai-stroke-{color} | stroke |
| chai-borderColor-{color} | borderColor |
| chai-outlineColor-{color} | outlineColor |
| chai-accentColor-{color} | accentColor |
| chai-caretColor-{color} | caretColor |
Typography
| Class | CSS Property |
|---|---|
| chai-fontSize-{n} | fontSize |
| chai-fontWeight-{n} | fontWeight |
| chai-fontStyle-{v} | fontStyle |
| chai-lineHeight-{n} | lineHeight |
| chai-letterSpacing-{n} | letterSpacing |
| chai-textAlign-{v} | textAlign |
| chai-textTransform-{v} | textTransform |
| chai-textDecor-{v} | textDecoration |
| chai-textOverflow-{v} | textOverflow |
| chai-whiteSpace-{v} | whiteSpace |
| chai-lineClamp-{n} | -webkit-line-clamp |
| chai-wordBreak-{v} | wordBreak |
Borders & Radius
| Class | CSS Property |
|---|---|
| chai-border-{v} | border |
| chai-borderW-{n} | borderWidth |
| chai-borderStyle-{v} | borderStyle |
| chai-borderColor-{color} | borderColor |
| chai-rounded-{n} | borderRadius |
| chai-roundedT-{n} | top-left + top-right radius |
| chai-roundedB-{n} | bottom-left + bottom-right radius |
| chai-roundedTL-{n} | borderTopLeftRadius |
| chai-roundedTR-{n} | borderTopRightRadius |
| chai-roundedBL-{n} | borderBottomLeftRadius |
| chai-roundedBR-{n} | borderBottomRightRadius |
Layout & Display
| Class | CSS Property |
|---|---|
| chai-d-{v} | display |
| chai-pos-{v} | position |
| chai-overflow-{v} | overflow |
| chai-overflowX-{v} | overflowX |
| chai-overflowY-{v} | overflowY |
| chai-z-{n} | zIndex |
| chai-opacity-{n} | opacity |
| chai-visibility-{v} | visibility |
| chai-cursor-{v} | cursor |
| chai-objectFit-{v} | objectFit |
Flexbox
| Class | CSS Property |
|---|---|
| chai-flex-{v} | flex |
| chai-flexDir-{v} | flexDirection |
| chai-flexWrap-{v} | flexWrap |
| chai-flexGrow-{n} | flexGrow |
| chai-flexShrink-{n} | flexShrink |
| chai-flexBasis-{n} | flexBasis |
| chai-alignItems-{v} | alignItems |
| chai-alignSelf-{v} | alignSelf |
| chai-alignContent-{v} | alignContent |
| chai-justifyContent-{v} | justifyContent |
| chai-justifyItems-{v} | justifyItems |
| chai-justifySelf-{v} | justifySelf |
| chai-placeItems-{v} | placeItems |
| chai-order-{n} | order |
Grid
| Class | CSS Property |
|---|---|
| chai-gridCols-{v} | gridTemplateColumns |
| chai-gridRows-{v} | gridTemplateRows |
| chai-gridArea-{v} | gridArea |
| chai-gridAutoFlow-{v} | gridAutoFlow |
| chai-colStart-{n} | gridColumnStart |
| chai-colEnd-{n} | gridColumnEnd |
| chai-rowStart-{n} | gridRowStart |
| chai-rowEnd-{n} | gridRowEnd |
Position
| Class | CSS Property |
|---|---|
| chai-top-{n} | top |
| chai-bottom-{n} | bottom |
| chai-left-{n} | left |
| chai-right-{n} | right |
| chai-inset-{n} | inset |
| chai-insetX-{n} | left + right |
| chai-insetY-{n} | top + bottom |
| chai-z-{n} | zIndex |
Transforms & Transitions
| Class | CSS Property |
|---|---|
| chai-transform-{v} | transform |
| chai-rotate-{v} | rotate |
| chai-scale-{v} | scale |
| chai-translate-{v} | translate |
| chai-transition-{v} | transition |
| chai-duration-{n} | transitionDuration |
| chai-delay-{n} | transitionDelay |
| chai-ease-{v} | transitionTimingFunction |
Shadow & Filter
| Class | CSS Property |
|---|---|
| chai-shadow-{v} | boxShadow |
| chai-filter-{v} | filter |
| chai-backdropFilter-{v} | backdropFilter |
| chai-blur-{v} | filter |
| chai-opacity-{n} | opacity |
Color Palette
chai includes the full Tailwind color palette with shades from 50 to 950.
Available color families:
slate · gray · zinc · neutral · stone · red · orange · amber · yellow · lime · green · emerald · teal · cyan · sky · blue · indigo · violet · purple · fuchsia · pink · rose
Usage:
chai-bg-{color}-{shade}
chai-text-{color}-{shade}
chai-borderColor-{color}-{shade}Examples:
<div class="chai-bg-blue-500"> <!-- backgroundColor: #3b82f6 -->
<p class="chai-text-rose-400"> <!-- color: #fb7185 -->
<hr class="chai-bg-slate-200"> <!-- backgroundColor: #e2e8f0 -->Special values: black, white, transparent, current
Value Rules
| Value type | Example | What chai does |
|---|---|---|
| Plain number | 16, 8, 24 | Appends px → 16px |
| Number with unit | 1.5rem, 50%, 100vh | Used as-is |
| Color name | red-500, indigo-400 | Resolved to hex → #ef4444 |
| Keyword | auto, flex, none, center | Used as-is |
| Raw hex | #ff0000 | Used as-is |
Examples
Card component
<div class="
chai-bg-slate-800
chai-px-24 chai-py-20
chai-rounded-16
chai-shadow-lg
">
<h2 class="chai-text-white chai-fontSize-20 chai-fontWeight-700 chai-mb-8">
Title
</h2>
<p class="chai-text-slate-400 chai-fontSize-14 chai-lineHeight-1.6">
Some description text here.
</p>
</div>Flex row
<div class="chai-d-flex chai-alignItems-center chai-justifyContent-between chai-gap-16">
<span class="chai-text-slate-300 chai-fontSize-14">Label</span>
<button class="chai-bg-indigo-600 chai-text-white chai-px-16 chai-py-8 chai-rounded-8">
Action
</button>
</div>Responsive-ish sizing
<img
class="chai-w-100 chai-h-200 chai-objectFit-cover chai-rounded-12"
src="photo.jpg"
alt="Photo"
/>Dark badge
<span class="
chai-bg-indigo-950
chai-text-indigo-300
chai-fontSize-11
chai-px-10 chai-py-4
chai-rounded-100
chai-letterSpacing-0.08em
chai-textTransform-uppercase
">
New
</span>Setup with Vite
<!-- index.html -->
<body>
<div class="chai-bg-slate-950 chai-px-32 chai-py-24">
<h1 class="chai-text-white chai-fontSize-32 chai-fontWeight-800">
Hello chai ☕
</h1>
</div>
<script type="module" src="./src/main.js"></script>
</body>// src/main.js
import { scan } from "./scanner.js";
import { parse } from "./parser.js";
import { applyStyle } from "./apply.js";
function run() {
scan().forEach(item => applyStyle(item.element, parse(item.className)));
}
document.readyState === "loading"
? document.addEventListener("DOMContentLoaded", run)
: run();Then run:
npm create vite@latest my-app -- --template vanilla
cd my-app
npm install
npm run devExtending chai
Add a new property shorthand
Open config/propertyMap.js and add your key:
export const propertyMap = {
// ...existing properties...
// your new ones:
trackColor: "scrollbarColor",
txtSize: "fontSize",
bd: ["borderLeft", "borderRight", "borderTop", "borderBottom"],
};Now chai-trackColor-slate-500 and chai-txtSize-18 work immediately.
Add a custom color
Open config/propertyMap.js and add to categoryGroups.colors:
export const categoryGroups = {
// ...
colors: {
// ...existing colors...
"brand": "#your-hex",
"brand-light":"#your-light-hex",
"brand-dark": "#your-dark-hex",
}
};Now chai-bg-brand and chai-text-brand-light work.
Limitations
Since chai applies inline styles, it cannot handle:
- Pseudo-classes like
:hover,:focus,:nth-child— use a<style>block for these - Media queries — add responsive logic manually in JS if needed
- CSS variables — you can pass them as values (
chai-color-var(--my-color)) but they must already be defined - Complex values with spaces — e.g.
chai-shadow-0 2px 8px blackwon't parse — define these in a<style>block
File Overview
| File | Purpose |
|---|---|
| config/propertyMap.js | All shorthand keys → CSS properties + color palette |
| src/scanner.js | Finds all chai- elements in the DOM |
| src/parser.js | Parses "chai-bg-red-500" into { property, value } |
| src/apply.js | Resolves values and sets element.style |
| src/main.js | Runs the engine on page load |
| index.html | Your HTML — use chai- classes here |
License
MIT — build whatever you want with it. ☕
