what.css is a utility-first CSS framework with semantic components, dark mode, and cascade layers. Your CSS always wins — no !important needed.
Every wwwhat project includes what.css automatically. It uses four cascade layers in this order:
@layer base, utilities, components, interactions;
| Layer | Contains |
|---|---|
base | Reset, CSS variables, theme tokens |
utilities | Spacing, layout, typography, colors |
components | Buttons, cards, forms, tables, alerts |
interactions | Modals, drawers, tooltips, transitions |
Because all framework styles live inside @layer, any CSS you write without a layer declaration automatically takes precedence. Override anything without fighting specificity.
Margin and padding use a numeric scale: 0, 1 (0.25rem), 2 (0.5rem), 3 (0.75rem), 4 (1rem), 6 (1.5rem), 8 (2rem).
| Pattern | Example | Result |
|---|---|---|
p-{n} | p-4 | padding: 1rem |
px-{n} / py-{n} | px-6 | padding-left: 1.5rem; padding-right: 1.5rem |
m-{n} | mt-8 | margin-top: 2rem |
gap-{n} | gap-4 | gap: 1rem |
space-y-{n} | space-y-4 | margin-top: 1rem between children |
<div class="flex items-center justify-between gap-4">
<span>Left</span>
<span>Right</span>
</div>
<div class="flex-col space-y-2">
<p>Stacked vertically</p>
<p>With spacing between</p>
</div>
Available: flex, grid, block, inline-flex, hidden, flex-col, flex-wrap, flex-1, items-center, justify-between, justify-center, self-center.
| Class | Effect |
|---|---|
text-sm, text-lg, text-xl, text-2xl | Font size |
font-bold, font-semibold, font-medium | Font weight |
text-center, text-right | Alignment |
truncate | Overflow ellipsis |
uppercase, capitalize | Transform |
text-muted | Muted color (gray-500) |
Text, background, and border colors follow the same naming pattern:
<p class="text-primary">Primary text</p>
<p class="text-danger">Error text</p>
<div class="bg-gray-100 border border-gray-200 rounded-lg p-4">
Subtle background with border
</div>
Available color groups: gray-{50-900}, primary-{50-900}, success, warning, danger, red, green, yellow, blue, indigo.
<button class="btn btn-primary">Save</button>
<button class="btn btn-outline">Cancel</button>
<button class="btn btn-danger btn-sm">Delete</button>
<button class="btn btn-success btn-lg btn-block">Submit</button>
Variants: btn-primary, btn-secondary, btn-success, btn-warning, btn-danger, btn-outline, btn-ghost, btn-link. Sizes: btn-sm, btn-lg, btn-xl. Modifiers: btn-block, btn-icon, btn-loading.
<div class="card">
<div class="card-header">
<h3 class="card-title">Title</h3>
</div>
<div class="card-body">Content here</div>
<div class="card-footer">Footer</div>
</div>
Variants: card-elevated, card-flat, card-bordered, card-interactive, card-horizontal. Sizes: card-sm, card-lg. Colors: card-primary, card-success, card-warning, card-danger.
<div class="form-group">
<label class="form-label">Email</label>
<input type="email" class="form-input" placeholder="you@example.com">
<span class="form-hint">We'll never share your email.</span>
</div>
Input classes: form-input, form-textarea, form-select, form-control (universal alias), form-checkbox, form-radio, form-switch. Helpers: form-label, form-group, form-error, form-hint. Sizes: form-control-sm, form-control-lg. Validation: is-valid, is-invalid, invalid-feedback.
<div class="table-container">
<table class="table table-striped table-hover">
<thead><tr><th>Name</th><th>Role</th></tr></thead>
<tbody><tr><td>Alice</td><td>Admin</td></tr></tbody>
</table>
</div>
<div class="alert alert-info">
<div class="alert-content">
<div class="alert-title">Heads up</div>
<p class="alert-description">This is an informational message.</p>
</div>
</div>
Variants: alert-info, alert-success, alert-warning, alert-danger. Sizes: alert-sm, alert-lg.
CSS Grid utilities for column layouts:
<div class="grid grid-cols-3 gap-4">
<div class="card card-body">One</div>
<div class="card card-body">Two</div>
<div class="card card-body">Three</div>
</div>
<!-- Spanning columns -->
<div class="grid grid-cols-4 gap-4">
<div class="col-span-2">Wide column</div>
<div>Normal</div>
<div>Normal</div>
</div>
<!-- Responsive: 1 col on mobile, 3 on desktop -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div>Card</div>
<div>Card</div>
<div>Card</div>
</div>
Available: grid-cols-1 through grid-cols-6, col-span-1 through col-span-3, col-span-full.
The entire framework is built on CSS custom properties. Override them to customize your theme:
:root {
/* Brand colors */
--w-primary-500: #8b5cf6;
--w-primary-600: #7c3aed;
--w-primary-700: #6d28d9;
/* Typography */
--w-font-sans: "Inter", sans-serif;
/* Spacing scale */
--w-spacing-4: 1.25rem;
/* Component-specific */
--w-btn-radius: 9999px;
--w-card-radius: 1rem;
}
| Group | Variables |
|---|---|
| Colors | --w-primary-{50-900}, --w-gray-{50-900}, --w-success-*, --w-danger-*, --w-warning-* |
| Semantic | --w-bg, --w-text, --w-border, --w-surface, --w-muted |
| Typography | --w-font-sans, --w-font-mono, --w-text-sm through --w-text-5xl |
| Spacing | --w-spacing-{0-24} |
| Components | --w-btn-*, --w-card-*, --w-alert-*, --w-modal-*, --w-input-*, --w-table-* |
Dark mode works two ways:
Automatic — Follows the OS/browser prefers-color-scheme preference. No setup required.
Manual — Add class="dark" to the <html> element. Use class="light" to force light mode and override OS preference.
<!-- Force dark mode -->
<html class="dark">
<!-- Force light mode (even if OS is dark) -->
<html class="light">
A common pattern for user-controlled dark mode:
<button onclick="toggleTheme()">Toggle Theme</button>
<script>
// Restore preference on load
(function() {
var theme = localStorage.getItem('w-theme');
if (theme === 'dark') document.documentElement.className = 'dark';
})();
function toggleTheme() {
var isDark = document.documentElement.classList.contains('dark');
document.documentElement.className = isDark ? 'light' : 'dark';
localStorage.setItem('w-theme', isDark ? 'light' : 'dark');
}
</script>
Dark mode automatically adjusts semantic tokens: --w-bg, --w-text, --w-border, --w-surface, and --w-muted all change to dark-appropriate values.
Responsive variants follow a {breakpoint}:{class} pattern:
| Prefix | Breakpoint |
|---|---|
sm: | 640px |
md: | 768px |
lg: | 1024px |
xl: | 1280px |
<!-- Stack on mobile, row on desktop -->
<div class="flex flex-col md:flex-row gap-4">...</div>
<!-- 1 column on mobile, 2 on tablet, 3 on desktop -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">...</div>
<!-- Hide on mobile -->
<nav class="hidden-mobile">Desktop navigation</nav>
Convenience classes: hidden-mobile (below 640px) and hidden-desktop (640px and above).
Add your own stylesheet after what.css. Thanks to cascade layers, your rules take priority without !important:
<link rel="stylesheet" href="/static/what.css">
<link rel="stylesheet" href="/static/styles.css">
/* These override framework styles automatically */
.btn {
border-radius: 9999px;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.card {
border: 2px solid var(--w-primary-200);
}
/* Add new component styles */
.pricing-card {
background: linear-gradient(135deg, var(--w-primary-50), var(--w-white));
border: 1px solid var(--w-primary-200);
border-radius: var(--w-rounded-xl);
padding: 2rem;
}
.btn { --w-btn-radius: 9999px; }. This changes the variable the framework uses internally, keeping all other button styles intact.