strata
DocsPackagesBlogsShowcase
Introduction

Guides

  • Installation
  • Configuration
  • Build Pipeline
  • Theme System
  • Data-Attribute States
  • Versioning & Contributing

Utilities

  • Spacing
  • Display
  • Flexbox
  • Grid
  • Sizing
  • Aspect Ratio
  • Typography
  • Colors
  • Borders
  • Shadows
  • Position
  • Overflow
  • Opacity & Visibility
  • Misc
  • Arbitrary Values
  • Variants

Components

  • Buttons
  • Cards
  • Forms
  • Navigation
  • Modals
  • Alerts, Badges & Progress
  • Tables & Lists
  • Dropdowns, Tooltips & Popovers
  • Accordion & Offcanvas
  • Placeholders

Configuration

Add a strata.config.js (or .cjs) to your project root:

module.exports = {
  content: ['./src/**/*.{html,jsx,tsx,vue,astro,svelte,js,ts}'],
  input:   './strata.css',
  output:  './dist/strata.output.css',
  safelist: [],

  // optional — CSS minification, used by `--minify` only
  minifier: 'lightningcss',        // 'lightningcss' | 'cssnano' | false
  targets:  { safari: 16 << 16 },  // browser targets for lightningcss
}

Already ran npx strata-css init?

The installer writes a starting strata.config.js for you — correct input/output paths for your framework, but always the same generic ./src/**/*.{html,jsx,tsx,vue,astro,svelte,js,ts} content glob, regardless of your actual folder layout. Everything below is about checking and customizing what it generated, not an alternative to it.

Content globs

Relative globs resolve against the project root — the directory containing strata.config.js — not whatever directory the build happens to run from.

Any file the glob matches is scanned, whatever its extension — .php, .blade.php, .mdx, .erb, .hbs, .twig, and so on. Only binary/media formats are skipped.

The default glob assumes a src/ layout — many frameworks don't use one

Next.js's App Router puts routes in app/, not src/app/, unless you opted into a src directory — this documentation site's own config is ['./app/**/*.{js,jsx,ts,tsx}', './components/**/*.{js,jsx,ts,tsx}'], not the generic default. If classes aren't showing up right after init, this glob not matching your real folders is the most common cause — check it before anything else.

Safelist

Class names to always emit, whether or not the scanner finds them — for classes built at runtime from a variable, returned by an API, or present in markup Strata never scans:

safelist: [
  'btn-primary',
  'shadow-lg rounded-pill',   // an entry may hold several space-separated classes
]

This site dogfoods its own safelist

The utility/component reference pages in this site toggle classes dynamically from JSON data inside an interactive playground — the scanner can't see those as literals, so they're safelisted directly from the same JSON that renders the reference tables.

Minifier & targets

--minify runs a fixed cascade and prints which engine ran: a minifier set in config is honoured exactly (hard-errors if unavailable), otherwise Lightning CSS runs by default, falling back to cssnano on a missing package, a parse failure, or a dropped declaration — and finally unminified CSS if neither is installed. Neither is a hard dependency; both are optional peers.

Why the order is fixed, not 'whichever output is smaller'

The two engines aren't interchangeable on your CSS. Given .legacy { *zoom: 1 }, Lightning throws — or with errorRecovery (always on) drops the declaration — while cssnano preserves it. A recovered parse error is treated as a failure, because the smaller output is smaller precisely by deleting something you wrote. Compression never gets to decide correctness.

targets is passed through to Lightning CSS. Without it, Lightning emits Media Queries Level 4 range syntax (width>=768px), which needs Safari 16.4+ — barely a change in practice, since Strata's own output already requires Safari 16.2+ through its use of color-mix(). Set targets if you want that floor stated explicitly rather than inherited.

This cascade only runs on the CLI

Under Vite, Next, or webpack the PostCSS plugin path is used instead, and the bundler does its own minification — minifier/targets have no effect there.

Diagnosing a missing class

init does run an initial build for you, but silently — no scanned-file count, no warnings printed. If a class isn't showing up, run this yourself to see what the scanner actually saw:

node bin/strata.js --build --verbose
# [Strata]   scanned 35/35 matched file(s), 0 skipped, 788 class name(s) found
# [Strata]   globs: ./src/**/*.{html,jsx,tsx}  (relative to /path/to/project)

Two conditions are reported as warnings automatically: no files matched the content globs, or files matched but no class names were found in them. If neither warning appears and a class is still missing, it's almost certainly built dynamically (`btn-${variant}`) — no scanner can recover that. Safelist it.

PreviousInstallationNextBuild Pipeline
strata

JIT CSS Framework. Built for modern UI.

Docs

  • Introduction
  • Installation
  • Configuration
  • Utilities
  • Roadmap

Packages

  • All Packages
  • Forms
  • Modal
  • Chart

GitHub

  • Repository
  • Issues
  • Pull Requests
  • Discussions

npm

  • strata-css
  • Releases
  • Changelog
LicenseContributingChangelog
PrivacyTerms