Farvist docs

A lightweight (~20 KB), Sass-powered glassmorphism CSS framework. Frosted surfaces, neon glow, gradients and a free backgrounds library β€” generated from design tokens with @for / @each loops.

MIT Zero dependencies No build step Dark + light

Installation

Drop in one stylesheet β€” no build step. Add the optional 2.5 KB 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>

Or build from the Sass source to customize the tokens:

npm install
npm run dev   # β†’ dist/farvist.css + dist/farvist.min.css

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

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).

.col-md-8
.col-md-4
<div class="row gy-2">
  <div class="col-12 col-md-8">…</div>
  <div class="col-12 col-md-4">…</div>
</div>

Utilities

Spacing, display, flex, text, color and sizing β€” all generated. Spacing follows {m|p}{t e b s x y}-{0–8} with optional -{breakpoint}-.

.mt-3   .px-4   .p-0   .m-md-5   .mx-auto      <!-- spacing -->
.d-flex .justify-content-between .align-items-center .gap-3
.fs-2xl .fw-bold .text-center .text-muted        <!-- type -->
.bg-primary .text-accent .rounded-lg .shadow-lg  <!-- color/shape -->

Backgrounds free Β· exclusive

Mesh gradients, patterns, spotlights and fade-masks β€” one class each. The headline feature Tailwind and Bootstrap make you hand-roll.

.bg-mesh-aurora
.bg-mesh-nebula .bg-drift
.bg-grid .bg-fade
.bg-spotlight-accent
<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).

Buttons

<button class="btn btn-primary">Primary</button>
<button class="btn btn-gradient-primary">Gradient</button>
<button class="btn btn-outline-accent">Outline</button>

Colors: primary secondary success danger warning info accent light dark. Sizes .btn-sm / .btn-lg; full-width .btn-block.

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' });

Feedback

Alerts, callouts and empty states.

Saved
Your changes are live.
Callouts draw the eye to a tip or aside.
πŸ“­

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

NameStatus
AdaActive
MiraAway
  • Inbox
  • Drafts
8.4k
Users
  • Shipped v0.11
    today
  • Docs polish
    earlier
  1. 1Account
  2. 2Plan
  3. 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

Online Failed
<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.

check
x
plus
minus
chevron-down
chevron-right
arrow-right
arrow-left
menu
search
user
users
bell
settings
heart
star
home
mail
lock
eye
download
upload
trash
edit
calendar
clock
info
alert
external
sun
moon
zap
sparkles
code
layers
bot
brain
message
message-dots
cpu
send
mic
stop
refresh
copy
thumbs-up
thumbs-down
wand
paperclip
image
command
terminal
globe
database
link
Is it accessible?
Yes β€” ARIA is wired up automatically by farvist.js.
Does it need a build step?
No β€” one <link> and you're set.
<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 and agent-status indicators β€” all built on the glass system. See the full AI console template.

Chat thread

How can I help?
Assistant Β· now
Scaffold a pricing page.
You
<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

0 / 4000

Agent status

Online Thinking Idle Failed

Streaming messages

After injecting new messages into the DOM, call Farvist.enhance() so any new tooltips, tabs and ARIA get wired up.

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

~2.5 KB, 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/tabpanel roles, roving tabindex, arrow-key nav.
  • Progress bars β€” role="progressbar" + aria-valuenow/min/max.
  • Breadcrumb Β· stepper Β· pagination β€” aria-current on the active item.
  • Forms β€” .is-invalid gets aria-invalid and is linked to its .invalid-feedback via aria-describedby.
  • Tooltips β€” the data-tooltip text 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 exposes aria-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.

Enter a valid email address.
<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-ring token.
  • 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.

β˜… Star on GitHub ← Back to the demo