Build with Boobstrap.
A CSS-first framework for responsive layouts, polished components, practical utilities, and optional behavior. Bring your own JavaScript, use Boobstrap's dependency-free controllers, or add the official Alpine adapter.
Installation
Install the same npm registry package with your preferred package manager, then import the compiled stylesheet once at your application entry point.
npm install @boobstrap/boobstrap
import "@boobstrap/boobstrap/dist/boobstrap.css";
Use from a CDN
For a plain HTML project, load the version-pinned stylesheet directly from jsDelivr:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@boobstrap/boobstrap@0.2.0/dist/boobstrap.css" />
To self-host instead, copy dist/boobstrap.css from the installed package into your assets.
Every public framework class starts with bs-. Boobstrap does apply a small element reset and base typography, but component and utility styles stay namespaced.
Starter template
Download a minimal Vite project that imports @boobstrap/boobstrap from npm. It includes a responsive landing page, theme-token overrides, components, a labeled form, dependency-free inline SVG icons, and a production validation check.
A real project, not just a snippet
Install, run the Vite dev server, customize the semantic tokens, then validate the production bundle with one command.
index.html
src/main.js
src/styles.css
scripts/validate.mjs
package.json
npm install
npm run dev
npm run validate
Theming
Dark mode is the default. Set data-bs-theme="light" on any ancestor to switch that subtree to the built-in light palette. Theme attributes can live on <html>, a page shell, or an individual preview.
Night by default
Deep plum surfaces with warm pink accents.
Bright when needed
The same semantic tokens, remapped for light surfaces.
<html data-bs-theme="light">
Customize semantic tokens
Override variables after importing Boobstrap. Components consume semantic tokens such as --bs-color-primary, so a small override updates the whole system.
:root {
--bs-color-primary: #8b5cf6;
--bs-color-primary-hover: #a78bfa;
--bs-radius-md: 0.5rem;
}
Typography
Headings and body copy receive sensible defaults. Use .bs-display for oversized hero text and .bs-lead for introductory copy.
Boobstrap
Heading one
Heading two
Heading three
Lead copy introduces a section with a larger, muted treatment.
Body copy inherits the framework text color and a comfortable 1.6 line height.
<h1 class="bs-display bs-text-gradient">Build boldly.</h1>
<p class="bs-lead">Thoughtful defaults, ready to ship.</p>
Layout & grid
.bs-container centers content with a fluid gutter and a 90rem ceiling. Add a size modifier for narrower content. .bs-section provides fluid vertical rhythm.
| Class | Maximum width |
|---|---|
.bs-container | --bs-container-2xl · 90rem |
.bs-container-sm | 40rem |
.bs-container-md | 48rem |
.bs-container-lg | 64rem |
.bs-container-xl | 76rem |
12-column grid
Use .bs-grid or its alias .bs-row, then assign column spans. Unprefixed columns work at every width; md begins at 48rem and lg at 64rem.
<div class="bs-grid bs-gap-4">
<div class="bs-col-12 bs-col-md-6 bs-col-lg-4">...</div>
<div class="bs-col-12 bs-col-md-6 bs-col-lg-8">...</div>
</div>
Responsive layout composition
Start every region at 12 columns, then opt into wider arrangements at md and lg. The markup stays in a useful reading order at every width.
A wide story at large screens
This region spans the full row on mobile and eight columns from the large breakpoint.
Supporting detail
Two equal cards from the medium breakpoint.
Another detail
Source order remains the mobile reading order.
<section class="bs-container bs-section" aria-labelledby="features-title">
<h2 id="features-title">Features</h2>
<div class="bs-grid bs-gap-4">
<article class="bs-card bs-col-12 bs-col-lg-8">…</article>
<aside class="bs-card bs-col-12 bs-col-md-6 bs-col-lg-4">…</aside>
</div>
</section>
Structure
Use a labeled <section> for the region, then place articles, asides, or plain containers directly inside the grid.
Class map
.bs-grid creates 12 tracks. .bs-col-12 is the mobile baseline; md applies from 48rem and lg from 64rem.
Accessibility
Keep the DOM in a logical small-screen reading order. Breakpoint classes should change presentation without changing meaning or focus order.
Responsive breakpoints
Column spans are mobile-first. Start with an unprefixed span, then override it only where the composition needs more room.
| Prefix | Starts at | Example |
|---|---|---|
| None | All viewport widths | .bs-col-12 |
md | 48rem / 768px | .bs-col-md-6 |
lg | 64rem / 1024px | .bs-col-lg-4 |
Buttons
Start with .bs-btn, add one visual variant, and optionally add a size or icon modifier. The same classes work on buttons and links.
<button class="bs-btn bs-btn-primary" type="button">Save changes</button>
<a class="bs-btn bs-btn-secondary" href="/docs">Read docs</a>
<button class="bs-btn bs-btn-secondary bs-btn-icon" type="button" aria-label="Favorite">…</button>
Structure
Use <button type="button"> for in-page actions and <a href> when the control navigates somewhere.
Class map
.bs-btn supplies structure. Add one of primary, secondary, or ghost, then an optional size or .bs-btn-icon.
Accessibility
Icon-only buttons need an aria-label. Hide a decorative SVG with aria-hidden="true", and use the native disabled attribute when unavailable.
Button API
Every button starts with the base class. Add one visual variant and, when needed, one size or shape modifier.
| Class | Purpose | Use when |
|---|---|---|
.bs-btn | Shared sizing, alignment, focus, and interaction styles. | Always required. |
.bs-btn-primary | High-emphasis gradient action. | One primary action per region. |
.bs-btn-secondary | Bordered, lower-emphasis action. | Alternative or supporting actions. |
.bs-btn-ghost | Minimal transparent action. | Tertiary actions and quiet navigation. |
.bs-btn-icon | Square button dimensions. | The accessible name is not visible. |
.bs-btn-sm / .bs-btn-lg | Compact or prominent sizing. | Dense toolbars or hero actions. |
Badges
Badges are compact status and metadata labels. Use the base class alone for a neutral badge or add the primary modifier.
<span class="bs-badge bs-badge-primary">New release</span>Cards
Cards establish a contained surface. Structure content with the body, title, and text classes; add .bs-card-raised when the card needs more visual elevation.
A thoughtful default
Contained content with a subtle border and surface treatment.
Explore the API →Extra elevation
The raised modifier adds a stronger shadow without changing structure.
<article class="bs-card bs-card-raised" aria-labelledby="launch-card-title">
<div class="bs-card-body">
<h3 class="bs-card-title" id="launch-card-title">Launch ready</h3>
<p class="bs-card-text">Supporting copy.</p>
<a class="bs-btn bs-btn-primary bs-btn-sm" href="/details">View details</a>
</div>
</article>Structure
Place content inside .bs-card-body, then use a real heading, supporting text, and the smallest set of actions the card needs.
Class map
.bs-card creates the surface, .bs-card-body adds inset spacing, and .bs-card-raised increases elevation without changing structure.
Accessibility
Use <article> only for standalone content. Give repeated cards headings, and avoid a whole-card link when nested controls are present.
Card API
Cards are intentionally small: one shell, one content wrapper, and optional typography and elevation helpers.
| Class | Purpose |
|---|---|
.bs-card | Surface, border, radius, clipping, and default elevation. |
.bs-card-raised | Stronger shadow for elevated or featured content. |
.bs-card-body | Responsive inset padding for card content. |
.bs-card-title | Consistent spacing below the card heading. |
.bs-card-text | Muted supporting-copy color. |
Alerts
Alerts communicate inline feedback. Pair .bs-alert with a state modifier and use .bs-alert-title for a clear lead-in.
<div class="bs-alert bs-alert-success" role="status">
<svg class="bs-icon bs-icon-lg" aria-hidden="true">…</svg>
<span><strong class="bs-alert-title">Saved</strong> Your changes were published.</span>
</div>Structure
Combine an optional decorative icon with a text wrapper. Put the short summary in .bs-alert-title before the supporting message.
Class map
.bs-alert is neutral. Add .bs-alert-primary for highlighted guidance or .bs-alert-success for successful outcomes.
Accessibility
Use role="status" for dynamic, non-urgent feedback and role="alert" sparingly for urgent errors. Never rely on color alone.
Alert API
The visual variant describes emphasis; the ARIA role describes announcement behavior. Choose each independently.
| Class | Purpose |
|---|---|
.bs-alert | Neutral alert layout, spacing, border, and surface. |
.bs-alert-title | High-contrast summary placed before supporting copy. |
.bs-alert-primary | Brand-highlighted guidance or informational emphasis. |
.bs-alert-success | Successful completion or confirmation feedback. |
Forms
Boobstrap styles native controls without replacing their semantics. Keep labels associated with controls and use .bs-form-group to establish consistent spacing.
<form action="/contact" method="post">
<div class="bs-form-group">
<label class="bs-label" for="email">Email</label>
<input class="bs-input" id="email" name="email" type="email" required />
</div>
<button class="bs-btn bs-btn-primary bs-mt-4" type="submit">Subscribe</button>
</form>Structure
Group each visible label with one native control. The form owns submission details; every submitted control needs a stable name.
Class map
.bs-form-group controls spacing. Apply .bs-input, .bs-select, or .bs-textarea to the matching native element.
Accessibility
Match for and id, choose the correct type and autocomplete token, and connect help or error text with aria-describedby.
Form API
These classes style native controls without replacing their built-in semantics, validation, autocomplete, or keyboard behavior.
| Class | Apply to | Purpose |
|---|---|---|
.bs-form-group | Wrapper | Consistent label-to-control spacing. |
.bs-label | <label> | Readable label size, weight, and color. |
.bs-input | <input> | Text-like native input treatment. |
.bs-select | <select> | Native selection control treatment. |
.bs-textarea | <textarea> | Resizable multiline control treatment. |
Code windows
The code-window family provides a complete presentation shell and optional syntax-color helpers. It does not perform syntax highlighting; apply the token classes in server-rendered or hand-authored markup.
<!-- Build boldly --> <button class="bs-btn bs-btn-primary"> Ship it </button> const ready = true;
.bs-code-window as the shell, .bs-code-toolbar for chrome, .bs-code-dots and three .bs-code-dot elements for the controls, and .bs-code-body on the <pre>.Code window API
Syntax classes only color tokens you mark up; Boobstrap does not ship a parser or client-side highlighter.
| Class | Purpose |
|---|---|
.bs-code-window | Outer shell, border, background, and clipping. |
.bs-code-toolbar | Optional filename or control row. |
.bs-code-body | Scrollable, formatted code content. |
.bs-code-tag | HTML tags and selectors. |
.bs-code-attribute | Attributes and property names. |
.bs-code-string | Quoted values and literals. |
.bs-code-comment | Comments and secondary annotations. |
Icons
Boobstrap keeps icons library-agnostic. Add .bs-icon to any inline SVG to normalize its size, alignment, and current-color stroke; use .bs-icon-sm, .bs-icon-lg, or .bs-icon-xl for scale.
<svg class="bs-icon bs-icon-lg" viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 3v18m9-9H3" />
</svg>
If you want a ready-made icon set, install one separately. For example, Lucide can replace matching SVG elements at runtime while Boobstrap remains CSS-only:
npm install lucide
import { createIcons, icons } from "lucide";
createIcons({ icons });
aria-hidden="true"; meaningful icons need an accessible label or visible text.Icon sizing
Icon utilities use em, so an icon follows the surrounding text or button size without a separate breakpoint system.
| Class | Rendered size |
|---|---|
.bs-icon | 1em with normalized current-color stroke. |
.bs-icon-sm | 0.875em |
.bs-icon-lg | 1.25em |
.bs-icon-xl | 1.5em |
Choose your behavior layer
Boobstrap never requires a runtime. Static HTML can use the complete visual system by itself; interactive projects can bring their own state, initialize Boobstrap's dependency-free controllers, or let Alpine own the same component contract.
CSS only
Use semantic markup and every bs- class without loading JavaScript.
Boobstrap JS
Progressively enhance collapse, dropdown, and tabs through explicit, tree-shakable controllers.
Alpine.js
Keep reactive state in Alpine with reusable x-data providers and x-bind objects.
Every interactive example below includes a Boobstrap JS / Alpine.js code switcher. The classes and accessibility contract stay consistent while the selected behavior layer owns state.
Importing the stylesheet remains runtime-free. Initialize all supported controllers, or import one component from a dedicated subpath.
npm install @boobstrap/boobstrap
import "@boobstrap/boobstrap";
import { initBoobstrap } from "@boobstrap/boobstrap/js";
const boobstrap = initBoobstrap();
The adapter registers bsCollapse, bsDropdown, and bsTabs. Register it before starting Alpine. The same plugin also supports @alpinejs/csp.
npm install @boobstrap/boobstrap @boobstrap/alpine alpinejs
import "@boobstrap/boobstrap";
import Alpine from "alpinejs";
import boobstrap from "@boobstrap/alpine";
Alpine.plugin(boobstrap);
Alpine.start();
View @boobstrap/alpine on npm. Alpine remains an application-level peer dependency and is never installed by the core framework.
Collapse
Reveal supporting content without removing it from the document. The controller synchronizes the native hidden attribute, aria-expanded, and data-bs-state.
The panel remains semantic HTML before and after enhancement.
<button class="bs-btn bs-btn-secondary" type="button"
data-bs-toggle="collapse" aria-controls="details">
Toggle details
</button>
<div class="bs-collapse" id="details" hidden>
Progressive by design.
</div>
<div x-data="bsCollapse">
<button class="bs-btn bs-btn-secondary" type="button"
x-bind="trigger" aria-controls="details">
Toggle details
</button>
<div class="bs-collapse" id="details" x-bind="panel" hidden>
Progressive by design.
</div>
</div>
Structure
Give the panel a unique id and reference it from the trigger's aria-controls.
State
.bs-collapse supplies the visual contract; hidden is the readable initial state.
Accessibility
Use a real button. The controller maintains aria-expanded and fires cancelable show/hide events.
Collapse API
Import Collapse from @boobstrap/boobstrap/js/collapse for direct control.
| Contract | Purpose |
|---|---|
show() / hide() | Change visibility and synchronized public state. |
toggle() | Invert the current panel state. |
bs:collapse:* | Cancelable before-events and bubbling completed-events. |
Dropdown
Dropdowns support pointer dismissal, item selection, Escape, Tab, arrow keys, Home, and End. Disabled items are skipped.
<div class="bs-dropdown" data-bs-dropdown>
<button class="bs-btn" id="actions-toggle" type="button"
data-bs-toggle="dropdown" aria-controls="actions-menu">Actions</button>
<div class="bs-dropdown-menu" id="actions-menu" role="menu"
aria-labelledby="actions-toggle" data-bs-dropdown-menu hidden>
<button class="bs-dropdown-item" type="button" role="menuitem">Edit</button>
</div>
</div>
<div class="bs-dropdown" x-data="bsDropdown" x-bind="root">
<button class="bs-btn" id="actions-toggle" type="button"
data-bs-toggle="dropdown" x-bind="trigger" aria-controls="actions-menu">
Actions
</button>
<div class="bs-dropdown-menu" id="actions-menu" role="menu"
aria-labelledby="actions-toggle" data-bs-dropdown-menu x-bind="menu" hidden>
<button class="bs-dropdown-item" type="button" role="menuitem">Edit</button>
</div>
</div>
Structure
Keep the toggle and menu in one .bs-dropdown root, and label the menu from its toggle.
Class map
.bs-dropdown-menu-end aligns the popup to the opposite inline edge when needed.
Accessibility
Use role="menu" and role="menuitem" only for action menus, not ordinary site navigation.
Dropdown API
Import Dropdown from @boobstrap/boobstrap/js/dropdown.
| Contract | Purpose |
|---|---|
show() / hide() | Open or close the menu; hide can optionally restore focus. |
toggle() | Invert the current menu state. |
bs:dropdown:* | Observe or cancel menu lifecycle transitions. |
Tabs
Tabs use automatic activation and a roving tabindex. Horizontal lists use Left/Right; vertical lists use Up/Down. Both support Home and End.
<div class="bs-tabs" role="tablist" aria-label="Account" data-bs-tabs>
<button class="bs-tab" id="profile-tab" type="button" role="tab"
aria-controls="profile-panel" aria-selected="true">Profile</button>
<button class="bs-tab" id="security-tab" type="button" role="tab"
aria-controls="security-panel">Security</button>
</div>
<div class="bs-tab-panel" id="profile-panel" role="tabpanel"
aria-labelledby="profile-tab">Profile settings</div>
<div class="bs-tab-panel" id="security-panel" role="tabpanel"
aria-labelledby="security-tab" hidden>Security settings</div>
<section x-data="bsTabs">
<div class="bs-tabs" role="tablist" aria-label="Account" x-bind="tablist">
<button class="bs-tab" id="profile-tab" type="button" role="tab"
x-bind="tab" aria-controls="profile-panel" aria-selected="true">Profile</button>
<button class="bs-tab" id="security-tab" type="button" role="tab"
x-bind="tab" aria-controls="security-panel">Security</button>
</div>
<div class="bs-tab-panel" id="profile-panel" role="tabpanel"
aria-labelledby="profile-tab" x-bind="panel">Profile settings</div>
<div class="bs-tab-panel" id="security-panel" role="tabpanel"
aria-labelledby="security-tab" x-bind="panel" hidden>Security settings</div>
</section>
Structure
Each tab's aria-controls and panel's aria-labelledby form a two-way relationship.
State
The selected tab gets aria-selected="true"; every inactive panel uses hidden.
Accessibility
Use tabs only when panels are peer views. Preserve meaningful headings inside complex panels.
Tabs API
Import Tabs from @boobstrap/boobstrap/js/tabs.
| Contract | Purpose |
|---|---|
activate(tab) | Select a tab element and synchronize all controlled panels. |
bs:tabs:change | Cancelable before-event with previous and next tab/panel detail. |
bs:tabs:changed | Bubbling event after the completed transition. |
Utilities
Utilities are single-purpose helpers designed for composition. Responsive display helpers use the md breakpoint at 48rem.
Display & flex
.bs-block, .bs-inline-block, .bs-flex, .bs-inline-flex, .bs-hidden, .bs-stack, .bs-flex-wrap, .bs-flex-1.
Alignment
.bs-items-start, .bs-items-center, .bs-items-end, .bs-justify-start, .bs-justify-center, .bs-justify-between, .bs-justify-end, .bs-self-center.
Sizing & position
.bs-w-full, .bs-h-full, .bs-relative, .bs-overflow-hidden.
Responsive display
.bs-md-flex, .bs-md-block, and .bs-md-hidden apply from 48rem upward.
Gap
.bs-gap-{n} supports 1, 2, 3, 4, 5, 6, 8, 10, 12 and maps directly to spacing tokens.
Margin
.bs-m-0, .bs-mx-auto, .bs-mt-{n} for 2, 3, 4, 6, 8, 10, and .bs-mb-{n} for 0, 2, 4, 6.
Padding
.bs-p-{n} for 0, 2, 3, 4, 5, 6, 8; .bs-px-{n} for 4, 6; .bs-py-{n} for 2, 4, 6, 8.
Text
Sizes .bs-text-xs through .bs-text-3xl; alignment, semantic colors, gradient text, font weights, italic, link decoration, and screen-reader-only helpers.
Spacing scale
Design tokens
All framework decisions are exposed as CSS custom properties. Color tokens may be remapped by a theme; typography, spacing, radius, elevation, container, and motion tokens are shared.
All classes
This index is generated from the exact compiled stylesheet used by this site. It includes every public bs- selector and its core declaration.
Accessibility
Boobstrap supplies visible focus treatment, reduced-motion safeguards, accessible color foundations, and .bs-sr-only. Your markup still owns semantics and behavior.
- Use native elements first:
<button>for actions and<a>for navigation. - Associate every form control with a visible
<label>, or use.bs-sr-onlywhen the visual design cannot accommodate one. - Add
aria-labelto icon-only buttons. - Use
role="status"for non-urgent dynamic alerts androle="alert"for urgent messages. - Do not rely on color alone to communicate state; pair it with text or an icon.
- When overriding tokens, re-check text and focus-ring contrast in both themes.
The base reset reduces animation and transition durations when the user enables prefers-reduced-motion: reduce.