Farvist docs
A lightweight (~21 KB), Sass-powered glassmorphism CSS framework. Frosted surfaces, neon glow, gradients and a free backgrounds library — generated from design tokens with @for / @each loops.
Installation
Drop in one stylesheet — no build step. Add the optional 8.5 KB (gzip) script for modals, tabs, toasts and the theme toggle.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/farvist/dist/farvist.min.css">
<script src="https://cdn.jsdelivr.net/npm/farvist/assets/farvist.js" defer></script>
Three builds v1.7
Swap the filename in the CDN URL. All three share the same tokens, skins and class names — the docs apply unchanged.
| File | Gzip | What's inside |
|---|---|---|
farvist.min.css | ~21 KB | Everything — all 42 components, utilities, backgrounds, skins. |
farvist-slim.min.css | ~19 KB | The framework without the 11 AI-interface components (chat, prompt, status, prose, tool-call, reasoning, command palette, diff, suggestions, attachment, snippet) — for sites that never render AI conversations. |
farvist-ai.min.css | ~6.6 KB | Only the AI-interface kit (plus tokens, skins, buttons, avatars, icons, toasts) — an add-on for sites already on Tailwind, Bootstrap or custom CSS. No reset, no grid, no utilities; assumes box-sizing: border-box and a browser-default 16px root (the kit is rem-sized); on a light host page wrap the UI in data-theme="light". Tailwind v3 hosts: also load farvist-ai-compat.css after your Tailwind build — v3's un-layered preflight otherwise strips the kit's borders and button styling. Bootstrap hosts need it too — unconditionally. The kit’s own buttons carry class="btn", and Bootstrap’s .btn is un-layered, so it wins: measured against Bootstrap 5.3.3, the send button and every .btn-glass lose their padding, weight, radius, glass fill and border, and button text drops to 1.2:1 on a dark page. The compat file restores all of it. Tailwind v4's preflight is layered and needs nothing. Live demo → |
Or build from the Sass source to customize the tokens — @use only the partials you need for a truly minimal sheet:
npm install
npm run dev # → dist/farvist(.min).css, farvist-slim, farvist-ai
Theming
Everything is driven by --fv-* custom properties. The default is the dark glass theme; add data-theme="light" to <html> to flip every surface at runtime — no recompile.
document.documentElement.setAttribute('data-theme', 'light'); // or remove for dark
Bring your brand — no build step v1.3
Every derived color — gradients, neon glows, mesh backdrops, the body orbs, button hover/active states, soft badge tints, focus rings — now derives from the --fv-* custom properties at runtime. Override a handful of variables and the whole framework re-brands, straight off the CDN:
:root {
--fv-primary: #10b981; /* your brand */
--fv-accent: #a3e635;
--fv-info: #2dd4bf;
/* optional companions when your brand flips brightness: */
--fv-primary-text: #6ee7b7; /* readable tint for text/links on the dark surface */
--fv-primary-contrast: #06281d; /* text on primary-filled buttons/badges */
}
Same for --fv-success, --fv-danger, --fv-warning, --fv-secondary — each accepts an optional --fv-{color}-contrast. Derivations use color-mix(), which is already in Farvist's browser baseline. This also means your AI assistant can re-brand a page by writing five lines of CSS. Prefer a visual tool? Open the Theme Builder →
Skins — prebuilt theme packs v1.4
Five named skins ship built-in, each a small token block on the same data-theme attribute (and each contrast-gated to WCAG AA in CI). Try them on this page:
<html data-theme="synthwave"> <!-- markup… -->
Farvist.theme('synthwave'); // …or JS (persists in localStorage)
<button data-fv-theme-cycle="synthwave,cyber,noir,forest,dawn">Skin</button>
Semantic colors (success / danger / warning) stay constant across skins on purpose — a red error stays red everywhere. Add your own skin by extending the $skins map in Sass, or ship a [data-theme="yourbrand"] block of --fv-* overrides in plain CSS.
Re-theme at build time by configuring the module:
@use 'farvist/scss/farvist' with (
$primary: #00e0ff,
$accent: #ff4dd2,
$glass-blur: 22px
);
Add a key to the $theme-colors map and you instantly get .btn-*, .badge-*, .text-*, .bg-* and more for it — that's the payoff of generating from maps.
Cascade layers — easy overrides
Farvist's CSS is wrapped in cascade layers — @layer reset, base, layout, components, utilities — so utilities beat components by layer order, not !important. The practical win: any CSS you write outside a layer beats all of Farvist, no specificity battles or !important needed.
/* your stylesheet, loaded after farvist.css */
.btn { border-radius: 0; } /* unlayered → wins over Farvist's .btn */
Prefer to keep your overrides organized? Put them in your own layer after utilities.
Browser support: the shipped CSS is autoprefixed (PostCSS + Autoprefixer). Everything works in Chrome/Edge 111+, Safari 16.4+, Firefox 113+ (~early 2023); older browsers degrade gracefully — glass falls back to an opaque surface via @supports, and the color-mix status pulse simply doesn't animate. Full matrix in the readme.
Grid
A 12-column flexbox grid with responsive breakpoints (sm md lg xl xxl).
<div class="row gy-2">
<div class="col-12 col-md-8">…</div>
<div class="col-12 col-md-4">…</div>
</div>
Utilities
Single-purpose helper classes, all generated from the token maps. Most take an optional breakpoint infix — {prop}-{sm|md|lg|xl}-{value} — that applies from that width up (d-md-flex, text-lg-center, col-md-6).
Spacing
Margin (m) and padding (p) on a 0–8 scale, per side: {m|p}{t|e|b|s|x|y}-{0–8}. x=left+right, y=top+bottom, blank=all sides; s/e are start/end (RTL-aware). mx-auto centers.
| Step | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|---|
| rem | 0 | .25 | .5 | .75 | 1 | 1.5 | 2 | 3 | 4 |
.mt-3 .px-4 .p-0 .my-6 .ms-auto .gap-3 .m-md-5
Sizing
.w-25 .w-50 .w-75 .w-100 .w-auto · .h-25….h-100 · .mw-100 (max-width) · .mh-100 (max-height)
Display
.d-none .d-block .d-inline .d-inline-block .d-flex .d-inline-flex .d-grid .d-table — each with breakpoints, so .d-none.d-md-block hides on phones, shows from md up.
Flexbox & alignment
.flex-row .flex-column .flex-wrap .flex-nowrap .flex-fill · .justify-content-{start|center|end|between|around|evenly} · .align-items-{start|center|end|baseline|stretch} · .align-self-* · .order-{0–5} · .gap-{0–8}
<div class="d-flex justify-content-between align-items-center gap-2">…</div>
Typography
Size .fs-xs .fs-sm .fs-base .fs-lg .fs-xl .fs-2xl .fs-3xl .fs-4xl .fs-5xl · Weight .fw-light .fw-normal .fw-medium .fw-semibold .fw-bold .fw-black · Line height .lh-1 .lh-base .lh-lg
Align .text-start .text-center .text-end (+ breakpoints) · Transform .text-uppercase .text-lowercase .text-capitalize · Wrap .text-truncate .text-nowrap .text-break
Colors
.text-{color}, .bg-{color} and .border-{color} for every theme color. All resolve from the runtime --fv-* variables, so they follow a re-brand.
Gradient text .text-gradient .text-gradient-accent .text-gradient-sunset .text-gradient-aurora
Borders & radius
.border .border-0 .border-{top|end|bottom|start} .border-{color} · .rounded .rounded-{sm|md|lg|xl|2xl} .rounded-pill .rounded-circle .rounded-0
Position & layering
.position-{static|relative|absolute|fixed|sticky} · z-index tokens .z-dropdown .z-sticky .z-fixed .z-modal .z-tooltip · .overflow-{auto|hidden|scroll|visible}
Effects
.shadow-{sm|md|lg|xl} .shadow-none · neon .glow .glow-{color} · .opacity-{0…100} (steps of 10) · .hover-lift (raise on hover) · .animate-float (gentle bob, reduced-motion safe)
Coming from Bootstrap
If you know Bootstrap, you already know most of Farvist. The grid, spacing, display, flex and colour utilities use the same class names on purpose — a lot of Bootstrap markup is drop-in. Here's what carries over and what differs.
| Area | Bootstrap | Farvist | Compatibility |
|---|---|---|---|
| Grid | .row .col-md-6 | .row .col-md-6 | identical |
| Spacing | .mt-3 .px-4 | .mt-3 .px-4 | same, scale goes to 8 |
| Display / flex | .d-flex .justify-content-between | .d-flex .justify-content-between | identical |
| Buttons | .btn .btn-primary .btn-lg | .btn .btn-primary .btn-lg | identical |
| Cards, alerts | .card .card-body · .alert-info | .card .card-body · .alert-info | identical |
| Text & colour | .text-center .text-muted .bg-primary | .text-center .text-muted .bg-primary | identical |
| Badges | .badge .bg-primary | .badge .badge-primary | renamed |
| Modal | JS plugin + data-bs-* | native <dialog> + data-fv-open | simpler |
| Theming | Sass rebuild | override --fv-* at runtime | no build step |
The big wins on top: a glass aesthetic, a free backgrounds library, an AI component kit, and runtime re-branding — none of which need a build step.
Backgrounds free · exclusive
Mesh gradients, patterns, spotlights and fade-masks — one class each. The headline feature Tailwind and Bootstrap make you hand-roll.
<section class="bg-mesh-aurora">…</section> <!-- mesh gradient -->
<div class="bg-grid bg-fade">…</div> <!-- pattern, faded at edges -->
<header class="bg-spotlight-primary">…</header> <!-- radial glow -->
Meshes: aurora · sunset · ocean · nebula. Patterns: grid · graph · dots · lines · noise. Modifiers: .bg-fade (put on a decorative layer — it masks children too), .bg-drift (animate a mesh).
Cards & badges
Glass card
Frosted surface with an inner highlight.
badge solid<article class="card card-glow">
<div class="card-body">
<h3 class="card-title">Glass card</h3>
<p class="card-text">…</p>
</div>
</article>
Forms
<label class="form-label">Email</label>
<input class="form-control" type="email">
Modal · Tabs · Toast
These three use the optional JS companion. Modal is a native <dialog>; accordion and dropdown are pure CSS (<details>).
<button data-fv-open="#m">Open</button>
<dialog class="modal" id="m"> … </dialog>
Farvist.toast({ title: 'Saved', variant: 'success' });
Command palette v1.5
The ⌘K menu every modern dev tool and AI app has — type-to-filter, full keyboard nav, and a combobox/listbox ARIA pattern, built on the native <dialog>. Press ⌘K / Ctrl K anywhere on this page, or:
Each .command-item carries data-fv-command — a URL/anchor to navigate to, or any string, which fires an fv:command event you can handle for custom actions. Add data-fv-keywords to match on synonyms.
<button data-fv-open="#cmd">Search <kbd>⌘K</kbd></button>
<dialog class="command" id="cmd" aria-label="Command menu">
<div class="command-search">
<svg class="icon"><use href="…#i-search"/></svg>
<input class="command-input" placeholder="Type a command…">
</div>
<ul class="command-list">
<li class="command-group">Jump to</li>
<li class="command-item" data-fv-command="/docs/">
<svg class="icon">…</svg><span class="command-label">Docs</span>
</li>
</ul>
<div class="command-empty" hidden>No matches.</div>
</dialog>
// custom actions:
document.querySelector('#cmd')
.addEventListener('fv:command', e => run(e.detail.value));
// or open it yourself: Farvist.command('#cmd')
Feedback
Alerts, callouts and empty states.
Nothing here yet.
<div class="alert alert-success"><div class="alert-heading">Saved</div>…</div>
<div class="callout callout-accent">A tip or aside.</div>
<div class="empty-state"><div class="empty-state-icon">📭</div><p>Nothing yet.</p></div>
Data display
| Name | Status |
|---|---|
| Ada | Active |
| Mira | Away |
- Inbox
- Drafts
- Shipped v0.11today
- Docs polishearlier
- 1Account
- 2Plan
- 3Done
<div class="table-responsive"><table class="table table-hover">…</table></div>
<ul class="list-group"><li class="list-group-item">Inbox</li></ul>
<div class="stat-value text-gradient">8.4k</div><div class="stat-label">Users</div>
<ul class="timeline"><li class="timeline-item timeline-primary">
<div class="timeline-marker"></div><div class="timeline-content">…</div></li></ul>
<ol class="stepper"><li class="step is-active"><span class="step-dot">2</span>…</li></ol>
Indicators
<div class="progress"><div class="progress-bar" style="width:60%"></div></div>
<div class="spinner spinner-primary"></div>
<div class="spinner-dots"><span></span><span></span><span></span></div>
<span class="status status-online">Online</span>
<div class="skeleton skeleton-text"></div>
More inputs
A styled range slider and a JS-free segmented control. (The switch is in Forms.)
<input type="range" class="form-range">
<div class="segmented">
<input type="radio" id="d" name="seg" checked><label for="d">Day</label>
<input type="radio" id="w" name="seg"><label for="w">Week</label></div>
Icons & accordion
55 line icons (24×24, sized via font-size or width/height, coloured by currentColor). The AI/chat set is highlighted.
Is it accessible?
Does it need a build step?
<svg class="icon"><use href="assets/icons/farvist-icons.svg#i-home"/></svg>
<details class="accordion-item">
<summary>Question</summary>
<div class="accordion-body">Answer.</div></details>
Chat & AI kit ✦
Components for AI products — a conversation thread, a prompt composer, agent status, and the model-output layer: rendered markdown (.prose), a streaming caret, tool-call cards, reasoning disclosures, citations, code diffs, prompt suggestions and attachments. See the full AI console template, or the same kit driving an operator UI in the trading bot and AI cluster consoles.
Chat thread
<div class="chat">
<div class="message"> <!-- assistant (left) -->
<span class="avatar avatar-sm avatar-accent">AI</span>
<div class="message-body">
<div class="message-bubble">How can I help?</div>
<div class="message-meta">Assistant</div>
</div>
</div>
<div class="message message-out"> … </div> <!-- user (right) -->
</div>
<!-- typing dots -->
<span class="typing"><span></span><span></span><span></span></span>
Prompt composer
Agent status
Prose — rendered model output
Bubbles preserve raw newlines (white-space: pre-wrap) for plain text. When you render markdown to HTML, wrap it in .prose (compact: .prose-sm) — it restores normal flow and styles headings, lists, tables and images at content scale.
<div class="message-bubble">
<div class="prose prose-sm"> …rendered markdown HTML… </div>
</div>
Streaming caret & message actions
Add .streaming to a bubble while tokens arrive — a pulsing caret marks live output (static under reduced motion). .message-actions is a copy/vote row that reveals on hover or focus (always visible on touch). A bare data-fv-copy in the row copies the message's bubble text and flashes the button green.
<div class="message-bubble streaming">…tokens so far…</div>
<div class="message-actions">
<button class="btn btn-glass btn-sm" data-fv-copy aria-label="Copy">…</button>
</div>
Tool calls
An agent's tool invocation as a compact card. The state classes tint the rail — keep the .tool-call-status text so meaning never relies on colour alone.
<div class="tool-call tool-call-done">
<div class="tool-call-header">
<svg class="icon" aria-hidden="true"><use href="…#i-terminal"/></svg>
<span class="tool-call-name">search_docs</span>
<span class="tool-call-status">Done</span>
</div>
<div class="tool-call-args">query: "backgrounds library"</div>
<div class="tool-call-result">3 sections matched.</div>
</div>
Reasoning
A collapsible "thinking" disclosure on the native <details> element — keyboard and screen-reader accessible with zero JS.
Thought for 12 seconds
<details class="reasoning">
<summary class="reasoning-summary">Thought for 12 seconds</summary>
<div class="reasoning-body">…model thinking…</div>
</details>
Citations
Superscript .cite chips link claims to a .sources footnote list — the RAG answer pattern.
…to blur<a class="cite" href="#src-1">1</a>
<ol class="sources">
<li id="src-1"><a href="…">docs/backgrounds</a></li>
</ol>
Diff view v1.6
The code-change display AI coding assistants live in. The +/− characters stay in the content, so meaning never rides on colour alone; the tints follow the runtime tokens.
@@ -1,3 +1,3 @@
:root {
- --fv-primary: #6d4af5;
+ --fv-primary: #10b981;
<div class="diff">
<div class="diff-header">src/theme.css
<span class="diff-stat"><span class="diff-stat-add">+1</span> <span class="diff-stat-del">−1</span></span></div>
<pre class="diff-body"><code><span class="diff-line diff-hunk">@@ -1,3 +1,3 @@</span>
<span class="diff-line diff-del">- old</span>
<span class="diff-line diff-add">+ new</span></code></pre>
</div>
Suggestions & attachments v1.6
Prompt-starter chips (.suggestion) and file pills (.attachment) for the composer.
<div class="suggestions">
<button class="suggestion">Summarize this page</button>
</div>
<span class="attachment">
<svg class="icon">…#i-paperclip</svg>
<span class="attachment-name">report.pdf</span>
<span class="attachment-meta">2.4 MB</span>
<button class="attachment-remove" aria-label="Remove report.pdf">×</button>
</span>
Named code blocks v1.6
Give a snippet the filename bar assistants use for generated files — hand-author the wrap and farvist.js still adds the copy button.
Farvist.toast({ title: 'Deployed', variant: 'success' });
<div class="snippet-wrap">
<div class="snippet-header">
<span class="snippet-title">app.js</span>
<span class="snippet-lang">javascript</span></div>
<pre class="snippet"><code>…</code></pre>
</div>
Streaming messages (JS)
Farvist.stream(el, text) types text into an element with the .streaming caret and re-runs enhance() when done (instant under reduced motion). Or inject markup yourself and call Farvist.enhance().
await Farvist.stream(bubble, 'Here is the answer, streamed word by word…');
chat.insertAdjacentHTML('beforeend', bubbleHTML);
Farvist.enhance(); // re-run progressive enhancement
Use Farvist with your AI ✦
Farvist is built to be generated correctly by AI assistants. Point your tool at the machine-readable context, or paste the primer below.
- llms-full.txt — every convention, component, icon and copy-paste recipe. Paste this into Cursor / Claude / ChatGPT.
- ai-context.json — machine-readable catalog (components, utilities, icons, recipes).
- llms.txt — the concise index (llms.txt convention).
- farvist.cursorrules — drop into your project as
.cursorrules.
Paste-in primer
You are an expert in Farvist, a glassmorphism CSS framework.
Prefer Farvist classes (components + utilities) over hand-written CSS.
Dark by default; add data-theme="light" to switch; give the page a
bg-mesh-* background so the glass reads. Colors: primary, accent, success…
(suffixes: btn-primary, text-accent). Spacing 0–7 (p-4 = 1rem).
Icons: <svg class="icon"><use href="…#i-bot"/></svg>.
Full context: https://farvist.com/llms-full.txt
JS companion
~8.5 KB gzip, no dependencies. It auto-applies ARIA to tabs & progress bars and wires these data-attributes:
data-fv-open="#id" // open a <dialog class="modal">
data-fv-dismiss // close the nearest dialog
data-fv-tab="#panel" // switch tabs (arrow-key nav included)
data-fv-theme-toggle // flip dark / light
data-fv-nav-toggle // toggle the mobile navbar
<pre class="snippet"> // gets a copy button (or use any [data-fv-copy])
Farvist.toast({ title, message, variant, timeout });
Farvist.copy(text); // copy text to the clipboard
Farvist.enhance(); // re-wire after injecting DOM dynamically
Accessibility
Farvist aims to be accessible by default. The optional farvist.js companion progressively enhances your markup on load, adding the ARIA that's tedious to hand-write — drop it in and most of the list below is automatic.
Automatic (via farvist.js)
- Tabs — full
tablist/tab/tabpanelroles, roving tabindex, arrow-key nav. - Progress bars —
role="progressbar"+aria-valuenow/min/max. - Breadcrumb · stepper · pagination —
aria-currenton the active item. - Forms —
.is-invalidgetsaria-invalidand is linked to its.invalid-feedbackviaaria-describedby. - Tooltips — the
data-tooltiptext is exposed to screen readers and shows on keyboard focus. - Toasts — announced via a live region;
variant:'danger'is assertive (role="alert"), others polite (role="status"). - Modal — native
<dialog>(focus trap + Esc); the navbar hamburger exposesaria-expanded.
Skip link
Make it the first element in <body>; it stays hidden until focused, then pins to the top-left.
<a class="skip-link" href="#main">Skip to content</a>
<main id="main" tabindex="-1"> … </main>
Form validation — try tabbing to the field
Mark the control .is-invalid and put the message in a sibling .invalid-feedback; the JS wires the rest.
<label class="form-label" for="email">Email</label>
<input class="form-control is-invalid" id="email">
<div class="invalid-feedback">Enter a valid email.</div>
<!-- JS adds aria-invalid + aria-describedby -->
Good to know
- Tooltips describe, they don't name — give icon-only controls their own
aria-label. - Pagination — wrap it in
<nav aria-label="Pagination">and label the prev/next arrows. - Focus is always visible for keyboard users; restyle it via the
--fv-focus-ringtoken. - Reduced motion — animation and transition are suppressed under
prefers-reduced-motion: reduce.
Contribute
Farvist is open source (MIT). Issues and PRs welcome. The framework lives under scss/, generated from token maps in scss/abstracts/_variables.scss.