Skip to content

v0.2.1 / 174 components / no build step

Ship the CSS you used.

Stylesheets that make a page look finished. Written for small screens first, no build step and no tool to run, and you link only the pieces the page actually shows.

npm i @barebase/style

Or link a file straight from the page, with nothing installed at all.

Theme published

Both themes measured at AA.

Sample panel

Delivery Live

Range
Requests per minute 1,284 low 840, high 1,410, last 12 hours

Bundle 3.2 GB of 5 GB
  • Media 2.1 GB
  • Backups 0.8 GB
  • Logs 0.3 GB
68%
Index rebuild
  • RN
  • KL
  • AV
  • +1

No script anywhere in this group. Every surface in it is a file linked in the head of this page, and the controls in it work.

Measured at a glance

  • Core only, delivered, gzip
    4,832 B
    Four files, and that is the whole mandatory import.
  • Median of the 174
    575 B
    What one more element costs the page.
  • Dependencies, build steps, runtime
    None
    A link tag is the whole install.

01 / What it is

A design substrate, not a page template.

Every one of these is a thing the framework refuses to do rather than a feature it advertises.

This page loads no stylesheet of its own. Every rule you can see is bare.style styling bare.style, which is the fastest way to find out what a framework is missing.

02 / Size

Measured, never estimated.

Every number here comes from scripts/size.ts, which compresses the real bytes. Run bun run size and check them.

  • Core only

    4,832 B

  • Core plus the largest single file

    8,793 B

  • All 174 files at once

    78,773 B

All three are the delivered form: dist/, comments stripped, gzip level 9 over one concatenated file. That is the only column comparable to another framework's published figure, which is always its minified build.

Both published forms, in bytes. Authored is src/ with its comments, delivered is dist/. gzip is level 9, brotli is quality 11.
Bundle Form Files Raw gzip, one file gzip, separate brotli
Core only delivered 4 21,740 4,832 B 5,669 4,023
Core only authored 4 65,158 19,901 21,895 16,872
Everything delivered 174 505,475 78,773 B 136,975 50,421
Everything authored 174 1,423,118 355,566 485,008 259,164

Two gzip columns because both are real delivery shapes. One file is a single link to a concatenated bundle. Separate is what per-element link tags over HTTP/2 cost, where each file is compressed on its own, and it is always the larger of the two.

03 / Agent cost

Cheaper for an agent to write.

The styling lives in the stylesheet instead of in the class attribute, so there is far less markup to type. When the thing doing the typing is a language model billed by the token, less to type is less to pay.

Six fragments - a hero, a settings form, a table with a toolbar, a card grid, a modal and a row of dashboard tiles - written twice. Once in bare.style, once in the class lists Tailwind's own documentation produces for that component. The wording on the page is identical in both, so the only thing being compared is the styling.

The same six fragments under three ways of counting. Only the last row is estimated.
Counted as Exact? bare.style Tailwind Ratio
Characters Exact 5,796 11,992 2.1x
Token floor Exact 1,724 3,389 2.0x
Tokens Estimated 2,197 4,623 2.1x

Counting exact tokens needs a 1.7 MB merge table from the model vendor, and shipping one inside a framework that argues against dependencies is not a trade worth making. So the last row is an estimate and says so. The middle row is not: it is the number of pieces the text splits into before any merging happens, which no real tokeniser can go below. All three land in the same place, which is the point of printing all three.

Where this number does not apply

  • A page is usually written once. This is a saving on writing it and on every rewrite of a whole component, and close to nothing on a one-line edit that either framework does cheaply.
  • The cost moves rather than disappearing. It moves out of the markup and into a stylesheet the browser downloads once and caches, which is a different budget and is measured separately in Size above.
  • Writing less of the wrong thing saves nothing. Correct class names are a separate problem, which is what the MCP server is for.
  • The Tailwind side is light theme only. bare.style gets dark from its tokens with no extra markup; a dark-capable Tailwind fragment needs another variant on every colour. Leaving that out makes this comparison kinder to Tailwind than it has to be.

Run bun run token-cost to reproduce every figure above, including the fragments themselves.

04 / Install

A link tag is the install.

Copy src/ into the directory your site serves and link the four core files plus whatever you use. Nothing to compile, nothing to configure, no runtime.

Each file declares the shared layer order before its own rules, so these tags can go in any sequence. A component loaded later cannot outrank one loaded first by accident.

Read the full documentation

index.html

<!-- mandatory -->
<link rel="stylesheet" href="/css/core/reset.css">
<link rel="stylesheet" href="/css/core/tokens.css">
<link rel="stylesheet" href="/css/core/type.css">
<link rel="stylesheet" href="/css/core/base.css">

<!-- only what this page shows -->
<link rel="stylesheet" href="/css/layout/stack.css">
<link rel="stylesheet" href="/css/data/table.css">
<link rel="stylesheet" href="/css/forms/button.css">

05 / Rules

Things this framework will not do.

Require a build step
No preprocessor, no plugin, no configuration file. A feature that cannot be expressed in plain CSS a browser reads directly is not in here.
Import a sibling
A component file never imports another component. The barrel files are the only exception, they exist for convenience, and they are never the cheap path.
Animate layout
Only transform, opacity, clip-path and filter, the four a compositor runs off the main thread. Animating width or top is how a page drops frames.
Ship a pairing under AA
4.5:1 for body text, 3:1 for large text and for anything non-text that carries meaning, measured against every surface in both themes.
Hide content behind script
Scroll reveals stay visible until a script has said it is running, so a page whose JavaScript is blocked renders in full rather than blank.
Use colour as the only signal
Every state colour expresses is also carried by a shape, a weight, an icon slot or a marker, so it survives greyscale and every form of colour vision deficiency.

06 / Theme

An explicit choice beats the system.

Light is the default. A reader who has not chosen follows their operating system. A reader who has chosen keeps that choice even when the system says the opposite, and that is the part most implementations get wrong: source order alone does not achieve it, because a later media query still beats an equal-specificity class rule placed before it.

Two things make it airtight. The media query targets :root:not(.theme-light), so a pinned light theme is never matched rather than merely overridden afterwards. The pinned blocks are :root.theme-light and :root.theme-dark, which outrank the plain :root default wherever they sit in the file.

The toggle in the bar above is currently following the system.

07 / Components

174 components, each documented live.

Every example in the documentation is a working component, and the markup shown under it is read out of that example rather than transcribed, so it cannot drift.

  • 4 files

    Core

    Reset, tokens, element defaults, the fluid type scale. The only mandatory import.

  • 8 files

    Layout

    Shell, grid, stack, cluster, sidebar, split, centre and spacer, all breakpoint free.

  • 14 files

    Forms

    Button, input, select, checkbox, radio, switch, range and file, each keyboard operable.

  • 9 files

    Navigation

    Bar, link, rail, tabs, breadcrumb, menu, drawer and pagination, with the current page marked.

  • 13 files

    Data

    Table, card, list, stat, badge, tag, avatar, keycap and divider for the surfaces that carry values.

  • 9 files

    Feedback

    Alert, banner, modal, toast, tooltip, popover, progress and spinner, announced as well as drawn.

  • 23 files

    Charts

    Bar, line, area, donut, funnel, treemap and the cartesian set, drawn without a charting library.

  • 3 files

    Prose

    Long-form column, code blocks with their own token set, and quotations.

  • 2 files

    Motion

    Transitions, named animations, scroll reveal and view transitions, every one refusable.