Module Documentation
SantyCSS ships as 5 independent CSS modules. Use the full bundle, or load only what you need for optimal performance.
Installation
Install once, use everywhere. Zero dependencies, no build step required.
npm install santycss
Package Structure
Everything ships inside the dist/ folder with the JS tooling at the root level.
santycss/ ├── dist/ │ ├── santy.css ← Full bundle (718KB) — all utilities + components + animations │ ├── santy.min.css ← Minified full bundle (629KB) │ ├── santy-core.css ← Utilities only (598KB) │ ├── santy-components.css ← Components only (68KB) │ ├── santy-animations.css ← 120+ animations (53KB) │ └── santy-email.css ← Email template CSS (13KB) ├── postcss/ │ └── index.js ← PostCSS plugin (tree-shaking) ├── lib/ │ ├── purge-core.js ← Purge API (tree-shaking engine) │ └── animations.js ← Animation definitions ├── index.js ← Main entry — CSS path helpers + purge API ├── santy-jit.js ← JIT runtime (generates classes on-the-fly) ├── vite-plugin-santycss.js ← Vite plugin └── purge.js ← CLI purge tool
| Export | Resolves to | Use when |
|---|---|---|
| santycss/css | dist/santy.css | You want everything in one file |
| santycss/min | dist/santy.min.css | Production, CDN, smallest file size |
| santycss/css/core | dist/santy-core.css | Only utilities, no components |
| santycss/css/components | dist/santy-components.css | Only UI components (.btn, .card…) |
| santycss/css/animations | dist/santy-animations.css | Only animation classes |
| santycss/css/email | dist/santy-email.css | HTML email templates |
| santycss/postcss | postcss/index.js | PostCSS tree-shaking plugin |
| santycss/vite | vite-plugin-santycss.js | Vite plugin |
Import Options
4 ways to use SantyCSS depending on your setup.
// Full bundle import 'santycss/css'; // Modular — load only what you need import 'santycss/css/core'; import 'santycss/css/components'; import 'santycss/css/animations'; import 'santycss/css/email';
/* In your main.css */ @import 'santycss/dist/santy.css'; /* Or individual modules */ @import 'santycss/dist/santy-core.css'; @import 'santycss/dist/santy-components.css'; @import 'santycss/dist/santy-email.css';
// app/layout.js or pages/_app.js import 'santycss/css'; export default function RootLayout({ children }) { return ( <html> <body>{children}</body> </html> ); }
// Get absolute paths for config files const santy = require('santycss'); santy.css // → /path/to/dist/santy.css santy.min // → /path/to/dist/santy.min.css santy.core // → /path/to/dist/santy-core.css santy.components // → /path/to/dist/santy-components.css santy.animations // → /path/to/dist/santy-animations.css santy.email // → /path/to/dist/santy-email.css
CDN Links
Once published on npm, jsDelivr and unpkg serve the files instantly — no setup needed.
<!-- Full minified bundle — recommended for production --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy.min.css"> <!-- Version-pinned (best practice for production) --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss@1.7.0/dist/santy.min.css"> <!-- Utilities only --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-core.css"> <!-- Components --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-components.css"> <!-- Animations --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-animations.css"> <!-- Email module --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-email.css"> <!-- unpkg alternative --> <link rel="stylesheet" href="https://unpkg.com/santycss/dist/santy.css">
🏫 MERIDIAN Academy
7-page school website — Home, About, Academics, Admissions, Faculty, Events, and a grade-filtered Notifications hub (Grade 1–12 + Staff).
Preview →💇 AURUM Studio — Saloon
Luxury dark salon: gold accents, serif typography, marquee strip, 6 service cards, stylist team with hover overlays, gallery, and booking CTA.
Preview →👁️ OPTIXA — Eye Vision Center
Sci-fi vision clinic: animated SVG iris ring, CSS scanline overlay, cyan glow, concentric tech animation, doctor cards, and radial-glow CTA.
Preview →🍺 IRONFORGE — Craft Brewery
Dark industrial brewery: amber/copper palette, ember marquee strip, 6-tap beer list with ABV/IBU, 6-step brewing process grid, events, newsletter.
Preview →Instead of loading the full 1.2 MB bundle, pick only the modules your UI actually uses. Each module is self-contained and can be imported individually in any order.
Available modules
reset1.9 KB
CSS reset + design tokens (always include this first)
layout86 KB
Display, position, overflow, z-index, object-fit, aspect-ratio, a11y
flex3 KB
Flex direction, wrap, grow, shrink, align, justify
grid2.6 KB
Grid template columns, rows, span, gap
spacing30 KB
Padding, margin (all directions, all scale values)
sizing8.3 KB
Width, height, min/max dimensions, fractional sizes
typography6.3 KB
Font size, weight, family, line-height, text-align, decoration
colors82 KB
Text color, background color, border color, caret color (full palette)
borders15 KB
Border width, style, radius, side-specific
effects11 KB
Opacity, shadows, filters, transitions, cursor, pointer-events
Import examples
ES module / Vite / Next.js / Vue
// Minimal dashboard UI — ~50 KB total import 'santycss/css/reset'; import 'santycss/css/flex'; import 'santycss/css/grid'; import 'santycss/css/spacing'; import 'santycss/css/typography'; import 'santycss/css/colors'; import 'santycss/css/components'; // pre-built UI components // Add responsive / hover / dark-mode variants if you use them import 'santycss/css/variants';
CDN — individual module links
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-reset.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-flex.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-spacing.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-typography.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-colors.css">
Node.js path helpers
const santy = require('santycss'); // Absolute paths for webpack / rollup config santy.reset // → /path/to/dist/santy-reset.css santy.flex // → /path/to/dist/santy-flex.css santy.spacing // → /path/to/dist/santy-spacing.css santy.typography // → /path/to/dist/santy-typography.css santy.colors // → /path/to/dist/santy-colors.css // … and: santy.layout, santy.grid, santy.sizing, santy.borders, santy.effects
md:, on-hover:) or dark-mode variants. Import santycss/css/variants alongside them if you need those.
What's included
sm: md: lg: xl:on-hover: on-focus: dark:--santy-primary etc.)<!-- HTML --> <link rel="stylesheet" href="santy.css"> <!-- or --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy.min.css"> // JS import 'santycss/css';
Utility categories
| Category | Example classes | Count |
|---|---|---|
| Spacing | add-padding-{n}, add-margin-{n}, gap-{n}, space-x-{n} | ~2400 classes |
| Colors | color-blue-500, background-green-100, border-color-red-600 | ~1200 classes |
| Typography | set-text-{n}, text-bold, text-center, font-sans, line-height-relaxed | ~400 classes |
| Layout | make-flex, make-grid, grid-cols-{1-12}, flex-row, align-center | ~300 classes |
| Sizing | set-width-{n}, set-height-{n}, max-width-{n}, aspect-ratio-16-9 | ~800 classes |
| Position | position-relative, pin-top-0, z-10, z-50, inset-0 | ~200 classes |
| Overflow | overflow-hidden, overflow-x-auto, overflow-y-scroll | 12 classes |
| Borders | add-border-{n}, round-corners-{n}, make-circle, make-pill | ~300 classes |
| Effects | add-shadow-md, opacity-50, blur-md, backdrop-blur-lg, ring-2 | ~200 classes |
| Transforms | rotate-45, scale-110, flip-horizontal, skew-x-6 | ~80 classes |
| Gradients | gradient-to-right, from-blue-500, to-purple-600 | ~100 classes |
| Transitions | transition-fast, transition-colors, transition-transform | ~30 classes |
| State variants | on-hover:*, on-focus:*, dark:*, group-hover:*, peer-checked:* | ~3000 classes |
| Responsive | sm:*, md:*, lg:*, xl:*, on-mobile:*, on-tablet:* | ~3000 classes |
| Accessibility | sr-only, not-sr-only, outline-none, pointer-events-none | ~30 classes |
import 'santycss/css/core'; <!-- Example: build your own card using utilities --> <div class="background-white round-corners-16 add-padding-24 add-shadow-md on-hover:add-shadow-lg on-hover:scale-102 transition-normal"> <h3 class="set-text-18 text-semibold color-gray-900 add-margin-bottom-8">Title</h3> <p class="set-text-14 color-gray-500 line-height-relaxed">Body text.</p> </div>
All components
| Component | Key classes |
|---|---|
| .btn | .btn-primary .btn-success .btn-danger .btn-sm .btn-lg .btn-outline .btn-ghost |
| .card | .card-header .card-body .card-footer |
| .modal | .modal-overlay .modal-box .modal-header .modal-body .modal-footer .modal-close |
| .drawer | .drawer-overlay .drawer-panel .drawer-header .drawer-body |
| .navbar | .navbar-brand .navbar-menu .navbar-item .navbar-dark .navbar-glass |
| .dropdown | .dropdown-menu .dropdown-item .dropdown-divider .dropdown-header |
| .tabs | .tabs-item .tabs-item.active .tab-panel .tabs-pill |
| .accordion | .accordion-item .accordion-header .accordion-body .accordion-icon |
| Component | Key classes |
|---|---|
| .alert | .alert-info .alert-success .alert-warning .alert-danger |
| .badge / .chip | .badge .badge-green .badge-blue .badge-yellow .badge-red .chip |
| .input / .select | .input .input-text .select .textarea .input-group .input-addon |
| .table | .table-hover .table-striped .table-responsive |
| .pagination | .page-item .page-link .page-item.active .page-item.disabled |
| .toggle / .slider | .toggle .toggle-slider .toggle-green .slider |
| .progress | .progress .progress-bar .progress-bar-green .progress-bar-red .progress-bar-yellow |
| .skeleton | .skeleton (animated loading placeholder) |
New in v1.4 — Dark Theme UI Components
CSS custom property tokens + ready-made dark-theme components for mobile apps, chat UIs, dashboards, and scanners.
Dark theme tokens
| Token | Value | Utility class |
|---|---|---|
| --color-surface | #0f172a | .bg-surface |
| --color-card | #1e293b | — |
| --color-accent | #38bdf8 | .text-accent |
| --color-accent-light | rgba(56,189,248,.13) | .bg-accent-light |
| --color-text | #f1f5f9 | .text-primary |
| --color-muted | #64748b | .text-muted |
New component classes
| Class | Description |
|---|---|
| .badge-green / -blue / -yellow / -red | Semi-transparent tinted badge variants |
| .progress-bar-green / -red / -yellow / -purple / -orange | Colour overrides for .progress-bar fill |
| .h-xs / .h-sm / .h-md / .h-lg | Named height utilities: 24 / 48 / 96 / 160px |
| .slider | Dark-themed range input (accent colour thumb) |
| .stat-card | Dark card for KPI / metric tiles |
| .btn-icon | 44×44 circular icon button |
| .input-text | Dark-themed text input with accent focus ring |
| .chat-bubble-user | Right-aligned user message bubble |
| .chat-bubble-ai | Left-aligned AI / assistant message bubble |
| .typing-indicator | Three-dot animated typing indicator |
| .calorie-ring | Wrapper for SVG ring / donut charts |
| .scan-overlay | Accent-bordered camera scan frame |
| .scan-line-animated | Animated horizontal scan sweep line |
| .bar-chart-wrapper | Dark card wrapper for bar chart content |
<!-- Typing indicator --> <div class="typing-indicator"> <span></span><span></span><span></span> </div> <!-- Chat bubbles --> <div class="chat-bubble-user">How many calories in a banana?</div> <div class="chat-bubble-ai">About 89 calories.</div> <!-- Tinted badges --> <span class="badge badge-green">Protein</span> <span class="badge badge-blue">Carbs</span> <span class="badge badge-yellow">Fat</span> <!-- Progress with colour variants --> <div class="progress"> <div class="progress-bar progress-bar-green" style="width:70%"></div> </div>
class="dark" to <html>. Use class="dark-auto" to follow the OS preference.
// Load utilities + components (most common setup) import 'santycss/css/core'; import 'santycss/css/components'; <!-- Button examples --> <button class="btn btn-primary">Save</button> <button class="btn btn-outline btn-sm">Cancel</button> <!-- CSS-only modal (no JS needed) --> <a href="#my-modal" class="btn btn-primary">Open</a> <div id="my-modal" class="modal-overlay"> <div class="modal-box"> <div class="modal-header"> <h4 class="modal-title">Confirm</h4> <a href="#" class="modal-close"></a> </div> <div class="modal-body">Are you sure?</div> </div> </div>
New in v1.5 — Advanced UI Patterns
9 new component families for common app UI patterns: command palettes, kanban boards, timelines, dropzones, mega menus, split panes, ratings, and code blocks.
| Component | Root class | Key modifiers & sub-classes |
|---|---|---|
| Command Palette | .cmd-palette |
-backdrop -input -list -group -item -item.active -empty -footer -kbd |
| Kanban Board | .kanban |
-col -col-header -col-title -col-count -card -card-label -card-title -card-meta -add-btn |
| Timeline / Feed | .timeline |
-item -dot -dot-blue/green/red/yellow -body -title -desc -time -card -compact |
| File Upload Dropzone | .dropzone |
-icon -title -desc -btn -types -sm .drag-over · .file-list .file-list-item .file-list-name .file-list-remove |
| Mega Menu | .mega-menu |
-wrap -grid -col-title -item -item-icon -item-title -item-desc -footer .open |
| Split Pane | .split-pane |
-panel -divider -vertical .dragging |
| Rating / Stars | .rating |
-star -star.filled -sm -lg -readonly -value -count |
| Code Block | .code-block |
-header -lang -dots -dot-red/yellow/green -copy -copy.copied -gutter -inner -line-numbers |
| Syntax tokens | — | .token-keyword .token-string .token-comment .token-number .token-fn .token-tag .token-attr |
Usage examples
<!-- Command Palette --> <div class="cmd-palette-backdrop"> <div class="cmd-palette"> <div class="cmd-palette-input-wrap"> <input class="cmd-palette-input" placeholder="Search commands…"> <span class="cmd-palette-kbd">esc</span> </div> <div class="cmd-palette-list"> <div class="cmd-palette-group">Recent</div> <div class="cmd-palette-item active"> <span class="cmd-palette-item-label">Open Settings</span> <span class="cmd-palette-item-hint">⌘,</span> </div> </div> </div> </div>
<!-- Timeline --> <div class="timeline"> <div class="timeline-item"> <div class="timeline-dot timeline-dot-green">✓</div> <div class="timeline-body"> <div class="timeline-time">2 hours ago</div> <div class="timeline-title">Deployed to production</div> </div> </div> </div> <!-- File Dropzone --> <div class="dropzone"> <div class="dropzone-icon">📁</div> <div class="dropzone-title">Drop files here</div> <div class="dropzone-desc">or click to browse</div> <button class="dropzone-btn">Choose files</button> <div class="dropzone-types">PNG, JPG, PDF up to 10MB</div> </div> <!-- Rating --> <div class="rating"> <span class="rating-star filled">★</span> <span class="rating-star filled">★</span> <span class="rating-star filled">★</span> <span class="rating-star">★</span> <span class="rating-star">★</span> <span class="rating-value">3.0</span> <span class="rating-count">(128 reviews)</span> </div> <!-- Code Block with syntax tokens --> <div class="code-block"> <div class="code-block-header"> <div class="code-block-dots"> <span class="code-block-dot code-block-dot-red"></span> <span class="code-block-dot code-block-dot-yellow"></span> <span class="code-block-dot code-block-dot-green"></span> </div> <span class="code-block-lang">javascript</span> <button class="code-block-copy">Copy</button> </div> <pre><code>const greet = (name) => { return `Hello, ${name}!`; // greeting };</code></pre> </div>
| Group | Classes |
|---|---|
| Looping | animate-spin, animate-ping, animate-pulse, animate-bounce |
| Fade | animate-fade-in, animate-fade-in-from-top/bottom/left/right, animate-fade-out |
| Slide | animate-slide-in-from-top/bottom/left/right, animate-slide-out-to-* |
| Zoom | animate-zoom-in, animate-zoom-in-from-*, animate-zoom-out-* |
| Bounce | animate-bounce-in, animate-bounce-in-from-top/bottom/left/right |
| Flip | animate-flip, animate-flip-in-x/y, animate-flip-out-x/y |
| Rotate | animate-rotate-in, animate-rotate-in-from-top-left/right/bottom-left/right |
| Back | animate-back-in-from-*, animate-back-out-to-* |
| Attention | animate-shake-x/y, animate-rubber-band, animate-tada, animate-wobble |
| Specials | animate-hinge, animate-jack-in-box, animate-roll-in, animate-roll-out |
| Speed | animation-speed-fastest (0.3s) → animation-speed-glacial (3s) |
| Delay | animation-delay-100 → animation-delay-3000 (ms) |
| Repeat | animation-loop-1/2/3/4/5, animation-loop-forever |
| Fill | animation-fill-none/forwards/backwards/both |
| Motion | motion-safe:animate-spin, motion-reduce:animate-none |
import 'santycss/css/animations'; <!-- Fade in on page load --> <div class="animate-fade-in">Appears smoothly</div> <!-- Staggered entrance --> <div class="animate-slide-in-from-left animation-delay-0">Item 1</div> <div class="animate-slide-in-from-left animation-delay-200">Item 2</div> <div class="animate-slide-in-from-left animation-delay-400">Item 3</div> <!-- Reduced motion accessibility --> <div class="motion-safe:animate-bounce motion-reduce:animate-none"> Bounces only if user hasn't requested reduce-motion </div>
New in v1.7
Accessibility, internationalisation, mobile-first components, command palette, date picker, and Figma plugin in development.
Accessibility Utilities
| Class | What it does |
|---|---|
.skip-to-content | Hidden link visible on focus — jumps keyboard users to main content |
.screen-reader-only | Visually hidden but accessible to screen readers |
.focus-trap | Container for modal/drawer focus trapping |
.aria-live-polite / .aria-live-assertive | Visually hidden ARIA live region containers |
.focus-ring / .focus-ring-white | Consistent focus outline utilities |
.focus-visible-ring | Focus outline only on keyboard navigation (not mouse) |
.motion-safe-animate | Disables animation when OS prefers-reduced-motion is active |
.high-contrast-border/bg/outline | forced-colors media query support for Windows High Contrast |
Internationalisation (i18n) & RTL
| Class | What it does |
|---|---|
.add-padding-block-{4–32} | Logical block padding — adapts to writing direction |
.add-padding-inline-{4–32} | Logical inline padding |
.add-margin-block-{n} / .add-margin-inline-{n} | Logical margins |
.pin-block-start-0 / .pin-inline-start-0 | Logical positioning |
.border-block-start / .border-inline-start | Logical borders |
.make-text-vertical | writing-mode: vertical-rl — CJK / Japanese vertical text |
.make-text-vertical-up | writing-mode: vertical-lr — upward vertical text |
.text-orientation-mixed / .text-orientation-upright | Controls glyph orientation in vertical text |
.text-direction-ltr / .text-direction-rtl | Explicit direction property |
Mobile-First Components
| Component | Root class | Key sub-classes |
|---|---|---|
| Bottom Sheet | .bottom-sheet |
-handle -header -title -body -footer -overlay .open .visible |
| Swipeable Carousel | .swipe-carousel |
-item -full -peek -multi -dots -dot .active |
| Pull-to-Refresh | .pull-to-refresh |
-spinner .pulling .refreshing |
| Safe Area Insets | — | .padding-safe-top .padding-safe-bottom .padding-safe-left .padding-safe-right .padding-safe-all .margin-safe-bottom .pin-bottom-safe |
| Command Palette | .command-palette |
-wrap -input-row -input -kbd -list -group-label -item -item-icon -item-label -item-shortcut -empty -footer .open |
| Date Picker | .date-picker |
-header -month-year -nav -weekdays -grid -day -day.today -day.selected -day.in-range -day.range-start -day.range-end -day.other-month -day.disabled -footer |
Inspect a Figma frame and export the exact SantyCSS classes that match the design. No more translating design tokens by hand.
What's New in v1.8
Figma plugin launch, full Inspector docs, AI class generator, SantyCSS Builder WordPress plugin, expanded component library, and a live changelog.
SantyCSS Inspector (Figma Plugin)
Select any Figma layer and instantly get the matching SantyCSS utility classes — colors, typography, spacing, shadows, borders, and border-radius — all mapped in one click.
AI Class Generator
Describe a UI element in plain English and get SantyCSS classes instantly. Provide your Anthropic API key to use Claude AI, or the built-in smart rule engine runs offline for free.
- Prompt-to-classes via Claude Haiku (optional API key)
- Smart rule engine fallback — works 100% offline
- Live preview + one-click copy
- API key stored securely in localStorage (never sent to our servers)
SantyCSS Builder (WordPress Plugin)
Drag-and-drop visual builder inside WordPress. Add SantyCSS utility classes to any block via a side panel — no code needed.
- Visual block editor with live preview
- Class autocomplete panel — all SantyCSS utilities
- Dark mode support baked in
- Zero dependencies — pure PHP + Vanilla JS
Expanded Component Library
New standalone components.html page with live previews and copy-paste code for buttons, cards, badges, alerts, modals, navbars, hero sections, pricing tables, testimonials, and more.
Live Changelog
New changelog.html page tracks every release from v1.0.0 → v2.6.1 with New / Fix / Improve tags and a timeline layout.
What it inspects
| Figma property | SantyCSS class generated |
|---|---|
| Auto-layout direction (horizontal) | make-flex flex-row |
| Auto-layout direction (vertical) | make-flex flex-column |
| Primary axis alignment | justify-center / justify-between / justify-end |
| Counter axis alignment | align-center / align-end / align-baseline |
| Flex wrap | flex-wrap |
| Item spacing / gap | gap-16, gap-24 … |
| Padding (uniform) | add-padding-24 |
| Padding (axis) | add-padding-x-16 add-padding-y-8 |
| Padding (individual sides) | add-padding-top-12 add-padding-right-16 … |
| Width (fixed) | set-width-320 |
| Width (fill container) | set-width-full |
| Width (hug contents) | set-width-fit |
| Height | set-height-48, set-height-full, set-height-fit |
| Corner radius | round-corners-8 |
| Full corner radius | make-pill |
| Stroke / border | add-border-1 + border-color-blue-500 |
| Fill color (solid) | background-blue-500 — nearest palette match across 200 colors |
| Text color | color-gray-900 |
| Font size | set-text-16 |
| Font weight | text-bold, text-semibold, text-medium … |
| Text alignment | text-center, text-right, text-justify |
| Text decoration | text-underline, text-line-through |
| Text transform | text-uppercase, text-lowercase, text-capitalize |
| Drop shadow | add-shadow-sm / add-shadow-lg / add-shadow-xl |
| Opacity | opacity-50, opacity-75 … |
| Clips content | overflow-hidden |
Install locally (development)
# 1. Clone or download the plugin folder # figma-plugin-santycss/ contains: manifest.json, code.js, ui.html # 2. In Figma Desktop: # Plugins → Development → Import plugin from manifest… # → select figma-plugin-santycss/manifest.json # 3. Select any layer on the canvas # Plugins → Development → SantyCSS Inspector
Plugin UI features
prefers-color-scheme.Color matching algorithm
The plugin converts Figma's RGBA values (0–1 range) to the nearest SantyCSS palette color using Euclidean distance in RGB space across all 20 color families × 10 shades = 200 reference colors. White (color-white) and black (color-black) are checked first with a tight threshold.
File structure
figma-plugin-santycss/ ├── manifest.json ← Plugin config (name, API version, entry points) ├── code.js ← Runs in Figma sandbox — reads node properties via Figma API ├── ui.html ← Plugin window UI — grouped output, copy buttons, dark mode └── README.md ← Install & publish instructions
- Create / log in at figma.com
- Go to Community → Publish a plugin
- Upload
manifest.json,code.js,ui.html - Add name, description, and a cover image — Figma reviews & publishes within 1–2 days
| Category | Key classes | Purpose |
|---|---|---|
| .email-wrapper / container | .email-wrapper, .email-container | Outer 600px max-width wrapper |
| Table layout | .email-table, .email-cell, .email-col-half, .email-col-third | Email-safe column layouts |
| Header / Footer | .email-header, .email-header-light, .email-footer, .email-footer-dark | Branding sections |
| Hero | .email-hero, .email-hero-light, .email-hero-gradient | Bold banner area |
| Body | .email-body-wrap, .email-body-wrap-gray, .email-section | Main content area |
| Typography | .email-h1/h2/h3, .email-p, .email-p-lead, .email-link, .email-muted | Email-safe fonts |
| Buttons | .email-btn, .email-btn-sm/lg/outline/dark/success/danger/warning | CTA buttons |
| Cards & Callouts | .email-card, .email-callout-success/warning/danger | Content blocks |
| Lists | .email-list, .email-check-list | Styled bulleted / checkmark lists |
| Badges | .email-badge-blue/green/red/yellow/purple/gray/new | Status labels |
| Images | .email-img, .email-img-rounded, .email-img-circle, .email-img-full | Responsive images |
| Avatars | .email-avatar-sm/md/lg | Profile pictures |
| Stats | .email-stat-value, .email-stat-label | Large number blocks |
| Code | .email-code, .email-code-inline | Developer emails |
| Spacers | .email-spacer-4 → .email-spacer-64 | Vertical spacing blocks |
| Social | .email-social-wrap, .email-social-link, .email-social-text-link | Social media links |
| Preheader | .email-preheader | Hidden preview text |
| Legal | .email-legal, .email-address, .email-unsubscribe | Footer compliance text |
How to include
Pick any one of these methods depending on your setup:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-email.css">
import 'santycss/css/email';
@import 'santycss/dist/santy-email.css';
const santy = require('santycss'); // santy.email → absolute path fs.readFileSync(santy.email, 'utf8');
Component examples
<!-- Full outer wrapper → max 600px, centered --> <table class="email-wrapper" role="presentation"><tr><td> <table class="email-container" role="presentation"> <!-- Two-column layout --> <tr> <td class="email-col-half">Left column</td> <td class="email-col-half">Right column</td> </tr> <!-- Three-column layout --> <tr> <td class="email-col-third">Col 1</td> <td class="email-col-third">Col 2</td> <td class="email-col-third">Col 3</td> </tr> </table> </td></tr></table>
<!-- Dark header with logo --> <tr><td class="email-header"> <img src="logo.png" class="email-logo" alt="Brand" width="140"> </td></tr> <!-- Light header variant --> <tr><td class="email-header-light"> ... </td></tr> <!-- Gradient hero banner --> <tr><td class="email-hero-gradient"> <h1 class="email-h1" style="color:#fff;">Welcome aboard! 🎉</h1> <p class="email-p-lead" style="color:rgba(255,255,255,.85);">Let's get started.</p> </td></tr> <!-- Footer with legal --> <tr><td class="email-footer"> <p class="email-legal">© 2026 Company Inc · 123 Street, City</p> <a href="{{unsubscribe_url}}" class="email-unsubscribe">Unsubscribe</a> </td></tr>
<tr><td class="email-body-wrap"> <h1 class="email-h1">Main heading</h1> <h2 class="email-h2">Section heading</h2> <h3 class="email-h3">Sub-heading</h3> <p class="email-p-lead">Large intro paragraph</p> <p class="email-p">Normal body text. <a href="#" class="email-link">Inline link</a></p> <p class="email-muted">Small muted helper text</p> <p class="email-small">Fine print / disclaimer</p> </td></tr>
<!-- Primary button (blue) --> <div class="email-btn-center"> <a href="https://example.com" class="email-btn">Get Started</a> </div> <!-- Button variants --> <a href="#" class="email-btn email-btn-sm">Small button</a> <a href="#" class="email-btn email-btn-lg">Large button</a> <a href="#" class="email-btn email-btn-outline">Outline button</a> <a href="#" class="email-btn email-btn-dark">Dark button</a> <a href="#" class="email-btn email-btn-success">Confirm order ✓</a> <a href="#" class="email-btn email-btn-danger">Cancel subscription</a> <a href="#" class="email-btn email-btn-warning">Action required ⚠</a>
<!-- White card with border --> <div class="email-card"> <h3 class="email-h3">Order Summary</h3> <p class="email-p">Item × 2 — $49.00</p> </div> <!-- Coloured callout banners --> <div class="email-callout-success">✓ Payment received — thank you!</div> <div class="email-callout-warning">⚠ Your subscription expires in 3 days.</div> <div class="email-callout-danger">✕ We couldn't process your payment.</div>
<!-- Bulleted list --> <ul class="email-list"> <li>Unlimited projects</li> <li>Priority support</li> </ul> <!-- Checkmark list (✓ prefix via CSS) --> <ul class="email-check-list"> <li>No credit card required</li> <li>Cancel any time</li> <li>Free 14-day trial</li> </ul>
<span class="email-badge-blue">Info</span> <span class="email-badge-green">Active</span> <span class="email-badge-red">Expired</span> <span class="email-badge-yellow">Pending</span> <span class="email-badge-purple">Pro</span> <span class="email-badge-gray">Draft</span> <span class="email-badge-new">New</span>
<table class="email-table"><tr> <td class="email-cell" style="text-align:center;"> <div class="email-stat-value">1,284</div> <div class="email-stat-label">Page views</div> </td> <td class="email-cell" style="text-align:center;"> <div class="email-stat-value">42%</div> <div class="email-stat-label">Open rate</div> </td> <td class="email-cell" style="text-align:center;"> <div class="email-stat-value">$3.2k</div> <div class="email-stat-label">Revenue</div> </td> </tr></table>
<!-- Horizontal rule --> <div class="email-divider"></div> <!-- Vertical spacing blocks (px values: 4 8 16 24 32 48 64) --> <div class="email-spacer-8"></div> <div class="email-spacer-24"></div> <div class="email-spacer-48"></div>
<!-- Code block (developer emails) --> <pre class="email-code">npm install santycss</pre> <!-- Inline code --> Use the <code class="email-code-inline">email-btn</code> class for buttons. <!-- Responsive images --> <img src="banner.jpg" class="email-img-full" alt="Banner"> <!-- full-width --> <img src="photo.jpg" class="email-img-rounded" alt="Photo"> <!-- 8px radius --> <img src="avatar.jpg" class="email-avatar-md" alt="Avatar"> <!-- 48px circle -->
<!-- Hidden preview text (shows in inbox before open) --> <div class="email-preheader">Your invoice is ready — view it now</div> <!-- Social media row --> <div class="email-social-wrap"> <a href="https://twitter.com/yourco" class="email-social-link"> <img src="twitter-icon.png" width="24" alt="Twitter"> </a> <a href="https://linkedin.com/company/yourco" class="email-social-text-link">LinkedIn</a> </div>
Complete email template
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy-email.css"> <table class="email-wrapper" role="presentation"> <tr><td> <!-- Preheader --> <div class="email-preheader">Your order has been confirmed ✓</div> <table class="email-container" role="presentation"> <!-- Header --> <tr><td class="email-header"> <img src="logo.png" class="email-logo" alt="Brand"> </td></tr> <!-- Hero --> <tr><td class="email-hero"> <h1 class="email-h1" style="color:#fff;">Order Confirmed! 🎉</h1> <p class="email-p" style="color:rgba(255,255,255,.8);">Order #12345</p> </td></tr> <!-- Body --> <tr><td class="email-body-wrap"> <p class="email-p">Hi Sarah, your order is on its way!</p> <!-- Success callout --> <div class="email-callout-success"> <strong>Estimated delivery: 2–3 business days</strong> </div> <div class="email-spacer-24"></div> <!-- CTA button --> <div class="email-btn-center"> <a href="#" class="email-btn">Track Your Order</a> </div> </td></tr> <!-- Footer --> <tr><td class="email-footer"> <p class="email-legal">© 2026 Brand Inc · 123 Main St</p> <a href="#" class="email-unsubscribe">Unsubscribe</a> </td></tr> </table> </td></tr> </table>
// postcss.config.js const santycss = require('santycss/postcss'); module.exports = { plugins: [ santycss({ content: [ './src/**/*.{html,js,jsx,ts,tsx,vue,svelte}', './pages/**/*.{js,jsx,ts,tsx}', ], safelist: ['animate-spin', 'make-hidden'], // never purge these }), ], };
// vite.config.js import { defineConfig } from 'vite'; import santycss from 'santycss/vite'; export default defineConfig({ plugins: [ santycss({ content: ['./src/**/*.{html,vue,jsx,tsx}'], }), ], });
Purge / Tree-shake API
Use the Node.js API directly for custom build pipelines, CI steps, or scripts.
const { purge, purgeFiles } = require('santycss'); // Purge from a string of HTML/JS const purgedCSS = purge(originalCSS, htmlContent, { safelist: ['animate-spin'], }); // Purge from file globs const purgedCSS = purgeFiles(originalCSS, [ './src/**/*.html', './src/**/*.jsx', ], { safelist: [] });
React / Next.js
// Install npm install santycss // app/layout.tsx (Next.js App Router) import 'santycss/css'; export default function RootLayout({ children }) { return <html><body>{children}</body></html>; } // Usage in any component export default function Card() { return ( <div className="background-white round-corners-16 add-padding-24 add-shadow-md"> <h2 className="set-text-20 text-bold color-gray-900">Hello</h2> <button className="btn btn-primary add-margin-top-16">Click</button> </div> ); }
Vue / Nuxt
// main.js import { createApp } from 'vue'; import 'santycss/css'; import App from './App.vue'; createApp(App).mount('#app'); // nuxt.config.ts export default defineNuxtConfig({ css: ['santycss/dist/santy.css'], }); <!-- MyComponent.vue --> <template> <div class="make-flex align-center gap-16"> <button class="btn btn-primary">Save</button> </div> </template>
Plain HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Option 1: CDN --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/santycss/dist/santy.min.css"> <!-- Option 2: Local file --> <link rel="stylesheet" href="santy.css"> </head> <body class="background-gray-50"> <div class="container add-padding-y-64"> <h1 class="set-text-40 text-bold color-gray-900">Hello, SantyCSS!</h1> <button class="btn btn-primary add-margin-top-24">Get Started</button> </div> </body> </html>