The component library

Everything Facet ships, live: every token, component, block, template and app-feel behaviour, with its exact copy-paste code and the same instructions an AI reads. Pick a category to browse its pieces as cards, or jump straight to anything from the index.

Fonts

Eighteen type roles, one per job. The core seven: headings, body text, code and labels, quotes, long-form reading, big numbers and a handwritten pen. The extended set: a loud hero display, a signature script, a typewriter, a receipt printer, a real barcode, a pixel face, a children's face, and native faces for Japanese, Chinese, Korean and Hindi (Russian is covered by the core faces). The theme picks the actual fonts; a page only asks for the role, and each card names the font the active theme chose.

--font-heading

The quick brown fox jumps over the lazy dog 0123456789 & ?! @ # % * { } </>

Used for: Page titles · section headings · hero statements · card titles · dialog headings.

--font-body

The quick brown fox jumps over the lazy dog 0123456789 & ?! @ # % * { } </>

Used for: Running text · buttons · form labels · menus · lists · table cells.

--font-mono

The quick brown fox jumps over the lazy dog 0123456789 & ?! @ # % * { } </>

Used for: Code blocks · inline code · keyboard keys · eyebrow labels · technical captions · token names.

--font-quote

The quick brown fox jumps over the lazy dog 0123456789 & ?! @ # % * { } </>

Used for: Pull quotes · blockquotes · testimonials · callouts · epigraphs.

--font-reading

The quick brown fox jumps over the lazy dog 0123456789 & ?! @ # % * { } </>

Used for: Article paragraphs · essays · long documentation · about pages · newsletters.

--font-numeric

The quick brown fox jumps over the lazy dog 0123456789 & ?! @ # % * { } </>

Used for: KPI stats · prices · big results · countdowns · chart figures.

--font-hand

The quick brown fox jumps over the lazy dog 0123456789 & ?! @ # % * { } </>

Used for: Margin notes · hand annotations · sticky notes · rough work · casual asides · doodled labels.

--font-hero

The quick brown fox jumps over the lazy dog 0123456789 & ?! @ # % * { } </>

Used for: One-word heroes · posters · launch screens · wordmarks · big statements. Digits shown in the numeric face — the hero cut ships letters only.

--font-signature

Tanishk Sharma

Used for: Sign-off lines · letters · certificates · invoices · greeting endings.

--font-typewriter

The quick brown fox jumps over the lazy dog 0123456789 & ?! @ # % * { } </>

Used for: Memos · legal drafts · screenplays · letterheads · retro notices.

--font-receipt

The quick brown fox jumps over the lazy dog 0123456789 & ?! @ # % * { } </>

Used for: Receipts · order confirmations · tickets · counters · timestamps.

--font-barcode

FACET-0123456789

Used for: Tickets · invoices · shipping labels · passes — the text IS a scannable Code 128 barcode.

--font-pixel

The quick brown fox jumps over the lazy dog 0123456789 & ?! @ # % * { } </>

Used for: Retro UIs · game screens · loading states · badges · easter eggs.

--font-children

The quick brown fox jumps over the lazy dog 0123456789 & ?! @ # % * { } </>

Used for: Kids' products · playful onboarding · stickers · game menus · celebration screens.

--font-japanese

いろはにほへと ちりぬるを 0123456789 & ?!

Used for: Japanese headings and accents (data-language variants) · traditional brush, formal.

--font-chinese

视野无限广 窗外有蓝天 0123456789 & ?!

Used for: Chinese headings and accents · regular-script brush, traditional.

--font-korean

다람쥐 헌 쳇바퀴에 타고파 0123456789 & ?!

Used for: Korean headings and accents · brush calligraphy.

--font-devanagari

सारे जहाँ से अच्छा 0123456789 & ?!

Used for: Hindi and Devanagari headings and accents · traditional book hand, elegant.

/* Components never name a face — they ask for the role. */
h1, h2, h3 { font-family: var(--font-heading); }
body        { font-family: var(--font-body); }
code, kbd   { font-family: var(--font-mono); }
blockquote  { font-family: var(--font-quote); }
article p   { font-family: var(--font-reading); }
.big-number { font-family: var(--font-numeric); }
.margin-note { font-family: var(--font-hand); }
.sign-off   { font-family: var(--font-signature); }
.ticket-id  { font-family: var(--font-barcode); }
:lang(ja)   { font-family: var(--font-japanese); }

Typography

The scale in use, as a real page of writing. Every block below is a raw HTML tag styled by the base layer; the mono tag under each names the token doing the work. Each font stack ends in a system fallback, so text renders instantly and survives a font failing to load.

Money, made concrete --text-display · hero statements and big numbers

A heading that opens the page --text-h1 · one per page

Body text carries almost every word on any page, set at a comfortable reading measure of 65 characters with a relaxed line height. It holds strong text, a link with a quiet underline, inline code, and a keyboard key like Esc without breaking rhythm. --text-body · --leading-body 1.6

A section heading inside the page --text-h2

  • Points under a heading sit at body size
  • With four pixels of space between lines
  • And the list marker hanging in the padding

A third-level heading, interspersed --text-h3

Headings take their own face (--font-heading) at --weight-heading, with line-height and letter-spacing that tighten as the type grows — display and h1 tightest, h3–h6 snug — which is what keeps the whole page feeling like one voice.

A quote steps aside from the flow: indented, muted, italic, with the accent as its spine. blockquote

The eyebrow label .eyebrow · --text-caption, --weight-strong, --tracking-wide caps — the small thick label above a heading or a menu group

Small text handles secondary lines: bylines, helper notes, legal asides that still deserve reading. --text-footnote


A caption or footnote, the finest print on the scale — image credits, field hints, the words under a result. --text-caption · --text-muted

<h1>A heading that opens the page</h1>
<p>Body text at a comfortable measure, holding <strong>strong text</strong>,
  <a href="#">a link</a>, inline <code>code</code> and a key like <kbd>Esc</kbd>.</p>
<blockquote>A quote steps aside from the flow.</blockquote>
<p><small>Small text for secondary lines.</small></p>

Color

The color system: a neutral base plus three accent ranks, shown as the same interface in light and dark. Components pick ranks, never raw colors, so one theme block restyles everything.

Beside the ranks sits the vivid palette — five bright decorative colors named by rank, like the accents: red, yellow, green, blue, purple. Decoration only — card tints (mixed into the surface), charts, playful accents — never semantic status; a theme may re-tune them. The raw brights are fills-only; when the palette must write — a tinted label, a stat on a washed card — each color carries a text-safe companion, the same hue at readable contrast in light and dark.

Every value lives once in facet.css as a variable named by role — --surface, never --gray-100 — so a theme is one block of overrides and nothing downstream changes. Click any swatch below to copy its token.

  • --color-1
  • --color-2
  • --color-3
  • --color-4
  • --color-5
  • --color-1-text
  • --color-2-text
  • --color-3-text
  • --color-4-text
  • --color-5-text

Light

Ink on paper. Muted text steps back for hints and captions.

  • --background
  • --surface
  • --text
  • --text-muted
  • --border
  • --accent-1
  • --accent-2
  • --accent-3

Saved ✓ · Expiring soon · Failed · 3 updates

Dark

Paper on ink. Muted text steps back for hints and captions.

  • --background
  • --surface
  • --text
  • --text-muted
  • --border
  • --accent-1
  • --accent-2
  • --accent-3

Saved ✓ · Expiring soon · Failed · 3 updates

Custom accent — the override recipe below, running live: this row overrides accent-1's four tokens on its own container, and every component using the rank follows.

The code is the custom-accent recipe: your own brand color on any accent rank, one small block of CSS, a supported feature. Override a rank's four tokens (the color, its hover, its pressed, and the on-color for text sitting on it) on :root for the whole page or on any element for a subtree, and check the on-color still passes AA. facet.set({"--accent-1": "..."}) is the same override applied live at runtime.

/* Your accent, one block. Rank tokens only — every component follows. */
:root {
  --accent-1: #0F6FDE;
  --accent-1-hover: #0B5FC2;
  --accent-1-pressed: #0850A6;
  --on-accent-1: #FFFFFF;
}

Spacing

Spacing is named by intent, not by number: reach for --space-card or --space-section, never a step on a scale. One global control — data-density="small|medium|large" — tightens or opens the whole system at once, and a theme sets its own rhythm. Below, real pieces sit on a tinted ground; the tint showing through is the token at work.

The full set, each named for where it belongs: --space-tight (bound pairs like a label and its field), --space-control (inside buttons and inputs), --space-inline (row gaps), --space-stack (default gap between blocks), --space-card (card padding), --space-page (page margins), --space-section (between sections), --space-hero (the biggest breaks) and --space-pin (the fixed 20px inset a viewport-pinned panel keeps from the screen edges — exact pixels, never density-scaled, so pinned panels fit exactly and never move with the scroll). Container widths cap the horizontal rhythm: --width-narrow 40rem for prose and calculators, --width-default 64rem for most pages, --width-wide 80rem for dashboards.

Gaps inside a control row · --space-control

Card padding · --space-card

The card's content box. Everything between this edge and the tinted edge is --space-card of padding.

Stack gap between fields · --space-stack

Field one
Field two
Field three

Between page sections · --space-section

The end of one section
The start of the next
<section class="card stack">      <!-- --space-card padding, --space-stack between blocks -->
  <h2>Card title</h2>
  <p class="row">                  <!-- --space-inline between the buttons -->
    <button class="btn btn-primary">Save</button>
    <button class="btn">Cancel</button>
  </p>
</section>

Shape and elevation

Small radii on controls, medium on cards, large on overlays, pill for chips and thumbs. Shadows stay subtle and flat in every theme. How things move is its own system — see Motion just below.

  • --radius-control
  • --radius-panel
  • --radius-card
  • --radius-pill
  • --shadow-raised
  • --shadow-floating
  • --shadow-overlay
/* Radii and shadows by role — a theme retunes them all at once. */
.panel   { border-radius: var(--radius-card); box-shadow: var(--shadow-raised); }
.menu    { border-radius: var(--radius-panel); box-shadow: var(--shadow-overlay); }
.chip    { border-radius: var(--radius-pill); }

Motion tokens

How everything moves, as one system: three durations and three easing curves that every component reads, plus one personality switch — Lively, Calm or Off — that retunes them all at once. The parallax, shine and idle drift ride the same engine, and reduced motion always wins.

Button press

Hold a button down, then let go — it sinks under the finger and springs back on release. The second one also fires a toast, so you can watch an arrival and exit.

Speed & easing

Three dots, one per duration token, each on its own easing curve — fast is 150ms, normal 300ms, slow 600ms. Press Replay; switch the personality above and the same dots run differently.

--duration-fast · --ease-out

--duration-normal · --ease-in-out

--duration-slow · --ease-spring

Always looping

The spinner and the loading shimmer never stop, by design.

The ambient engine

Parallax and shine on the cards below, driven by one source. Idle is the default: it loops on its own every few seconds and nothing follows you. The third mode follows the device — your cursor here on a desktop or trackpad, the tilt of a phone or tablet in your hands (iPhone and iPad ask permission) — and plays the idle loop whenever you go still.

data-parallax="10"

I drift with the motion

data-parallax="22"

I drift further

data-shine

Light travels across me
/* Anything you animate reads the same tokens the library uses. */
.panel { transition: box-shadow var(--duration-fast) var(--ease-out); }
.sheet { transition: translate var(--duration-slow) var(--ease-spring); }

<!-- One attribute retunes the whole system -->
<html data-motion="calm">   <!-- or "off"; reduced motion always wins -->

<!-- The same engine moves and lights elements -->
<img src="hero.png" data-parallax="12" alt="">
<button class="btn btn-primary" data-shine>Get started</button>

Base styles

The look of raw HTML itself. Around thirty bare tags are already designed before any class is added: headings, paragraphs, links, lists, quotes, tables, images, rules, code and keyboard keys, and the whole form family — labels, text inputs, selects, textareas, file and date pickers, checkboxes, radios and buttons. One visible focus ring, selection colors, thin scrollbars and the print base come with it, and controls refuse accidental text selection while every piece of content stays selectable. The working tags are below; the text tags — headings, paragraphs, lists, quotes, small print — are shown as a full page of writing on the Typography page. If a page only carries writing and simple forms, it may need no classes at all.

A raw table

Scale stepSizeUsed for
--space-control8pxGaps inside controls
--space-stack16pxDefault stack gap
--space-section48pxBetween page sections

Raw checks and radios

A raw button, inline styles and the focus ring

Inline code, a key like Esc and a link are styled too — and press Tab here to see the focus ring every control shares.


Even the horizontal rule above and this small print are the base layer.

<table>
  <thead><tr><th>Scale step</th><th>Size</th></tr></thead>
  <tbody><tr><td>--space-stack</td><td>16px</td></tr></tbody>
</table>

<label for="amount">A raw text input</label>
<input id="amount" type="text" placeholder="Type here">

<select><option>Monthly</option><option>Yearly</option></select>
<textarea rows="2"></textarea>
<button>A raw button</button>

<p>No classes anywhere — base styles only.</p>

Print & export

Printing built in. Mark what belongs on paper and what does not, and every page prints clean: white ground, folds opened, nothing cut in half. A save-as-PDF button is one attribute.

Prints only — invisible on screen Screen only — never prints

The two badges demonstrate the roles: open the print preview and they trade places.

Layout primitives

Container

The page-width wrapper. It centers the content, caps how wide it grows, and keeps the side padding even on every screen.

Content sits here: centered, width-capped, themed side padding. The dashed edge is this demo's bounds.

Stack

Puts blocks one above the other with an even, themed gap. The default way to space a column of anything.

First block

Second block

Third block

Row

Puts things side by side with an even gap, wrapping onto new lines when the room runs out.

Updated a minute ago

Grid

A grid of equal columns — as many as fit the screen, one on phones, with no breakpoints to write.

One

Two

Three

Four

Snap section

Full-screen sections that snap one screen at a time as you scroll — the feel of a modern product page, built to work on iPhone.

Intro

What this page tells you, in one line.

Inputs

Number inputs and sliders, prefilled with examples.

Results

A verdict-first result block, recalculating live.

View stack

The app shell. Each section is a screen, one shows at a time, and plain links move between them — with the browser's back button working.

Home

One screen, one job. Play

Question

Its own scroll container when it overflows. Answer

Result

facet.views.back() returns along the trail.

Forms & controls

Button

The action element: three variants and three sizes for primary, secondary and quiet actions. Works identically as a button or a link.

Icon button

A square button holding one icon — for compact actions whose meaning the icon and its tooltip carry.

Switch, checkbox, radio

Switches, checkboxes and radios — the native controls wearing the theme, with nothing custom to break.

Stepper & segmented control

A count with minus and plus buttons, and a segmented control for flipping between a few views of the same thing.

Fields: input, textarea, select, search

Labelled inputs — text, dropdown, search and more — in one pattern with hints and error lines built in.

File upload & date input

The file picker and the date input, themed but kept native, so the browser's own dialogs do the work.

Number input

A money-grade number field: digits group as you type, the amount is spelled out in words underneath, and a clear button empties it in one tap.

Slider

A range slider with its live value beside it — for small bounded choices you drag to.

Detailed slider

A slider for wide ranges: drag fast across the whole span, then land the exact value with the steppers or the number box.

Choice grid

A grid of small picture buttons — a symbol above a tiny caption — for picking one of a few options at a glance.

Content & data

Card

The grouped surface: a padded, rounded panel that lifts content above the page. The building block of most layouts.

Default

Monthly summary

Raised slightly above the page.

Outlined

Quiet neighbour

No shadow pile-ups.

Clickable

Open the report →

Lifts on hover, presses on click.

Fast by default

No runtime sits between you and the platform, so the page loads instantly.

Ada LovelaceSigned up today

List

Rows with a leading icon or picture, a title, and a trailing value or action — the workhorse of feeds, settings and results.

  • Ada Lovelace Signed up today — two-line row, icon top-aligned 12
  • Notifications On
  • Plain row — no icon at all Paid
  • Avatar image in the icon slot Status badge or a value in the trail Expiring
  • report-2026.pdf 2.4 MB — a real button in the trail of a static row

Table

The data table: quiet header, striped rows, and a hover that names the row you are reading. For records, not layout.

MonthCategoryAmount
AprilGroceries12,480
MayGroceries11,975
JuneTravel31,200
JulyRent48,000

Chart

A themed line chart drawn from a list of points — with labels, event markers and an optional dashed projection.

Heading bar

A short thick accent stroke under a heading — the designed look for a section title, between plain text and a font change.

Latest articles

Pricing

Text clamp

Holds a long block of text to a set number of lines and fades the last one out instead of cutting it with an ellipsis, so cards and rows stay the same height when their copy runs long. The full text stays in the page for screen readers, reader view and print.

Facet is a plain HTML, CSS and JS design library, and this paragraph runs well past three lines so the clamp has something to hold: the first lines read in full and the last fades softly away at the foot, with no ellipsis and no hard edge. Every word here is still in the page — a screen reader, reader view, a search crawler and a printed page all get the whole thing, because the clamp is only a visual limit on screen.

Set the line count per instance with --clamp-lines; this one holds two lines. The rest of the sentence keeps going so the fade has copy to act on and you can see this block clamp tighter than the one above it.

Badge, chip, avatar, progress

Four tiny signals: the badge for a status word, the chip for a filter, the avatar for a person, the progress bar for a share of done.

Draft Paid Expiring Failed 3 updates

TS F

Icon badge

A small glossy status dot pinned to an app icon's corner — numbers, ticks or alerts, like a home-screen badge.

Result block

The answer card: one plain sentence a person can repeat, with the number large underneath. For calculators and verdicts.

At 6% inflation, today's ₹1 lakh buys this much in 2036

₹55,839

Value lost
₹44,161
Buying power kept
56%
Halves every
12 years

Icons

The icon set: thin line glyphs you place with one attribute and color with the text color. About sixty ship, and you can add your own.

<button class="btn btn-icon" aria-label="Search" data-tip="Search everything">
  <svg data-icon="search"></svg>
</button>
<p><svg class="glyph" data-icon="clock"></svg> Updated an hour ago</p>

Themed map

A Google Map wearing the active theme, so the map matches the page in every theme, light and dark.

Overlays & disclosure

Modal, drawer, popover

Modal, drawer and popover, built on the platform's own dialog machinery — focus, Escape and the backdrop come free.

Delete this report?

This cannot be undone. The figures stay in your ledger.

Filters

Quick note

Popovers light-dismiss: click anywhere else.

Accordion, toast, dropdown menu

The accordion for folding content, the toast for a passing notice, and the dropdown menu for a few actions behind a button.

How is the rate calculated?

From the average of the last twelve months, weighted toward recent ones.

Can I export everything?

Yes — every table has an export in its dropdown menu.

Description tooltip

A one-attribute explanation bubble: put the text on any element and it appears on hover or keyboard focus. On touch screens a tap opens it — placed wherever there is room — and it stays until you scroll or tap anywhere else.

Navigation

Tabs, breadcrumb, pagination

Tabs for switching views, the breadcrumb for where you are, pagination for long lists — the wayfinding trio.

The overview pane: totals and the verdict.

Status

Skeleton, spinner, empty state

The three honest ways to show absence: a skeleton while loading, a spinner while working, an empty state when there is nothing.

Crunching the numbers…

No reports yet

The first one appears here the moment you save it.

Loading skin

The loading state: mark any region busy and its content turns into pulsing placeholders shaped like itself, then comes back.

Monthly spend

₹ 48,600 across 31 transactions, most of it rent and groceries.

On budget

Monthly spend

₹ 48,600 across 31 transactions, most of it rent and groceries.

On budget

Component states

The state system: hover, focus, disabled, selected, busy and status, carried the same three ways on every component.

Unavailable
Growth plan

Selected — the accent ring says so.

Renewal due

The edge points at the badge that says why.

Ready arrangements of the components above. A block is not a new thing to learn — it is proof that the primitives compose, shipped as markup you copy whole. Each one follows the same rules as everything else: semantic tags, no extra wrappers, states and hooks included.

Grid of cards

Cards laid out in the auto-fitting grid — as many columns as fit, one on phones, no breakpoints to write.

Groceries

₹ 12,480 this month

Travel

₹ 31,200 this month

Rent

₹ 48,000 this month

Horizontal card row

Cards that scroll sideways with momentum and a gentle snap — a shelf of content on any screen.

April

Saved ₹ 8,200

May

Saved ₹ 9,750

June

Saved ₹ 7,120

July

Saved ₹ 10,400

August

Saved ₹ 6,900

Filterable card list

A search field over a list: type and the rows that do not match disappear, live.

Inflation calculator
Wedding budget
Retirement plan

List cards

Full-width outlined rows, one card per record, with the fields side by side inside.

Groceries
14 entries · June
₹ 12,480
Travel
3 entries · June
₹ 31,200

Product detail

The product page pair: a gallery on one side, with the name, price, options and buy action stacked beside it.

Field notebook

Dot-gridded, 120 pages, lies flat.

₹ 450

Cart line items

The order as rows — item, quantity stepper, line total — with the totals and checkout in a card beside it.

Field notebook A6 ₹ 900

Delivery₹ 60
Total₹ 960

Full top menu

The site header: a brand lockup, links with small icons and one action. It can stick to the top of the page as a blurred translucent strip; on phones the links fold behind an icon that grows the panel open under a darkening blur.

Sidebar navigation

Grouped navigation links in a side column — the pattern this page's own index uses.

Side index

The pinned index beside long content: a search box and grouped links, with the current item marked and kept centred as you move. This page's left menu is this block.

Hero

The opening statement: display type, one line under it, one primary action.

Know what your money will be worth.

Inflation, explained with your own numbers.

Start free See how it works

Feature grid

Icon, claim, one sentence — repeated in the auto-fitting grid. The what-you-get section.

Live rates

Updated the moment the data lands.

Private

Your numbers never leave the page.

Yours

Export everything, any time.

Pricing table

Plan cards side by side — name, price, the differences, one action each — with the recommended plan lifted.

FREE

₹ 0

  • 3 reports
  • Every theme

PRO · RECOMMENDED

₹ 199/mo

  • Unlimited reports
  • Exports & sharing

FAQ list

Questions as accordions that keep one answer open at a time, with no JS.

Is my data private?

Everything computes in your browser; nothing is sent anywhere.

Can I cancel any time?

Yes — one click, and exports stay available.

CTA band

The closing ask: an ink-filled strip with one line and one button.

Ready when you are.

Logo row & testimonial

A muted row of logos and one quote with a face and a name — the proof pair.

THE HINDUMINTMONEYCONTROLET

The first calculator my parents actually understood.
Asha R · Pune

Data table with toolbar

Search, filter chips and actions in a row above the data table — the working screen of a records app.

EntryAmount
Groceries12,480
Travel31,200
Rent48,000

Stat row

KPI cards: one number that matters with its label under it, in the auto-fitting grid.

₹ 91,680SPENT · JUNE
₹ 10,400SAVED · JUNE
6.2%INFLATION · YOY

App identity

An app's identity header: the centered icon, name and one-line purpose, with the version details in rows below.

Anime quote quiz

Guess who said it

In development

4,120OPENS
v0.9VERSION
212 KBSIZE

Settings section

Settings rows — a label with its switch, select or stepper — in a quiet stack under a group heading.

NOTIFICATIONS

Form section

Grouped fields with one submit row: a fieldset per group, the primary action last.

Article header, prose, media

The editorial set: title, byline and meta over long-form semantic text, with the article structured-data slot.

GUIDES · 6 MIN

What inflation does to a decade

Tanishk Sharma · 5 July 2026

A lakh in 2014 does not buy what it used to — and the gap is not a feeling, it is a number you can chart…

Money you do not grow is money you quietly spend.
from the guide
The same basket, priced across ten years.

Layer 4 is the whole page. Where Layer 3 assembles components into sections, Layer 4 assembles sections into a finished product — full layouts you rename and fill in. The three flagship shapes render live below in a real iframe: on a wide screen, flip Desktop, Tablet and Phone to see each template's genuine responsive layout at that width; on a phone the preview simply shows the phone layout, since the wider ones cannot render truthfully there. Or open the full page. Every template links the same /lib/facet.css this site does and ships the SEO head pack. The whole set is listed underneath.

Landing page

A marketing site from the block layer: top menu, hero, social proof, feature grid, pricing, FAQ, CTA band and footer. Swap the words, keep the shape.

Open ↗

<!-- Start from the whole page: save the template and edit the words -->
https://facet-kappa.vercel.app/templates/landing.html

SaaS dashboard

An analytics product — Northstar — with a folding sidebar, a top bar, a KPI stat row, a live chart, and a filterable table beside an activity panel. The everyday shape of a web app.

Open ↗

<!-- Start from the whole page: save the template and edit the words -->
https://facet-kappa.vercel.app/templates/saas.html

Social app

A three-column feed — Ripple — that folds to one column with a bottom tab bar on phones, showing off the app-kit tab bar and the settings sheet. Compose box, a live feed, trends and who-to-follow.

Open ↗

<!-- Start from the whole page: save the template and edit the words -->
https://facet-kappa.vercel.app/templates/social.html

Every template

The whole starter set — eight page shapes, each a complete file you save, rename and fill in. Every one links the same /lib/facet.css and facet.js this site uses and ships the SEO head pack; the deck, document and card print at exact size.

https://facet-kappa.vercel.app/templates/landing.html
https://facet-kappa.vercel.app/templates/saas.html
https://facet-kappa.vercel.app/templates/social.html
https://facet-kappa.vercel.app/templates/app.html
https://facet-kappa.vercel.app/templates/article.html
https://facet-kappa.vercel.app/templates/deck.html
https://facet-kappa.vercel.app/templates/document.html
https://facet-kappa.vercel.app/templates/card.html

Layer 5 is what you apply to a finished page to make it feel like a native app: parallax and idle motion, synthesized sound and haptics, faint backgrounds, and the app kit — the tab bar, the settings sheet, the float button and the scroll gauge. Every control is live in the settings sheet at the bottom-right of this page — open it and flip Motion or Sounds to feel what the HTML below wires up.

Parallax & idle motion

Parallax and idle drift: elements shift gently with the cursor or the phone's tilt, and sweep on their own when nothing moves.

data-parallax="10"

I follow the pointer

.idle-float

I pulse at rest

.idle-sway

I sway a little

Shine

A specular light that travels across an element as the device moves — the way app icons catch light. One attribute.

data-shine, --shine: 1

Light sweeps across me

data-shine data-parallax="10"

I drift and catch light

Sound & haptics

UI sound and vibration with no audio files: a tap under buttons, a tick on steppers, a snap when a pager lands.

Backgrounds

Very faint materials for big quiet surfaces. Two variants: Grid shows its five looks stacked below — the technical grid, the dot grid, the circle grid of outlined rings, graph paper and the custom grid of your own symbols — and each area carries its own controls, so every look tunes independently; Fluid drifts soft color like light through glass. The technical, dot and circle grids can also scatter your own characters across the pattern, at a size you pick, in a fresh arrangement on every visit.

Technical

Plus marks at every intersection — the drawing-board look.

Dots

A dot at every half cell — the quiet default.

Circles

An outlined ring at every half cell — the dots' rhythm, bolder presence.

Graph paper

Minor and major squares, deliberately the lightest.

Custom grid

Your own symbols as the pattern — pick icons, or type anything.

Variant GRID: .bg-grid (technical plus marks), .bg-dots (dot grid), .bg-circles (circle grid: outlined rings on the dots' half-cell rhythm; --bg-ring sets the ring diameter, default 15px), .bg-ruled (writing lines), .bg-graph (graph paper, deliberately the lightest) — or the custom grid, data-bg-glyph="✦" with any character or emoji, a facet icon name, or several tokens separated by spaces for an alternating grid; facet.js draws the tile in the pattern ink and redraws live whenever the attribute, the theme, the mode or the element's style changes. Every grid tunes with --bg-tint (ink color, default the muted text token; the accent ranks --accent-1/-2/-3 are the sanctioned choices), --bg-strength (ink opacity, default 12%) and --bg-cell (spacing, default 2.5rem); the custom grid adds data-bg-glyph-size (spacing override, px) and data-bg-glyph-scale (glyph size as a fraction of the cell, default 0.42). facet.glyphBackground(el) draws a late-added surface.

The scatter: data-bg-scatter="✦ ❋" on .bg-grid, .bg-dots or .bg-circles replaces roughly one lattice point in ten with one of your characters (any character or emoji, or a facet icon name); data-bg-scatter-rate tunes the frequency (one character per N points, default 10) and data-bg-scatter-scale the character size (0.1–2, default 1). The arrangement is seeded fresh each page load — every visit scatters differently — but themes and modes re-ink the same arrangement within the load. facet.scatterBackground(el) draws a late-added surface.

Variant FLUID: data-bg-fluid — facet.js mounts three GPU-composited layers (ground, breathing pools, drifting bubbles) colored by the accent and vivid tokens, so themes and modes recolor with no redraw; desynced clocks keep it from repeating; still under data-motion="off" and reduced motion; plain surface with JS off. facet.fluidBackground(el) mounts a late-added surface.

Fixed to the screen: .bg-fixed on any grid look makes it the page's one still backdrop — <div class="bg-dots bg-fixed"></div> as the body's first child, content floats over it with no wrapper; it raises its own --bg-strength default to 22% because whole-page fixed use is where the whisper default disappears on dim phone panels. data-bg-fluid-fixed beside data-bg-fluid pins the POOLS to the screen while the surface scrolls over them like a window; the surface clips with a clip-path rounded to the card radius (--bg-fluid-radius overrides).

Use ONE background per surface, never nested; all patterns fade under prefers-contrast: more and never print.

App kit

Tab bar

The app's floating command bar, like the pill in Apple's Photos app: a round menu button that slides the navigation in from the left edge, the pill of sections with its gliding highlight, and a round settings button that slides the settings panel in from the right. Every piece is optional, and one extra class turns the same bar into a desktop site bar pinned to the top. This site's own bar — with its corner panels condensing in and out of their buttons — is the whole system running live.

Phone · the app bar — floats at the bottom

Desktop · the site bar — floats at the top; the brand is the home tab (highlighted when home is current), pages sit to the right, and the same markup folds back to the phone pill on small screens

Fewer options · tabs only, for a simple app

More options · tabs and settings, no menu

Tap the segments: the highlight stretches and settles between them. The corner buttons open the two edge panels — menu left, settings right — and swap each other out. The brand is the home tab in both shapes — first option in the phone pill, left anchor on desktop — and the CTA slot hides itself on phones; one markup serves both.

<!-- the app bar (phone: floats at the bottom). Add class
     "tab-bar-top" and wide screens pin it to the top as the
     site bar; the brand and CTA slots show only there. -->
<nav class="tab-bar tab-bar-top" aria-label="Sections">
  <button type="button" class="tab-menu" aria-controls="nav-sheet"
          aria-expanded="false" aria-label="Open menu"
          data-tip="Opens the navigation">
    <svg width="20" height="20" data-icon="menu"></svg>
  </button>
  <div class="tab-set">
    <!-- the brand IS the home tab: aria-current="page" on the home page -->
    <a class="tab-brand" href="/" aria-current="false"><svg width="18" height="18" data-icon="sparkle"></svg>acme</a>
    <button type="button" class="tab-seg" data-section="intro" aria-current="true">Intro</button>
    <button type="button" class="tab-seg" data-section="inputs" aria-current="false">Inputs</button>
    <a class="btn btn-primary btn-small tab-action" href="/start">Start free</a>
  </div>
  <button type="button" class="tab-settings" aria-controls="settings-sheet"
          aria-expanded="false" aria-label="Open settings"
          data-tip="Opens the settings">
    <svg width="20" height="20" data-icon="sliders"></svg>
  </button>
</nav>

<!-- each edge panel is a scrim + sheet pair -->
<div class="sheet-scrim" data-open="false"></div>
<aside class="sheet sheet-left sheet-rise" id="nav-sheet" data-open="false"
       aria-hidden="true" aria-label="Navigation">…</aside>
<div class="sheet-scrim" data-open="false"></div>
<aside class="sheet sheet-rise" id="settings-sheet" data-open="false"
       aria-hidden="true" aria-label="Settings">…</aside>

<!-- .sheet-rise: on phones the panel rises out of the bar in the
     bar's own glass; on wide screens it stays an edge sheet. -->

<!-- the page clears the fixed bar with one class, no hand-measured
     padding: top on wide screens, bottom on phones. (A page with the
     plain bottom bar pads with var(--bar-clearance-bottom) instead.) -->
<main class="page-under-bar">…</main>

Sheet & menu

The settings sheet: a panel that slides in over a dark scrim, holding menu rows and setting toggles. The same panel can instead rise out of the tab bar's corner as a glass card on phones, or hang from the top bar's corner on wide screens — the menu and settings panels running this site, opened from the bar below, are that shape live.

Float button

A lone round button floating at the page's corner — the home for one global action, like opening the menu.

Content translation

Content in more than one language: author each variant in the markup and one button flips the page.

The quick brown fox.

Only the active language shows; the rest are hidden in place.

Scroll gauge

A slim themed scroll thumb beside a panel — it shows your place where the native scrollbar is hidden.

The gauge beside this box is injected by facet.scrollGauge.

Its thumb is exactly the visible share of this content.

Scroll with momentum and the pill slides out of the groove.

That spill is deliberate: the groove clips it away.

When content fits, the gauge fades out entirely.

Panels use it beside .sheet-scroll; pages use the draggable lane variant.

The lane variant, .scroll-gauge-page, floats off the right edge.

Its onScrub option turns the whole groove into a drag handle.

Grab it and the thumb turns gold while you hold it.

Installable (PWA)

Turns a page into an installable app: three small files at your project root, with offline caching from the library.

The install button reveals itself only when the browser actually offers installation (so here it may stay hidden). facet.install() triggers the prompt from code.

1 · sw.js at your project root — one line:

importScripts("https://facet-kappa.vercel.app/lib/facet-sw.js");

2 · the head block on the page (manifest, apple metas, worker registration):

<link rel="manifest" href="/manifest.json">
<meta name="theme-color" content="#FFFFFF">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<link rel="apple-touch-icon" href="/icons/icon-180.png">
<script src="https://facet-kappa.vercel.app/lib/facet.js" data-service-worker="/sw.js" defer></script>

3 · manifest.json + icons/ — copy the template manifest and the icon set, then edit the name and colors.