Skip to content

FloKuersten/farvist

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Farvist · glass edition

CI npm minzipped size license dependencies

A lightweight, Sass-powered CSS framework with a futuristic, frosted-glass aesthetic — a customizable alternative to Bootstrap and Tailwind. Every value is a design token in a Sass map, and the utility classes are generated automatically with @for and @each loops.

  • 🪟 Glassmorphism — frosted backdrop-filter surfaces, translucent fills, inner highlights and deep shadows on every component.
  • 🌈 Neon & gradients — gradient buttons, gradient text, and colored glow utilities generated from token maps.
  • 🌌 Background library — mesh gradients, patterns, spotlights and fade-masks in one class (.bg-mesh-aurora, .bg-grid, .bg-spotlight, .bg-fade). A free feature Tailwind and Bootstrap make you hand-roll.
  • 🌗 Dark & light themes — dark "space" theme by default; flip data-theme="light" on <html> to retheme at runtime via --fv-* custom properties.
  • ⚙️ Auto-generated utilities — spacing, display, flex, color, glow, gradient, sizing and more, produced by loops instead of hand-writing hundreds of rules.
  • 🧩 30+ glass components — buttons, badges, alerts, cards, forms, navbar, plus modal, dropdown, tabs, accordion, tooltip, toast, progress, spinner, skeleton, switch, avatar, breadcrumb, pagination, table and chips.
  • 🎨 Assets included — a 55-icon SVG set (currentColor-driven), decorative SVGs (mesh, blob, grid, dots, logo) and a 2.5 KB optional JS companion for the interactive bits.
  • 🖼️ Premade templates — a glass dashboard and a copy-paste block gallery in examples/.
  • 📐 12-column flexbox grid with responsive columns and offsets.
  • 🪶 ~20 KB gzipped (127 KB minified) — and shrinks further when you trim the token maps.
  • 🦾 Modern & accessible@use/@forward modules (no deprecated @import), :focus-visible rings, prefers-reduced-motion support, and a @supports fallback for browsers without backdrop-filter.

Quick start

Install from npm

npm install farvist

Import the CSS (and the optional 2.5 KB JS) through your bundler:

import 'farvist/dist/farvist.min.css';
import 'farvist/assets/farvist.js'; // optional — modals, tabs, toasts, theme toggle

Or pull in the Sass source to theme it from the token maps (with node_modules on your Sass load path):

@use 'farvist/scss/farvist';

Use the compiled CSS

Via CDN (no build step — live on jsDelivr and unpkg):

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/farvist/dist/farvist.min.css" />
<!-- optional 2.5 KB companion for modals, tabs, toasts, theme toggle -->
<script src="https://cdn.jsdelivr.net/npm/farvist/assets/farvist.js" defer></script>

Or use the local build:

<link rel="stylesheet" href="dist/farvist.css" />

The framework defaults to the dark glass theme. Open index.html for a full live demo (with a dark/light toggle). For best results give the page a rich background — Farvist paints radial "orbs" behind the content so the glass has something to blur.

Build from source

You need Node.js. Dart Sass is pulled in as a dev dependency.

npm install        # install Dart Sass
npm run dev        # build dist/farvist.css (expanded) + dist/farvist.min.css (minified)
npm run watch      # rebuild on save
Script What it does
npm run build Compile expanded dist/farvist.css
npm run build:min Compile minified dist/farvist.min.css
npm run dev Both of the above
npm run watch Recompile on every change

Theming

Dark / light at runtime

The whole system is driven by --fv-* CSS custom properties. The default :root is the dark theme; a [data-theme="light"] block overrides the surface variables. Toggle it with one line of JS:

document.documentElement.setAttribute('data-theme', 'light'); // or remove it for dark

Components reference the variables (--fv-body-bg, --fv-glass-bg, --fv-glass-border, --fv-muted, …) so they retheme instantly — no recompile.

Bring your brand — runtime re-branding (v1.3)

Every derived color — gradients, neon glows, mesh backdrops, body orbs, button hover/active states, soft tints, focus rings — derives from the --fv-* custom properties at runtime via color-mix(). 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 with an optional --fv-{color}-contrast. CI enforces this with a theming gate — no component rule may bake a brand color.

Skins — prebuilt theme packs (v1.4)

Five named skins ship built-in, each contrast-gated to WCAG AA in CI: synthwave · cyber · noir · forest · dawn (light).

<html data-theme="synthwave">
Farvist.theme('synthwave');   // applies + persists (localStorage); theme('dark') resets
<button data-fv-theme-cycle="synthwave,cyber,noir,forest,dawn">Skin</button>

Add your own by extending the $skins Sass map — or ship a plain-CSS [data-theme="yourbrand"] block of --fv-* overrides.

Re-theme at build time

Because everything is a token, you can recolor the whole framework by configuring the module:

// my-theme.scss
@use 'farvist/scss/farvist' with (
  $primary:    #00e0ff,   // your neon
  $accent:     #ff4dd2,
  $glass-blur: 22px,
  $border-radius: 1rem
);

Or edit the maps directly in scss/abstracts/_variables.scss:

$theme-colors: (primary, secondary, success, danger, warning, info, accent, light, dark);
$spacers:      (08);                 // drives .m-*/.p-*
$font-sizes:   (xs … 5xl);              // drives .fs-*
$gradients:    (primary, accent, sunset, aurora);   // drives .bg-gradient-*, .btn-gradient-*, .text-gradient-*
$glows:        (primary, accent, info, success, danger, warning);  // drives .glow-*
$grid-breakpoints: (xs:0, sm:576, md:768, lg:992, xl:1200, xxl:1400);

Add a key to $theme-colors and you instantly get .btn-*, .badge-*, .alert-*, .text-*, .bg-*, .border-* for it — that's the payoff of generating from maps.

Want it smaller? Remove a breakpoint from $grid-breakpoints or a step from $spacers and recompile — the generators emit fewer classes instantly.


How the generators work

This is what the project is really about. Two Sass loops do the heavy lifting.

@for — numeric scales

The 12-column grid and the opacity scale are produced by counting:

@for $i from 1 through $grid-columns {
  .col-#{$i} {
    flex: 0 0 auto;
    width: math.percentage(math.div($i, $grid-columns));
  }
}
// → .col-1 { width: 8.333% } … .col-12 { width: 100% }

@each — walking the token maps

Spacing utilities come from nested @each loops over breakpoints × properties × scale × sides:

@each $bp in map.keys($grid-breakpoints) {
  $infix: breakpoint-infix($bp);               // '' , '-sm', '-md', …
  @include media-up($bp) {
    @each $prop, $abbrev in (margin: 'm', padding: 'p') {
      @each $size, $length in $spacers {
        @each $side, $targets in $spacing-sides {
          .#{$abbrev}#{$side}#{$infix}-#{$size} { /**/ }
        }
      }
    }
  }
}
// → .m-0, .mt-3, .px-4, .py-lg-0, .me-2, … (the full responsive matrix)

The glass look itself is a mixin reading runtime variables, so dark/light just works:

@mixin glass($strong: false) {
  background-color: var(--fv-glass-bg);
  backdrop-filter: blur(var(--fv-glass-blur)) saturate(var(--fv-glass-saturate));
  border: 1px solid var(--fv-glass-border);
  box-shadow: var(--fv-shadow-lg), inset 0 1px 0 rgba(255,255,255,.1);
}

Class reference (cheatsheet)

Glass & effects

Class Description
.glass, .glass-strong Frosted surface (light/strong)
.glow, .glow-{primary|accent|info|success|danger|warning} Neon glow shadow
.text-glow Neon halo on text
.bg-gradient-{primary|accent|sunset|aurora} Gradient fill
.text-gradient, .text-gradient-{name} Gradient-clipped text
.bg-animated Slowly drifting gradient (pair with .bg-gradient-*)
.hover-lift, .animate-float Motion helpers

Backgrounds

Class Description
.bg-mesh-{aurora|sunset|ocean|nebula} Multi-orb mesh gradient backdrop
.bg-mesh Default mesh (aurora)
.bg-grid, .bg-graph, .bg-dots, .bg-lines, .bg-noise Theme-aware patterns
.bg-pattern-sm, .bg-pattern-lg Pattern tile-size modifiers
.bg-spotlight, .bg-spotlight-{color} Radial glow backdrop
.bg-fade, .bg-fade-b, .bg-fade-x Fade a background to the edges. Uses mask-image, which fades children too — put it on a dedicated decorative layer, and best with the transparent patterns (.bg-grid.bg-fade)
.bg-drift Slowly pan a mesh/gradient (reduced-motion safe)

Mesh stops come from the $bg-meshes map and reference your theme colors, so they restyle with the palette.

Components

Buttons.btn + .btn-{color} / .btn-outline-{color} / .btn-gradient-{name} / .btn-glass / .btn-link / .btn-sm / .btn-lg / .btn-block

Badges.badge + .badge-{color} / .badge-soft-{color} / .badge-pill

Alerts.alert-{color} with .alert-heading / .alert-link

Cards.card (.card-glow, .card-solid, .card-header/-body/-footer, .card-title/-subtitle/-text, .card-img-top)

Forms.form-label .form-control .form-select .form-text · .form-check (.form-check-input .form-check-label) · .input-group (.input-group-text) · validation .is-valid/.is-invalid + .valid-feedback/.invalid-feedback

Nav.navbar .navbar-brand .navbar-nav .nav-link

Modal (native <dialog> + JS) — .modal (.modal-header/-title/-body/-footer/-close)

Dropdown (native <details>) — .dropdown .dropdown-menu (.dropdown-menu-end) .dropdown-item .dropdown-divider

Tabs (JS) — .tabs .tab .tab-panel (toggle with data-fv-tab="#panel")

Accordion (native <details>, no JS) — .accordion-item .accordion-body

Tooltip (CSS-only) — data-tooltip="text" on any element

Toast (JS) — .toast .toast-{color} (.toast-title/-message/-close), spawn via Farvist.toast()

Table.table .table-hover .table-striped .table-responsive

Progress.progress .progress-bar .progress-{color} .progress-striped .progress-animated

Spinner.spinner .spinner-{sm|lg|color} · .spinner-dots

Skeleton.skeleton .skeleton-{text|title|avatar|btn}

Switch.switch .switch-track .switch-thumb

Avatar.avatar .avatar-{sm|lg|xl|color} · .avatar-status[-busy|-away] · .avatar-group

Chip.chip .chip-{color} .chip-close

Breadcrumb / Pagination.breadcrumb .breadcrumb-item · .pagination .page-item .page-link

Stepper.stepper .step (.is-active / .is-done) .step-dot .step-label

Timeline.timeline .timeline-item (.timeline-{color}) .timeline-marker .timeline-content

Segmented (radio, no JS) — .segmented + input/label pairs · Rating.rating (+ .rating-empty)

Stat.stat-value .stat-label .stat-trend (-up/-down) · Range.form-range

Empty state.empty-state .empty-state-icon/-title/-text · List group.list-group .list-group-item

Callout.callout .callout-{color} .callout-title

Chat (AI).chat .message (.message-out) .message-body .message-bubble .message-meta .message-actions · .typing · .streaming (live caret) · citations: .cite + .sources

Prompt composer (AI).prompt .prompt-field (auto-sizing) .prompt-actions .prompt-meta · Agent status.status .status-{online|busy|idle|error}

Prose (AI).prose / .prose-sm: wrap rendered LLM markdown so headings, lists, bare tables and images read at content scale (bubbles preserve raw newlines otherwise)

Tool call (AI).tool-call (.tool-call-{running|done|error}) .tool-call-header/-name/-status/-args/-result · Reasoning.reasoning on native <details> (.reasoning-summary .reasoning-body)

Theme colors: primary · secondary · success · danger · warning · info · accent · light · dark.

Icons, assets & JavaScript

A 55-icon SVG sprite ships in assets/icons/. Icons inherit currentColor, so they take the text color (and any .text-glow):

<svg class="icon"><use href="assets/icons/farvist-icons.svg#i-bell"/></svg>
<svg class="icon icon-lg text-accent"><use href="assets/icons/farvist-icons.svg#i-star"/></svg>

Sizes: .icon (1em) · .icon-sm · .icon-lg · .icon-xl. Decorative SVGs (logo.svg, patterns/mesh.svg, blob.svg, grid.svg, dots.svg) live in assets/, and theme-aware CSS patterns are built in: .bg-grid .bg-dots .bg-noise.

The optional 2.5 KB companion powers the interactive components — drop it in with defer:

<script src="assets/farvist.js" defer></script>

It wires modals (data-fv-open="#id" / data-fv-dismiss), tabs (data-fv-tab), theme toggling (data-fv-theme-toggle), dropdown outside-click close, and toasts:

Farvist.toast({ title: 'Saved', message: 'All good.', variant: 'success', timeout: 4000 });

Everything else (accordion, dropdown, tooltip, switch, progress…) is pure CSS and needs no JS.

Layout

.container / .container-fluid · .row · .col, .col-auto, .col-{1–12}, .col-{sm…xxl}-{1–12} · .offset-{0–11} · .g-* .gx-* .gy-*

Spacing — {property}{sides}{-breakpoint}-{size}

m = margin, p = padding · sides t e b s x y (or blank for all) · size 0–8 · optional -sm…-xxl · negatives m-n3 · centering mx-auto

.mt-3   .px-4   .p-0   .m-md-5   .py-lg-0   .mx-auto   .mb-n2

Display, flex, type, color, borders, sizing, position

.d-{none|block|flex|grid|…} (responsive) · .flex-{row|column|wrap} .justify-content-* .align-items-* .gap-* · .h1.h6 (heading scale on any element) .fs-{xs…5xl} .fw-{light…black} .text-{start|center|end} .text-truncate · .text-{color|muted|body} .bg-{color|surface} .border-{color} · .border .rounded-{sm…2xl|pill|circle} .shadow-{sm…xl} · .w-{25…100} .vh-100 · .position-* .sticky-top .fixed-top .z-* .opacity-{0…100}


For AI assistants

Farvist ships machine-readable context so AI coding tools (Cursor, Claude, Copilot) generate correct markup:

  • llms-full.txt — every convention, component, icon, and copy-paste recipe (whole sections: login, pricing, chat UI, dashboard shell…). Paste it into Cursor / Claude / ChatGPT.
  • ai-context.json — machine-readable catalog (components, utility families, 55 icons, recipes).
  • llms.txt — concise index (the llms.txt convention).
  • farvist.cursorrules — drop into your project as .cursorrules.

robots.txt welcomes the AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended…) and every page links /llms.txt. The catalog is regenerated from the compiled CSS + icon sprite on every build (npm run build:ai) and shipped in the npm package.

Project structure

scss/
├── farvist.scss               # entry point — @use's every layer in cascade order
├── abstracts/               # no CSS output — tokens + tools
│   ├── _variables.scss      #   design tokens incl. glass/glow/gradient maps
│   ├── _functions.scss      #   color(), spacer(), breakpoint helpers, YIQ contrast
│   ├── _mixins.scss         #   media-up(), glass(), button-variant(), visually-hidden()
│   └── _index.scss          #   @forward barrel  →  @use '../abstracts' as *
├── base/                    # reset, :root vars + dark/light themes, typography
├── layout/                  # container + 12-col flexbox grid
├── components/              # 20 partials: buttons … modal, dropdown, tabs, toast, …
└── utilities/               # generated helper classes
    ├── _spacing.scss        #   the nested-@each spacing matrix
    ├── _utilities.scss      #   display, flex, text, color, border, sizing, …
    ├── _effects.scss        #   glass, glow, gradient, motion + @supports
    └── _backgrounds.scss    #   mesh gradients, patterns, spotlights, fade-masks
assets/
├── farvist.js            # 2.5 KB optional companion (modal, tabs, toast, theme)
├── logo.svg                 # wordmark + gradient mark
├── icons/farvist-icons.svg   # 55-icon sprite (currentColor)
└── patterns/                # mesh, blob, grid, dots decorative SVGs
examples/
├── dashboard.html           # full glass dashboard template
└── blocks.html              # copy-paste sections (hero, pricing, auth, …)
dist/                        # compiled output (committed for convenience)
index.html                   # live demo with a dark/light toggle

The architecture follows the 7-1 pattern and Sass's modern module system: each partial pulls in what it needs with @use '../abstracts' as *;.


Browser support

Modern evergreen browsers. The shipped dist/*.css is autoprefixed (via PostCSS + Autoprefixer against the browserslist in package.json), so Safari's -webkit-backdrop-filter, Firefox's -moz- flex-gap/appearance, and other vendor prefixes are added for you.

Baseline (everything works): Chrome/Edge 111+, Safari 16.4+, Firefox 113+ (~early 2023) — set by @layer (Mar 2022) and color-mix(). Below that it degrades gracefully:

Feature Needs Below baseline
Cascade layers (@layer) Chrome 99 · Safari 15.4 · Firefox 97 utilities still win via source order
backdrop-filter glass Chrome 76 · Safari 9 (-webkit-) · Firefox 103 opaque surface via @supports fallback
color-mix() (status pulse ring) Chrome 111 · Safari 16.2 · Firefox 113 dot shows, ring just doesn't animate
field-sizing (auto-grow textarea) Chrome 123+ fixed min/max-height

Building from the SCSS source instead of the shipped CSS? Run Autoprefixer on your output, or rely on the dist/ files.

License

MIT — do whatever you like.

About

A lightweight glassmorphism CSS framework with a free backgrounds library, 30+ components and dark/light themes.

Topics

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors