SantyCSS is a utility-first framework where class names describe what they do — in words you already know. No cryptic abbreviations, no lookup tables.
Same power. Human-readable names.
<div class="p-6 mt-4 flex items-center justify-between border-l-4 border-blue-500 rounded-xl shadow-lg text-xl font-semibold hover:scale-105 transition-all">
<div class="add-padding-24 add-margin-top-16 make-flex align-center justify-between add-border-left-4 border-color-blue-500 round-corners-12 add-shadow-lg set-text-20 text-semibold on-hover:scale-105 transition-normal">
AI tools like Claude, ChatGPT, and Copilot write CSS every day — but they default to Tailwind or Bootstrap. SantyCSS is different: its class names are the documentation.
Class names like make-flex align-center are self-documenting. Any AI can generate, read, and modify SantyCSS without a lookup table.
Paste santycss.context.md into Claude, GPT-4, or Cursor system prompt and the AI generates SantyCSS instead of Tailwind — every time.
AI-generated code should just work. Link one CSS file and use 8,500+ classes — no Webpack, no PostCSS, no config. Paste AI output directly into your HTML.
The built-in AI Generator turns plain English into ready-to-use SantyCSS classes instantly — right in the browser, no API key required.
Try the generator ↓A complete design system in one file.
Class names are full descriptive words. add-border-left-20 does exactly what it says — no memorization needed.
Drop santy.css into any project and start building. No Node, no config, no CLI tools needed.
Prefix any class with on-mobile:, on-tablet:, md:, lg: for responsive design.
Hover, focus, active, disabled states with intuitive prefixes like on-hover: and on-focus:.
20 color families × 10 shades each for text, background, border, fill, and stroke. Plus dark mode variants.
Pre-built components: .btn, .card, .input, .badge, .alert, .spinner, and more.
One line. That's it.
# Install npm install santycss # Option A — Import full CSS (React / Vue / Vite / Next.js) import 'santycss/css'; # Option B — Import individual parts import 'santycss/css/core'; import 'santycss/css/components'; import 'santycss/css/animations'; # Option C — In CSS / SCSS @import 'santycss/dist/santy.css'; # Option D — Resolve path (webpack / rollup config) const santy = require('santycss'); // santy.css → absolute path to dist/santy.css // santy.core → absolute path to dist/santy-core.css // santy.components → absolute path to dist/santy-components.css
Drop one line into any HTML file — no download, no npm, works instantly anywhere.
<!-- jsDelivr (recommended, global CDN) --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy.min.css"> <!-- Version-pinned (best for production) --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss@1.3.1/dist/santy.min.css"> <!-- unpkg --> <link rel="stylesheet" href="https://unpkg.com/santycss/dist/santy.css"> <!-- Load only components via CDN --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-core.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-components.css">
<!-- In your <head> --> <link rel="stylesheet" href="santy.css">
Split CSS into 3 independent files. Load only the parts your page needs for optimal performance.
<!-- Utilities only (layout, spacing, colors, typography) --> <link rel="stylesheet" href="santy-core.css"> <!-- Components only (btn, card, modal, drawer, table…) --> <link rel="stylesheet" href="santy-components.css"> <!-- 70+ animations — only when you need them --> <link rel="stylesheet" href="santy-animations.css">
<div class="container add-padding-y-48"> <!-- A card --> <div class="card add-padding-32 add-shadow-md"> <h1 class="set-text-32 text-bold color-gray-900">Hello SantyCSS</h1> <!-- Border example --> <div class="add-border-left-4 border-color-blue-500 add-padding-left-16 add-margin-y-24"> Border on the left, 4px wide. </div> <!-- Button --> <button class="btn btn-primary on-hover:scale-105 transition-normal"> Click me </button> </div> </div>
Drop-in for every major JS framework. Purge works exactly like Tailwind.
1. Copy santy.css into your project
your-app/
public/
santy.css ← copy here
src/
app/
layout.js2. Import in layout.js (App Router) or _app.js
// app/layout.js (Next.js 13+) import '../public/santy.css' export default function RootLayout({ children }) { return ( <html> <body>{children}</body> </html> ) }
3. Purge at build time — postcss.config.js
const santycss = require('santycss/postcss') module.exports = { plugins: [ santycss({ content: ['./src/**/*.{js,jsx,ts,tsx}', './app/**/*.{js,jsx,ts,tsx}'], safelist: ['make-hidden', 'animate-spin'], // always keep these }), ], } // Result: 723 KB → ~15 KB in production automatically
4. Use in components
export default function Card({ title, badge }) { return ( <div className="card add-padding-24 on-hover:add-shadow-lg transition-normal"> <h2 className="set-text-20 text-semibold color-gray-900">{title}</h2> <span className="badge background-blue-100 color-blue-700">{badge}</span> <button className="btn btn-primary add-margin-top-16">Go</button> </div> ) }
✦ Typical real-world page using 50–150 classes. Actual size varies by usage. Same order of magnitude as Tailwind's purged output.
A complete, honest breakdown across Tailwind, Bootstrap, Material UI, Bulma, Foundation & Chakra UI.
| Feature | SantyCSS | Tailwind | Bootstrap | Material UI | Bulma | Foundation |
|---|
Not available out-of-the-box in any other framework.
Not available in Tailwind without plugins or custom config.
All other frameworks use abbreviated or cryptic names. SantyCSS reads like English — no memorising abbreviations.
Every px from 0–200 is pre-generated. Bootstrap uses rem steps. Tailwind needs [20px] for custom values.
Bootstrap has 0, Tailwind has 4, Bulma has 0. SantyCSS ships 120+ — fades, bounces, slides, zooms, flips, scroll-triggered, stagger, and more.
Tailwind and Chakra require Node + bundler. Bootstrap requires PostCSS for customisation. SantyCSS works instantly.
Split CSS into 3 separate files so you can load only what a page needs. No other utility framework offers this.
Bootstrap ships spinners. Tailwind, Bulma, Foundation ship nothing. SantyCSS ships skeleton loaders, spinners, and progress bars.
State prefixes read like English. Responsive prefixes describe the viewport in words, not breakpoint codes.
SantyCSS works in every mode — CDN link, JIT runtime, PostCSS plugin, Vite plugin, or CLI purge. No other framework covers all these without plugins.
All missing from Tailwind and most others. SantyCSS ships text-shadow, Material elevation levels, and single-class absolute centering.
text-shadow
Five intuitive patterns. Read once, use forever.
add-{property}-{value} — Additive utilitiesUsed for properties that you're adding/applying: padding, margin, border, shadow.
make-{value} — Behavioral / displayChanges what an element is or how it behaves.
set-{property}-{value} — Size / value settersAssigns a specific numeric value to a dimension or font-size.
pin-{side}-{value} — PositioningPositions an absolute/fixed element by anchoring it to a side.
{state}:{class} — State & responsive variantsPrefix any class with a state or breakpoint to scope its effect.
The full class name catalogue, organized by category.
Replace {n} with any pixel value from 0–200 (every 1px up to 50, then every 4px), plus larger values like 256, 320, 384, 448, 512, 640, 768, 1024.
| Class | CSS Output | Description |
|---|---|---|
| add-padding-{n} | padding: {n}px | All sides |
| add-padding-top-{n} | padding-top: {n}px | Top only |
| add-padding-bottom-{n} | padding-bottom: {n}px | Bottom only |
| add-padding-left-{n} | padding-left: {n}px | Left only |
| add-padding-right-{n} | padding-right: {n}px | Right only |
| add-padding-x-{n} | padding-left + right: {n}px | Horizontal axis |
| add-padding-y-{n} | padding-top + bottom: {n}px | Vertical axis |
| add-margin-{n} | margin: {n}px | All sides |
| add-margin-top-{n} | margin-top: {n}px | Top only |
| add-margin-bottom-{n} | margin-bottom: {n}px | Bottom only |
| add-margin-left-{n} | margin-left: {n}px | Left only |
| add-margin-right-{n} | margin-right: {n}px | Right only |
| add-margin-x-{n} | margin-left + right: {n}px | Horizontal |
| add-margin-y-{n} | margin-top + bottom: {n}px | Vertical |
| add-margin-x-auto | margin-left: auto; margin-right: auto | Center horizontally |
| center-margin | margin: 0 auto | Center block element |
| subtract-margin-{n} | margin: -{n}px | Negative margin |
| gap-{n} | gap: {n}px | Flex/grid gap |
| gap-x-{n} | column-gap: {n}px | Column gap only |
| gap-y-{n} | row-gap: {n}px | Row gap only |
Live Demo
Border widths: 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 28, 32, 40, 48px
| Class | CSS Output | Notes |
|---|---|---|
| add-border-{n} | border: {n}px solid | All sides |
| add-border-top-{n} | border-top: {n}px solid | Top |
| add-border-bottom-{n} | border-bottom: {n}px solid | Bottom |
| add-border-left-{n} | border-left: {n}px solid | Left |
| add-border-right-{n} | border-right: {n}px solid | Right |
| add-border-x-{n} | border-left + right: {n}px solid | Horizontal |
| add-border-y-{n} | border-top + bottom: {n}px solid | Vertical |
| border-color-{name}-{shade} | border-color: {hex} | e.g. border-color-blue-500 |
| border-solid / dashed / dotted / double | border-style: … | Border style |
| round-corners-{n} | border-radius: {n}px | 0–128px |
| make-circle | border-radius: 50% | Perfect circle |
| make-pill | border-radius: 9999px | Pill/capsule shape |
| round-top-{n} | border-top-left/right-radius: {n}px | Top corners |
| round-bottom-{n} | border-bottom-left/right-radius: {n}px | Bottom corners |
| round-left-{n} | border-top/bottom-left-radius: {n}px | Left corners |
| round-right-{n} | border-top/bottom-right-radius: {n}px | Right corners |
Live Demo
| Class | CSS Output |
|---|---|
| set-text-{n} | font-size: {n}px (8–144) |
| text-thin | font-weight: 100 |
| text-extra-light | font-weight: 200 |
| text-light | font-weight: 300 |
| text-normal | font-weight: 400 |
| text-medium | font-weight: 500 |
| text-semibold | font-weight: 600 |
| text-bold | font-weight: 700 |
| text-extra-bold | font-weight: 800 |
| text-black-weight | font-weight: 900 |
| text-italic / text-not-italic | font-style: italic / normal |
| font-sans / font-serif / font-mono | System font stacks |
| text-left / center / right / justify | text-align |
| text-uppercase / lowercase / capitalize | text-transform |
| text-underline / strikethrough / no-decoration | text-decoration |
| text-truncate | Ellipsis overflow truncation |
| text-nowrap | white-space: nowrap |
| line-height-none / tight / snug / normal / relaxed / loose | line-height presets |
| add-letter-space-{n} | letter-spacing: {n}px |
| letter-space-wide / wider / widest | em-based letter spacing |
Font Scale
set-text-48
set-text-36 text-bold
set-text-24 text-semibold
set-text-18 text-medium
set-text-14 text-normal — body text
set-text-12 letter-space-wider uppercase
| Class | CSS Output |
|---|---|
| make-flex / make-grid / make-block / make-hidden | display values |
| flex-row / flex-column | flex-direction |
| flex-wrap / flex-nowrap | flex-wrap |
| align-center / align-start / align-end / align-stretch | align-items |
| justify-center / justify-between / justify-start / justify-end / justify-around / justify-evenly | justify-content |
| flex-grow / flex-shrink / flex-none / flex-equal | flex shorthand values |
| self-center / self-start / self-end / self-stretch | align-self |
| place-center | place-items: center; place-content: center |
| grid-cols-{1-12} | grid-template-columns: repeat(n, 1fr) |
| grid-rows-{1-6} | grid-template-rows: repeat(n, 1fr) |
| span-col-{n} | grid-column: span n |
| span-col-full | grid-column: 1 / -1 |
| gap-{n} / gap-x-{n} / gap-y-{n} | gap / column-gap / row-gap |
| order-{1-12} / order-first / order-last | order |
| grid-flow-row / grid-flow-col / grid-flow-dense | grid-auto-flow |
Grid Demo — grid-cols-4 gap-16
| Class | CSS Output |
|---|---|
| set-width-{n} | width: {n}px (0–1024) |
| set-width-full | width: 100% |
| set-width-screen | width: 100vw |
| set-width-auto | width: auto |
| set-width-min / max / fit | min-content / max-content / fit-content |
| set-width-1-of-2 | width: 50% |
| set-width-1-of-3 / 2-of-3 | width: 33.33% / 66.66% |
| set-width-1-of-4 … 3-of-4 | width: 25% / 50% / 75% |
| set-height-{n} | height: {n}px (0–1024) |
| set-height-full | height: 100% |
| set-height-screen | height: 100vh |
| min-width-{n} / max-width-{n} | min/max-width: {n}px |
| min-height-{n} / max-height-{n} | min/max-height: {n}px |
| max-width-none | max-width: none |
20 color families × 10 shades (50–900). Use prefixes: color-, background-, border-color-, fill-, stroke-.
| Pattern | Example | CSS Output |
|---|---|---|
| color-{name}-{shade} | color-blue-500 | color: #3b82f6 |
| background-{name}-{shade} | background-green-100 | background-color: #dcfce7 |
| border-color-{name}-{shade} | border-color-red-600 | border-color: #dc2626 |
| fill-{name}-{shade} | fill-purple-500 | fill: #a855f7 (SVG) |
| stroke-{name}-{shade} | stroke-teal-400 | stroke: #2dd4bf (SVG) |
| color-white / color-black | — | color: #fff / #000 |
| background-white / background-black | — | background-color: #fff / #000 |
| Class | CSS Output |
|---|---|
| add-shadow-sm / md / lg / xl / inner | box-shadow presets |
| no-shadow | box-shadow: none |
| opacity-{0–100} | opacity: 0–1 (in steps of 5) |
| transition-fast / normal / slow | transition: all 0.15s / 0.3s / 0.5s ease |
| transition-colors / opacity / transform | Targeted transitions |
| rotate-45 / 90 / 135 / 180 / 270 | transform: rotate(Ndeg) |
| scale-75 / 90 / 95 / 100 / 105 / 110 / 125 / 150 | transform: scale(N) |
| flip-horizontal / flip-vertical | transform: scaleX(-1) / scaleY(-1) |
| skew-x-3 / 6 / 12 / skew-y-3 / 6 / 12 | transform: skewX/Y(Ndeg) |
| blur-sm / blur / blur-md / blur-lg / blur-xl | filter: blur(Npx) |
| grayscale / sepia / invert | filter presets |
| brightness-{50–200} / contrast-{50–200} | filter: brightness/contrast |
| animate-spin / ping / pulse / bounce | Looping animations |
| animate-fade-in / fade-in-from-top / … | 9 fade entrances |
| animate-bounce-in-from-{top/bottom/left/right} | 5 bounce entrances |
| animate-slide-in-from-{side} / slide-out-to-{side} | 4+4 slide variants |
| animate-zoom-in / zoom-in-from-{side} / zoom-out-… | 5+5 zoom variants |
| animate-flip / flip-in-x / flip-in-y / flip-out-x / y | 5 flip variants |
| animate-shake-x / shake-y / rubber-band / tada / wobble | Attention seekers |
| animate-rotate-in / rotate-in-from-{corner} | 5+5 rotate variants |
| animate-back-in-from-{side} / back-out-to-{side} | 4+4 back variants |
| animate-hinge / jack-in-box / roll-in / roll-out | Specials |
| animation-speed-{fastest → glacial} | Duration helpers (0.3s–3s) |
| animation-delay-{100–3000} | Delay in ms |
| animation-loop-{1–5} / forever | Iteration count |
| animation-fill-{none/forwards/backwards/both} | Fill mode |
| drop-shadow-sm / md / lg | filter: drop-shadow(…) |
| text-shadow-sm / md / lg | text-shadow presets |
| blend-multiply / screen / overlay / … | mix-blend-mode |
Animation Demo
| Prefix | Media Query | Example |
|---|---|---|
| on-mobile: | max-width: 639px | on-mobile:make-hidden |
| on-tablet: | 640px – 1023px | on-tablet:grid-cols-2 |
| on-desktop: | min-width: 1024px | on-desktop:grid-cols-4 |
| on-wide: | min-width: 1280px | on-wide:set-text-20 |
| sm: | min-width: 640px | sm:make-flex |
| md: | min-width: 768px | md:grid-cols-3 |
| lg: | min-width: 1024px | lg:add-padding-48 |
| xl: | min-width: 1280px | xl:set-text-24 |
| xxl: | min-width: 1536px | xxl:container |
| Prefix | Targets | Example |
|---|---|---|
| on-hover: | :hover | on-hover:background-blue-600 |
| on-focus: | :focus | on-focus:add-shadow-md |
| on-active: | :active | on-active:scale-95 |
| on-disabled: | :disabled | on-disabled:opacity-50 |
| on-checked: | :checked | on-checked:background-blue-500 |
| on-first: | :first-child | on-first:add-margin-top-0 |
| on-last: | :last-child | on-last:add-margin-bottom-0 |
| on-odd: / on-even: | nth-child | on-odd:background-gray-50 |
| on-placeholder: | ::placeholder | on-placeholder:color-gray-400 |
| on-focus-within: | :focus-within | on-focus-within:add-shadow-md |
| on-focus-visible: | :focus-visible | on-focus-visible:outline |
| dark: | prefers-color-scheme: dark | dark:background-gray-900 |
| group-hover: | Parent .group:hover | group-hover:color-blue-500 |
<!-- Responsive card grid: 1 col mobile → 2 col tablet → 3 col desktop --> <div class="make-grid grid-cols-1 gap-16 on-tablet:grid-cols-2 on-desktop:grid-cols-3"> <div class="card group cursor-pointer transition-normal on-hover:add-shadow-lg on-hover:scale-102"> <span class="color-gray-600 group-hover:color-blue-600 transition-colors"> Hover me </span> </div> </div>
| Class | CSS Output |
|---|---|
| position-static | position: static |
| position-relative | position: relative |
| position-absolute | position: absolute |
| position-fixed | position: fixed |
| position-sticky | position: sticky |
| pin-top / pin-bottom / pin-left / pin-right | top/bottom/left/right: 0 |
| pin-top-{n} / pin-left-{n} / … | top/left/…: {n}px |
| inset-0 | top/right/bottom/left: 0 |
| Class | CSS Output |
|---|---|
| z-0 | z-index: 0 |
| z-10 | z-index: 10 |
| z-20 | z-index: 20 |
| z-30 | z-index: 30 |
| z-40 | z-index: 40 |
| z-50 | z-index: 50 |
| z-100 | z-index: 100 |
| z-auto | z-index: auto |
| layer-{n} / layer-auto | z-index: n (alternate name) |
| Class | CSS Output |
|---|---|
| overflow-hidden | overflow: hidden |
| overflow-auto | overflow: auto |
| overflow-scroll | overflow: scroll |
| overflow-visible | overflow: visible |
| overflow-x-hidden | overflow-x: hidden |
| overflow-x-auto | overflow-x: auto |
| overflow-y-hidden | overflow-y: hidden |
| overflow-y-auto | overflow-y: auto |
| Class | CSS Output |
|---|---|
| cursor-pointer | cursor: pointer |
| cursor-default | cursor: default |
| cursor-not-allowed | cursor: not-allowed |
| cursor-grab / cursor-grabbing | cursor: grab / grabbing |
| cursor-wait / cursor-text / cursor-move | cursor: wait / text / move |
| cursor-crosshair / cursor-zoom-in / cursor-zoom-out | cursor variants |
| cursor-none / cursor-help / cursor-auto | cursor variants |
| Class | CSS Output |
|---|---|
| pointer-events-none | pointer-events: none |
| pointer-events-auto | pointer-events: auto |
| select-none | user-select: none |
| select-all | user-select: all |
| select-text | user-select: text |
| select-auto | user-select: auto |
| Class | CSS Output |
|---|---|
| object-fit-cover / fit-cover | object-fit: cover |
| object-fit-contain / fit-contain | object-fit: contain |
| object-fit-fill / fit-fill | object-fit: fill |
| object-fit-none / fit-none | object-fit: none |
| object-position-center / top / bottom / left / right | object-position |
| aspect-ratio-16-9 / aspect-video | aspect-ratio: 16 / 9 |
| aspect-ratio-1-1 / aspect-square | aspect-ratio: 1 / 1 |
| aspect-ratio-4-3 | aspect-ratio: 4 / 3 |
| aspect-ratio-3-2 | aspect-ratio: 3 / 2 |
| Class | CSS Output |
|---|---|
| gradient-to-right | background-image: linear-gradient(to right, var(--grad-from), var(--grad-to)) |
| gradient-to-bottom | background-image: linear-gradient(to bottom, …) |
| gradient-to-left / gradient-to-top | linear-gradient to left / top |
| gradient-to-bottom-right / top-right | diagonal gradients |
| from-blue-500 | --grad-from: #3b82f6 |
| from-purple-500 / from-purple-600 | --grad-from: #a855f7 / #9333ea |
| from-green-500 / from-teal-500 | --grad-from: #22c55e / #14b8a6 |
| from-orange-500 / from-red-500 / from-pink-500 | gradient start colors |
| to-purple-600 | --grad-to: #9333ea |
| to-blue-500 / to-indigo-500 | --grad-to: #3b82f6 / #6366f1 |
| to-green-500 / to-teal-500 / to-cyan-400 | gradient end colors |
| to-pink-500 / to-rose-500 / to-amber-400 | gradient end colors |
Gradient Demo
| Class | CSS Output |
|---|---|
| sr-only | Visually hidden, screen-reader accessible |
| not-sr-only | Undo sr-only (make visible again) |
| outline-none | outline: none |
| outline | outline: 2px solid currentColor |
| outline-offset-2 / outline-offset-4 | outline-offset |
| ring-2 / ring-4 / ring-8 | box-shadow focus ring (primary color) |
| ring-blue / ring-green / ring-red / ring-purple | Colored focus rings |
| ring-offset-1 / ring-offset-2 / ring-offset-4 | Ring with white gap offset |
| Class | CSS Output |
|---|---|
| backdrop-blur-sm | backdrop-filter: blur(4px) |
| backdrop-blur | backdrop-filter: blur(8px) |
| backdrop-blur-md | backdrop-filter: blur(12px) |
| backdrop-blur-lg | backdrop-filter: blur(16px) |
| backdrop-blur-xl / 2xl / 3xl | blur(24px / 40px / 64px) |
| navbar-glass | backdrop-filter: blur(12px) + semi-transparent bg |
CSS variables, dark mode, peer variants, print styles, RTL support.
Override design tokens in your own stylesheet — no build step, no config file, just CSS. Every component reads from these variables.
/* Override in your CSS file */ :root { --santy-primary: #7c3aed; /* brand purple */ --santy-primary-dark: #6d28d9; --santy-primary-light: #ede9fe; --santy-secondary: #0f172a; --santy-success: #16a34a; --santy-danger: #dc2626; --santy-radius: 12px; --santy-radius-sm: 6px; --santy-radius-lg: 20px; --santy-font-sans: 'Inter', sans-serif; }
| Token | Default | Used by |
|---|---|---|
| --santy-primary | #3b82f6 | .btn-primary, .ring-*, .tabs-item.active |
| --santy-primary-dark | #2563eb | .btn-primary:hover |
| --santy-primary-light | #dbeafe | light bg accents |
| --santy-secondary | #6b7280 | .btn-secondary |
| --santy-success / danger / warning / info | green/red/amber/cyan | .btn-success, .alert-*, notification-* |
| --santy-radius / -sm / -md / -lg / -xl / -full | 8px … 9999px | all rounded corners |
| --santy-font-sans / -serif / -mono | system-ui / Georgia / monospace | .font-sans, .font-serif, .font-mono |
Add .dark to <html> or <body> — all components auto-adapt. Use .dark-auto to follow the OS preference.
<!-- Manual dark mode --> <html class="dark"> <!-- Follow OS preference --> <html class="dark-auto"> <!-- Per-element dark override --> <div class="dark:background-gray-900 dark:color-white">
| Component | .dark class adapts |
|---|---|
| .card / .card-header / .card-body / .card-footer | ✅ |
| .btn-outline / .btn-ghost / .btn-secondary | ✅ |
| .alert-info / -success / -warning / -danger | ✅ |
| .badge / .notification-* | ✅ |
| .input / .select / .textarea | ✅ |
| .modal-box / .drawer-panel | ✅ |
| .accordion / .tabs / .dropdown-menu | ✅ |
| .table / .navbar / .pagination | ✅ |
Target sibling elements when an ancestor or peer changes state — no JS required.
<!-- peer-checked: show sibling --> <input type="checkbox" class="peer"> <p class="make-hidden peer-checked:make-block"> Visible when checked! </p> <!-- peer-hover: change color --> <input class="peer"> <label class="peer-focus:color-blue-600"> Label</label> <!-- group-hover: child reacts to parent --> <div class="group cursor-pointer"> <span class="group-hover:color-blue-500">hover me</span> </div>
| Variant | Triggers when |
|---|---|
| peer-hover:{cls} | peer element is hovered |
| peer-focus:{cls} | peer element is focused |
| peer-checked:{cls} | peer checkbox/radio is checked |
| peer-disabled:{cls} | peer element is disabled |
| group-hover:{cls} | parent .group is hovered |
| group-focus:{cls} | parent .group has focus |
Built-in accessibility and print utilities — no plugins or extra config.
<!-- Print styles --> <nav class="print:make-hidden">…</nav> <footer class="print:make-hidden">…</footer> <article class="print:set-text-12 print:color-black">…</article> <!-- Motion accessibility --> <div class="motion-safe:animate-spin motion-reduce:animate-none">…</div> <!-- Link states --> <a class="color-blue-500 on-visited:color-purple-600 on-hover:color-blue-700"> Link </a>
| Variant | Description |
|---|---|
| print:{cls} | Applied only when printing |
| print:make-hidden | Hide element in print |
| print:make-block | Show element only in print |
| motion-safe:{cls} | Only if user has no reduce-motion preference |
| motion-reduce:{cls} | Applied when reduce-motion is set |
| motion-reduce:animate-none | Kills animations for accessibility |
| on-visited:{cls} | Visited links |
| on-required:{cls} | Required form fields |
| on-invalid:{cls} | Invalid form fields |
| on-read-only:{cls} | Read-only inputs |
SantyCSS ships logical property utilities. Add dir="rtl" to <html> and spacing/borders automatically flip — no extra classes needed.
<!-- RTL-safe layout --> <html dir="rtl"> <div class="ps-16 pe-8"> <!-- padding-inline-start/end flips in RTL --> </div> <div class="ms-auto border-start-4"> <!-- start/end flip in RTL --> </div>
| Class | Logical Property |
|---|---|
| ps-{n} | padding-inline-start (LTR: left, RTL: right) |
| pe-{n} | padding-inline-end (LTR: right, RTL: left) |
| ms-auto | margin-inline-start: auto |
| me-auto | margin-inline-end: auto |
| border-start-1/2/4 | border-inline-start (flips in RTL) |
| border-end-1/2/4 | border-inline-end (flips in RTL) |
| start-0 / end-0 | inset-inline-start/end: 0 |
High-level classes for common patterns — built on top of utilities.
.make-button .style-primary .size-small/.large/.xl
.dropdown .dropdown-menu .dropdown-item
.tabs .tabs-item.active .tab-panel
.accordion .accordion-header .accordion-body
.notification .notification-success/.error
.progress .progress-bar / .skeleton
.badge / .chip .chip-blue/.green
| Name | Role | Status |
|---|---|---|
| Alice | Admin | Active |
| Bob | Editor | Pending |
.table .table-hover .table-striped
.toggle .toggle-slider / .range
.steps .step .step.active .step.done
.card .card-header .card-body .card-footer
.input .select .textarea .input-group
.avatar .avatar-md / .spinner .spinner-lg
.alert .alert-info/.success/.warning/.danger
.navbar .navbar-brand .navbar-item .navbar-dark
.tooltip .tooltip-top/.bottom/.left/.right .tooltip-content
Full UI patterns built entirely with SantyCSS classes.
Starter
Perfect for personal projects.
Pro
For growing teams.
Enterprise
For large organizations.
Product Designer · San Francisco
Describe what you want in plain English and get ready-to-use SantyCSS classes instantly.
100% client-side · no API key · works offline
SantyCSS is growing. Here's where we're taking it — from AI tooling to design systems.
Type a description → get SantyCSS classes instantly
Autocomplete + live hover preview for every class
Brand your entire UI with CSS vars — zero build step
Composable, AI-friendly class naming for components
Select a frame → export SantyCSS classes instantly
In-browser editor — try SantyCSS in 30 seconds
Hover any class → see the raw CSS it generates
Flip the AI script — SantyCSS explains itself instead of you explaining Tailwind to AI.
Scaffold, purge, and manage SantyCSS from the terminal
npx santycss [your-html-files]
Built-in ARIA-friendly classes AI consistently misses
make-sr-only make-focusable skip-to-content
Paste into Claude / ChatGPT / Cursor — AI generates SantyCSS instead of Tailwind
Share a bug, feature idea, or just say hi — your message goes straight to WhatsApp.
Opens WhatsApp with your message pre-filled — just hit send.