Typed tokens in. Plain CSS out.
The contract CSS never had, as a set of small, opt-in libraries you adopt one at a time.
Status: early and experimental (0.x). The measurement layer,
css-calipers, is stable and headed to 1.0; the rest is taking shape.
This project grew out of a blog post: We still don't have proper CSS frameworks.
We still don't have proper CSS frameworks. What we call frameworks today are utility libraries, class-naming conventions, and methodologies dressed up in framework branding. What every other ecosystem has, and CSS lacks, is typed input, defined output, a contract a compiler can actually enforce.
Traditional CSS frameworks put their opinions in the middle. They hand you a vocabulary and a way to compose it, prescribing how you author and assemble your styles. But the edges stay loose: the values you feed in and the CSS that comes out are still unchecked strings, so an off-scale number or a mistyped token ships without complaint.
CSS-Bookends does the opposite. It is opinionated at the edges (typed tokens in, valid CSS out) and loose in the middle (how you compose, layer, and organize is entirely yours). Each piece takes structured, typed tokens and emits plain, inspectable CSS. Values stay opaque through composition and only become strings at the very edge, so mistakes surface where you can see them rather than shipping silently:
import { m } from "css-calipers";
const paddingBase = m(16); // 16px
const rotation = m(45, "deg"); // 45deg
paddingBase.add(rotation); // throws: cannot add px and deg
paddingBase.add(m(8)).css(); // "24px"It also stays faithful to the full CSS spec. Many frameworks only let you reach for a curated subset of what CSS can do, so anything outside their vocabulary or scale is awkward or impossible to express, even when it would be perfectly valid CSS. CSS-Bookends does not gate the output: if CSS allows it, you can emit it.
CSS-Bookends is split into two kinds of package:
- Lexicons are the foundational vocabularies. A lexicon defines typed values
and the operations on them, and depends on little or nothing else.
css-calipers(measurement) is a lexicon;coloursandspacingwill be too. Lexicons can build on one another (aspacinglexicon builds oncss-calipers). - Books are the standalone helper libraries built on top of one or more
lexicons. A book takes typed tokens and emits plain CSS for a single concern.
@css-bookends/media-queriesis a book;borders,shadow, andmarginswill be.
A lexicon is the vocabulary; a book is written using it. Every package, lexicon or book, is independently installable and pulls in only what it actually depends on. The umbrella is organizational, never a bundle you are forced to take whole.
Every package publishes under the @css-bookends/* scope, lexicons and books
alike (for example @css-bookends/css-calipers and @css-bookends/media-queries).
@css-bookends/css-calipers— the measurement lexicon and the foundation most other pieces build on. Stable, headed to 1.0. repo · npm@css-bookends/media-queries— typed, unit-safe media query strings, built on@css-bookends/css-calipers. Experimental 0.x.
More lexicons (spacing, colours) and books (borders, shadow, margins)
are being brought in.
CSS frameworks are usually class libraries with predefined styles. That is not what this is. Conceptually it is closer to compiler pipelines that validate inputs and generate output than to utility-first or class-based CSS frameworks. Validated, typed inputs go in. Plain CSS comes out.
Instead of authoring strings like "20px", values are represented as structured
objects (via the css-calipers lexicon) and passed through book APIs such as
borders, margins, and media queries. These render plain CSS through a standard
.css() call or a normalized object.
CSS remains the final specification. This system does not replace it, restrict it, or redefine it. It enforces correctness at authoring time and emits fully inspectable CSS.
A glossary of the architecture terms used across this repo. See ARCHITECTURE.md
for the model and AGENTS.md for the rules that enforce these.
- lexicon : a foundational vocabulary, typed values and the operations on them (measurement, colours, spacing). Depends on little or nothing else.
- book : a standalone helper for one CSS concern (borders, shadows, ...), built on one or more lexicons. Takes typed tokens, emits plain CSS.
- page : one of a book's three stages,
input(accept many shapes) ->storage(one canonical internal shape) ->output(render to CSS). - press : the definition of a book, its three pages plus config defaults.
- bookPress : the factory engine in
@css-bookends/bookpressthat stamps a book from a press, able to override any single page or the whole press. - bookpress : the package that provides the
bookPressand the press types. bookPress<BookName>: a book's factory function, named with thebookPressprefix (for examplebookPressColours,bookPressBorders). The metaphor: the bookPress presses a book from its press. Calling it returns a configured book. This is the only sanctioned way to obtain a helper; the raw value-helper is never imported directly.- default instance : each package calls its own factory once with the built-in
defaults and exports the result (for example
colours). Import this instance, not the raw helper. - shelf (
@css-bookends/shelf) : the aggregate composition root. It pulls in every book's default instance and re-exports them, so a single import gives you the whole preconfigured set. .css(): the single render terminal. Every helper renders its final output through.css(); the output variant is chosen by config or a typed format object (for examplecolorFormats.hex), never by a per-format render method.
Install only the pieces you want; nothing pulls in the rest of the umbrella.
# the measurement lexicon
npm install @css-bookends/css-calipers
# a book (brings in css-calipers as its dependency)
npm install @css-bookends/media-queriesOr take the whole bookshelf in one package, which re-exports every lexicon and book:
npm install @css-bookends/shelfThis is a pnpm monorepo and the source of truth for every package. Established
packages are mirrored out to their own standalone repositories (for example
css-calipers), which keep their URL, stars, and issues.
lexicons/ foundational vocabularies (css-calipers, ...)
books/ standalone helper libraries (media-queries, ...)
This is a solo, early-stage project. If the direction resonates, you can buy me a coffee to support continued work.