---
name: oat-css
description: Our preferred CSS framework — ultra-lightweight, semantic HTML UI library (~8KB). Style web UIs with semantic HTML and minimal classes. Override with app-level SCSS only when necessary.
license: MIT
authors: "SpinSpire Team"
---
# Oat CSS
Oat is an ultra-lightweight (~8KB min+gz), zero-dependency, semantic HTML/CSS/JS UI library by [Kailash Nadh](https://nadh.in) (5k+ stars on [GitHub](https://github.com/knadh/oat)). It styles native HTML elements out of the box — no classes needed for basic UIs. Dynamic components use WebComponents with minimal JS.
**Philosophy:** Semantic tags and attributes are styled contextually without classes, forcing best practices and reducing markup class pollution. Only reach for custom CSS when Oat's defaults don't cover your use case.
## Installation
### npm (SvelteKit, Vite, etc.)
```
bun add @knadh/oat
```
In your app entry or root SCSS:
```scss
@import '@knadh/oat/oat.min.css';
```
Import the JS for dynamic components (dialog, dropdown, tabs, toast, tooltip, sidebar):
```ts
import '@knadh/oat/oat.min.js';
```
Or selectively import individual files from `@knadh/oat/css/` and `@knadh/oat/js/`.
### CDN
```html
```
## Core Principle
**Use semantic HTML. Oat styles elements based on their tag and ARIA attributes, not CSS classes.**
```html
Content
```
## When to Add Custom CSS/SCSS
Only override when:
1. **Brand colors** — redefine CSS variables in `:root` (see Theming below)
2. **Layout** — use Oat's `.hstack`, `.vstack`, `.container`/`.row`/`.col-*` grid, or add your own
3. **Complex compositions** — recipes like stats cards, split buttons, form cards
4. **Custom animations or interactions** — Oat doesn't ship opinionated transitions beyond the basics
Every Oat component below is purely semantic HTML. No custom CSS needed.
## Components
### Typography
```html
Heading 1 Heading 2 Heading 3
Paragraph with bold , italic , and a link .
code block
Blockquote
Ordered item
```
### Button
`` is styled by default. Use `data-variant` for semantics, `.outline`/`.ghost` for style, `.small`/`.large` for size.
```html
Primary
Secondary
Danger
Outline
Ghost
Small
Large
Disabled
Link as button
```
Button group:
```html
Left
Center
Right
```
### Card
```html
Content here.
```
### Alert
Use `role="alert"` with optional `data-variant` (`success`, `warning`, `error`).
```html
Success! Your changes have been saved.
Warning! Please review before continuing.
Info This is a default alert.
Error! Something went wrong.
```
### Form
Wrap inputs in `` for proper styling. Input groups use ``.
```html
```
### Dialog (modal)
Uses native `` with `commandfor`/`command` attributes (zero JS required).
```html
Open
```
### Dropdown
Uses `` WebComponent + native Popover API.
```html
Options ▾
```
### Tabs
Uses `` WebComponent.
```html
Account
Password
Account Settings
Password Settings
```
### Table
```html
```
### Badge
```html
Default
Success
Danger
Warning
Outline
```
### Accordion
Native ``/``.
```html
What is Oat?
Oat is a minimal, semantic-first UI library.
Grouped
```
### Progress & Meter
```html
```
### Spinner
```html
Loading
Content dims
```
### Skeleton
```html
```
### Avatar
```html
OT
```
### Sidebar
```html
☰
App
...
```
### Toast
```js
ot.toast('Saved!', 'Success', { variant: 'success' })
ot.toast('Error!', 'Oops', { variant: 'danger', placement: 'top-left' })
ot.toast('Warning', null, { variant: 'warning' })
ot.toast('Info', null, { placement: 'top-center' })
// Custom HTML
ot.toast.el(document.querySelector('#my-toast-template'), { duration: 8000 })
// Clear all
ot.toast.clear()
```
### Tooltip
Just use the `title` attribute.
```html
Save
Left
Bottom
```
### Grid
12-column CSS grid.
```html
```
### Utilities
Common utility classes from `utilities.css`:
| Class | Purpose |
|---|---|
| `.hstack` | Horizontal flex container |
| `.vstack` | Vertical flex container |
| `.justify-start/center/end/between` | Flex justify |
| `.items-start/center/end` | Flex align |
| `.gap-{0-8}` | Gap spacing |
| `.mt-{0-8}`, `.mb-{0-8}`, `.mx-{0-8}`, `.my-{0-8}` | Margin |
| `.pt-{0-8}`, `.pb-{0-8}`, `.px-{0-8}`, `.py-{0-8}` | Padding |
| `.text-light` | Muted text |
| `.text-center` | Center text |
| `.align-center` | Center content |
| `.unstyled` | Remove list/button default styles |
| `.table` | Scrollable table wrapper |
| `.badge` | Badge/tag |
| `.button` | Link styled as button |
| `.skeleton` | Loading placeholder |
| `.outline` | Outline variant for buttons |
| `.ghost` | Ghost variant for buttons |
| `.small`, `.large` | Size modifier |
## Theming
If asked to customize the default oat-css theme, first offer to replicate one of the themes from https://oat.ink/demo/
If the user still wants to create a new theme, then override ONLY (minimal) what needs to be overridden in ":root".
Oat uses `light-dark()` for automatic dark mode based on system preference.
See the full list at [theme.css](https://github.com/knadh/oat/blob/master/src/css/01-theme.css).
### Dark mode
Set `data-theme="dark"` on `` to force dark. Oat also auto-detects `prefers-color-scheme`.
### Design tokens
Oat exposes spacing, typography, shadow, and radius tokens:
```scss
.custom {
padding: var(--space-4);
margin-block-end: var(--space-6);
border-radius: var(--radius-medium);
box-shadow: var(--shadow-medium);
transition: transform var(--transition-fast);
}
```
## Community Usage & Extensions
Oat is created by [Kailash Nadh](https://nadh.in) and used in his own projects. The community has built:
- **[oat-chips](https://github.com/someshkar/oat-chips)** — Chip/tag component with filters, colors, selection
- **[oat-animate](https://github.com/dharmeshgurnani/oat-animate)** — Lightweight animation extension with `in-view`, `hover`, `on-load` triggers
- **[oat-table](https://github.com/MADEVAL/Oat-Table)** — Sort, filter, and select rows in semantic ``
Oat is compared alongside Water.css, Pico CSS, and MVP.css as a minimal, classless, or semantic-first CSS framework. Its distinctive traits are the shadcn-inspired aesthetic, WebComponents for dynamic widgets (tabs, dropdown), and the sub-10KB bundle.
## Icons
Oat doesn't bundle an icon set. The approach that fits Oat's philosophy (zero dependencies, vanilla HTML, no build step) is the **SVG sprite** pattern: one `.svg` file referenced via `` in your HTML.
```html
```
Style with CSS — size via `width`/`height`, color via `color`/`fill`.
### Recommended: Bootstrap Icons
Lightest sprite (578 KB raw, ~96 KB gzipped), 2,000+ icons, clean design that matches Oat's aesthetic, MIT license.
| Method | Link |
|--------|------|
| CDN | `https://unpkg.com/bootstrap-icons@1.11.3/bootstrap-icons.svg` |
| npm | `npm install bootstrap-icons`, copy `node_modules/bootstrap-icons/bootstrap-icons.svg` |
```html
```
Browse icons at https://icons.getbootstrap.com — the icon name is the filename without `.svg`.
### Alternative: Tabler Icons
6,128 icons, slightly heavier sprite (2 MB raw, ~700 KB gzipped), more variety and a modern 2px-stroke style. MIT license.
```html
```
### Tradeoffs
- **SVG sprite** — one HTTP request, cached after first visit, no JS, no build step. The full set is always loaded regardless of which icons you use (not tree-shakeable).
- **Tree-shakeable npm packages** (Lucide, Boxicons, Heroicons) require a bundler and a framework — they don't fit Oat's vanilla HTML + CSS philosophy. Use them only if you're already committed to a JS build pipeline.
- **Custom sprite** — for maximum minimalism, use a CLI like `svg-sprite` to build a sprite with only the icons you need. Adds a build step but minimizes payload.
### Icon button helper
Oat's `.icon` utility sizes a button for icon-only usage:
```html
```
## Real-world patterns
These compositions use only Oat's built-in components and utility classes — no custom CSS:
**Stats cards (dashboard metrics):**
```html
```
**Form card:**
```html
Name
Notifications
```
**Empty state:**
```html
Nothing here yet
Create something to get started.
```
## Key Guidelines
1. **Reach for semantic HTML first** — a `` is already styled, a `` already works
2. **Use `data-variant`** (not custom classes) for color semantics: `primary`, `secondary`, `success`, `danger`, `warning`
3. **Use ARIA attributes** (`role="alert"`, `aria-busy="true"`, `role="switch"`) — Oat styles them automatically
4. **Prefer Oat's composable components** (card + hstack + badge + progress) over writing custom SCSS
5. **Override CSS variables** for theming instead of writing component-level overrides
6. **Keep HTML clean** — minimal classes, semantic tags, readable structure
7. **Only write custom SCSS when** Oat doesn't provide a component, or your layout needs unique structure not covered by `.hstack`/`.vstack`/`.grid`