barefoot-css
v8.7.0
Published
A bare-bones, themeable, JS-free CSS framework. No boots, no baggage.
Maintainers
Readme
Barefoot CSS
Kick off your boots. A bare-bones, themeable, JS-free CSS framework for people who'd rather not ship 200KB of stylesheet to render a button.
Live demos: conformance demo · layout playground · paint & paper · data story · form architecture · keyboard & a11y · resilience & coexistence · acceptance gate · theme studio
Why Barefoot?
- Tiny. Core (
index.css) is ~3KB gzipped. Import only what you use — no 200KB bundle. - Container-aware, not viewport-aware. Tables, forms, cards, and layouts adapt to the box they're in. No media queries, no JS. Try the playground.
- Themeable in minutes. Every visual is a
--bf-*variable. No Sass, no rebuild. Tokens ship as W3C DTCGtokens.json. - JS-free by default. Dialogs are
<dialog>, accordions are<details>, menus are popovers. Opt-in zero-dependency JS only where CSS can't reach (tabs, sorting, theme persistence). - Accessible. Native semantics, visible focus, AA contrast,
forced-colorssupport, axe-core tested in CI. - Neutral. Ink on paper, hairline borders, no shadows. Your design, not ours.
Quick start
No build step. CDN first, npm second:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Barefoot test drive</title>
<!-- import the major you installed: @^8 on npm, or pin the major below -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/barefoot-css@8/dist/index.css">
<!-- opt-in: one <link> per component / theme -->
<!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/barefoot-css@8/dist/components/dialog.css"> -->
<!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/barefoot-css@8/dist/themes/sunset.css"> -->
</head>
<body>
<button>Save</button>
<input type="email" placeholder="[email protected]">
</body>
</html>npm install barefoot-css@import "barefoot-css"; /* core: layers, reset, tokens, base */
@import "barefoot-css/components/dialog.css"; /* opt-in components, one import each */
:root {
--bf-primary: #2563eb;
--bf-radius: 0.5rem;
--bf-font: "Inter", system-ui, sans-serif;
}Features
| Area | What you get |
|---|---|
| Layout | .bf-flow, .bf-switcher, .bf-sidebar — container-aware primitives. Tight in a sidebar, roomy in a column. → docs/layout.md |
| Adaptive | Tables card-stack, forms reflow with a zero-JS error summary, cards flip orientation. Opt-in, never in full.css. → docs/adaptive.md |
| Forms & tables | Validation groups that tint on :has(:user-invalid), sticky headers + leading column with a "more data" fade. → docs/paint-paper.md |
| Form architecture | The async validation contract (data-async-pending + live region), wizard steppers, field arrays — plus the CSS-vs-JS state boundary. → docs/forms.md |
| Keyboard & a11y | Per-pattern keyboard maps (sort-header roving, filter Esc-to-clear, nested dialogs), the roving-tabindex contract, and the opt-in user-preference layer. → docs/keyboard.md |
| Data story | A density scale (data-density, one multiplier for padding and type), server-rendered sort (data-sort), and row selection with a zero-JS bulk-actions bar. → docs/components.md |
| Resilience | .bf-elastic boxes that absorb text expansion, a side-by-side @layer contract for living next to another reset, and print that is full or cut (data-print). → docs/coexistence.md |
| Print | Opt-in print.css flattens layouts, re-tabulates adaptive tables, prints link URLs. Zero cost on screen. |
| Verify | Opt-in dev checker audits Barefoot markup contracts in your console — what axe can't know. → docs/verify.md |
| DX governance | .bf-debug audit overlay (layer boundaries + orphan flags), the deprecation split in the checker, npm run perf selector budgets, recipe fixtures pinned to their docs, and the acceptance gate at literal 500×15 scale. → docs/debug.md · docs/performance.md · docs/verify.md |
Size
Measured from the current build, not estimated. Core stays under 10KB gzipped (enforced by npm run check).
| Artifact | Raw | Gzip | Brotli |
|---|---|---|---|
| full.css | 56.65KB | 10.61KB | 9.24KB |
| js/verify-contracts.js | 25.70KB | 8.34KB | 7.20KB |
| index.css | 11.55KB | 3.07KB | 2.63KB |
| js/verify.js | 6.44KB | 2.52KB | 2.15KB |
| components/forms.css | 10.79KB | 2.25KB | 1.92KB |
| js/carousel.js | 4.66KB | 1.92KB | 1.63KB |
| js/table-sort.js | 4.01KB | 1.84KB | 1.55KB |
| js/popover-menu.js | 3.08KB | 1.45KB | 1.22KB |
| js/theme.js | 3.07KB | 1.42KB | 1.15KB |
| components/forms-base.css | 5.49KB | 1.41KB | 1.17KB |
| js/lifecycle.js | 2.95KB | 1.38KB | 1.15KB |
| js/nav.js | 2.95KB | 1.37KB | 1.14KB |
| js/tabs.js | 2.90KB | 1.29KB | 1.09KB |
| js/deprecations.js | 2.45KB | 1.23KB | 1.01KB |
| js/toast.js | 2.96KB | 1.11KB | 0.91KB |
| components/debug.css | 3.00KB | 1.06KB | 0.91KB |
| js/roving-index.js | 2.10KB | 1.04KB | 0.89KB |
| js/filter-clear.js | 1.65KB | 0.86KB | 0.71KB |
| utilities.css | 3.18KB | 0.86KB | 0.65KB |
| components/icons.css | 3.69KB | 0.80KB | 0.65KB |
| components/print.css | 2.38KB | 0.80KB | 0.66KB |
| js/tooltip.js | 1.86KB | 0.78KB | 0.64KB |
| components/states.css | 2.75KB | 0.76KB | 0.66KB |
| js/verify-domain.js | 1.54KB | 0.71KB | 0.60KB |
| components/stepper.css | 2.67KB | 0.70KB | 0.56KB |
| components/table.css | 2.13KB | 0.69KB | 0.58KB |
| components/popover.css | 2.74KB | 0.67KB | 0.58KB |
| js/remove-on-click.js | 1.25KB | 0.66KB | 0.54KB |
| components/forms-select.css | 1.66KB | 0.63KB | 0.54KB |
| components/reveal.css | 2.11KB | 0.63KB | 0.55KB |
| components/buttons.css | 2.10KB | 0.62KB | 0.50KB |
| components/command.css | 2.05KB | 0.59KB | 0.49KB |
| components/nav.css | 1.29KB | 0.50KB | 0.40KB |
| components/segmented.css | 1.23KB | 0.50KB | 0.37KB |
| components/carousel.css | 1.19KB | 0.50KB | 0.41KB |
| components/dialog.css | 1.13KB | 0.49KB | 0.42KB |
| components/accordion.css | 1.44KB | 0.49KB | 0.38KB |
| js/reveal.js | 0.88KB | 0.46KB | 0.38KB |
| components/forms-validation.css | 1.65KB | 0.45KB | 0.36KB |
| components/data-display.css | 1.33KB | 0.45KB | 0.36KB |
| components/layout.css | 1.62KB | 0.44KB | 0.37KB |
| components/data-grid.css | 0.98KB | 0.43KB | 0.34KB |
| js/chips.js | 0.72KB | 0.43KB | 0.36KB |
| components/forms-async.css | 0.84KB | 0.42KB | 0.33KB |
| components/skeleton.css | 0.93KB | 0.41KB | 0.33KB |
| components/table-adaptive.css | 0.99KB | 0.41KB | 0.32KB |
| themes/seed-system.css | 1.48KB | 0.41KB | 0.35KB |
| components/forms-checks.css | 1.07KB | 0.41KB | 0.31KB |
| js/return-focus.js | 0.65KB | 0.40KB | 0.30KB |
| components/media.css | 0.92KB | 0.39KB | 0.31KB |
| js/alert-dismiss.js | 0.69KB | 0.39KB | 0.32KB |
| components/nav-adaptive.css | 0.75KB | 0.38KB | 0.29KB |
| components/pagination.css | 0.86KB | 0.38KB | 0.28KB |
| components/chip.css | 0.81KB | 0.37KB | 0.29KB |
| components/table-select.css | 0.69KB | 0.35KB | 0.27KB |
| components/tabs.css | 0.78KB | 0.35KB | 0.26KB |
| components/timeline.css | 0.84KB | 0.34KB | 0.27KB |
| components/layout-stagger.css | 1.02KB | 0.34KB | 0.29KB |
| components/badge.css | 0.94KB | 0.34KB | 0.26KB |
| components/alert.css | 0.85KB | 0.34KB | 0.26KB |
| components/table-sticky.css | 0.84KB | 0.34KB | 0.28KB |
| themes/playful.css | 0.59KB | 0.33KB | 0.29KB |
| components/density.css | 2.97KB | 0.32KB | 0.26KB |
| js/barefoot.js | 0.62KB | 0.32KB | 0.28KB |
| themes/editorial.css | 0.58KB | 0.32KB | 0.27KB |
| themes/theming-scope.css | 1.76KB | 0.32KB | 0.26KB |
| components/grid.css | 1.23KB | 0.31KB | 0.25KB |
| components/forms-range.css | 0.91KB | 0.31KB | 0.23KB |
| components/empty-state.css | 0.57KB | 0.30KB | 0.24KB |
| components/spinner.css | 0.61KB | 0.30KB | 0.25KB |
| components/field-array.css | 0.60KB | 0.29KB | 0.23KB |
| components/form-adaptive.css | 0.54KB | 0.29KB | 0.23KB |
| components/card-adaptive.css | 0.50KB | 0.28KB | 0.23KB |
| components/forms-file.css | 0.60KB | 0.28KB | 0.21KB |
| components/forms-meter.css | 0.74KB | 0.28KB | 0.23KB |
| components/layout-rhythm.css | 0.61KB | 0.28KB | 0.21KB |
| themes/forest.css | 0.47KB | 0.27KB | 0.23KB |
| themes/dashboard.css | 0.50KB | 0.26KB | 0.22KB |
| components/a11y-prefs.css | 0.94KB | 0.26KB | 0.22KB |
| themes/sunset.css | 0.44KB | 0.25KB | 0.21KB |
| components/breadcrumbs.css | 0.51KB | 0.25KB | 0.18KB |
| components/forms-state.css | 0.48KB | 0.25KB | 0.17KB |
| themes/coastal.css | 0.44KB | 0.24KB | 0.20KB |
| themes/custom.css | 0.45KB | 0.23KB | 0.19KB |
| components/code.css | 0.40KB | 0.22KB | 0.16KB |
| components/divider.css | 0.36KB | 0.22KB | 0.16KB |
| components/layout-flow.css | 0.34KB | 0.22KB | 0.17KB |
| components/view-transition.css | 0.52KB | 0.22KB | 0.18KB |
| components/card.css | 0.33KB | 0.21KB | 0.15KB |
| components/forms-color.css | 0.42KB | 0.21KB | 0.16KB |
| components/menu-items.css | 0.29KB | 0.20KB | 0.13KB |
| components/tabs-adaptive.css | 0.38KB | 0.19KB | 0.16KB |
| components/segmented-adaptive.css | 0.44KB | 0.19KB | 0.15KB |
| components/elastic.css | 0.30KB | 0.19KB | 0.15KB |
| components/layout-switcher.css | 0.27KB | 0.19KB | 0.15KB |
| themes/theming-anim.css | 0.33KB | 0.18KB | 0.14KB |
| components/prose.css | 0.32KB | 0.17KB | 0.13KB |
| components/script-type.css | 0.25KB | 0.14KB | 0.10KB |
| components/layout-sidebar.css | 0.16KB | 0.13KB | 0.11KB |
| js/verify-forms.js | 0.14KB | 0.12KB | 0.10KB |
| js/verify-tables.js | 0.14KB | 0.12KB | 0.09KB |
| js/verify-core.js | 0.13KB | 0.12KB | 0.10KB |
| js/verify-all.js | 0.13KB | 0.12KB | 0.10KB |
| components/coexistence.css | 0.05KB | 0.07KB | 0.04KB |
Opt-in JS (dist/js/): zero-dependency modules, imported individually or via barefoot.js. verify.js is dev-only and never in the barrel. → docs/javascript.md
Browser support
Evergreen only — Chrome 135+, Firefox 151+, Safari 26.2+. No transpiling of modern CSS (container queries, anchor positioning, oklch()). Older engines gracefully degrade to plain layouts.
Project layout
src/ index.css (core), components/, themes/, js/ (opt-in)
demo/ conformance demo + playground + paint-paper + resilience + studio
docs/ theming, components, layout, adaptive, accessibility, …
tests/ a11y (axe), JS, CSS behavior, visual regression
build/ bundler + size budget + preview serverfull.css is frozen since v4.6 — new surfaces ship as separate opt-in files.
Docs
| Guide | Covers |
|---|---|
| Theming | Tokens, light-dark(), data-bf-theme, starter themes |
| Components | Markup, behavior, JS status |
| JavaScript | Opt-in modules + the bf:* event contract |
| States | State machine, empty states, validation summaries |
| Adaptive / Layout | Container-aware components & primitives |
| Paint & paper | Validation, sticky tables, print |
| Form architecture | Async validation, wizards, field arrays, the state boundary |
| Keyboard | Per-pattern keyboard maps, roving focus, nested dialogs, user preferences |
| Coexistence | Side-by-side @layer contract, the focus-ring audit, @import vs <link> |
| Debug | .bf-debug audit overlay: layer boundaries, orphan data-state flags, what CSS can't see |
| Accessibility / Performance | Conformance; byte and selector budgets (npm run perf) |
| Migration | v4 · v5 · v3 |
| Status & plan | What's built, what's next |
Develop
npm install
npm run check # build + size budget + docs + lint
npm run preview # serve demo/ at localhost:4173Testing
Chromium by default; Firefox / WebKit / axe / visual via flags:
npm test # all suites (Chromium)
npm run test:a11y # axe-core only
npm run test:ff # Firefox
npm run test:webkit # WebKit
npm run test:visual:update # regenerate baselines (deliberate only)CI runs build + a11y + behavior (Chromium, Firefox, WebKit) + visual regression. Docs + demo deploy to GitHub Pages on every push to main.
License
MIT — go build something. Shoes optional.
