Getting Started v1.0.0
Quick Start
Include the CSS and JS files in your HTML. No build tools needed.
<!-- CSS -->
<link rel="stylesheet" href="css/vanduo.css">
<!-- JS (order matters) -->
<script src="js/utils/helpers.js"></script>
<script src="js/vanduo.js"></script>
<!-- Add only the components you need -->
<script src="js/components/navbar.js"></script>
<script src="js/components/modals.js"></script>
<!-- ... -->
Modular CSS Imports
Import only what you need instead of the full bundle:
<!-- Full framework -->
<link rel="stylesheet" href="css/vanduo.css">
<!-- Or pick individual modules -->
<link rel="stylesheet" href="css/core/reset.css">
<link rel="stylesheet" href="css/core/colors.css">
<link rel="stylesheet" href="css/core/typography.css">
<link rel="stylesheet" href="css/core/grid.css">
<link rel="stylesheet" href="css/components/buttons.css">
<!-- ... add what you need -->
CSS Variable Customization
Override CSS variables in your own stylesheet to customize the entire framework:
:root {
/* Brand colors */
--color-primary: #6366f1;
--color-primary-dark: #4f46e5;
--color-primary-light: #818cf8;
/* Typography */
--font-family-base: 'Inter', sans-serif;
--font-size-base: 1rem;
/* Spacing (Fibonacci-based) */
--spacing-1: 1px; --spacing-2: 2px;
--spacing-3: 3px; --spacing-5: 5px;
--spacing-8: 8px; --spacing-13: 13px;
/* Borders */
--border-color: #e2e8f0;
--btn-border-radius: 8px;
}
Theme Switching
Vanduo supports light, dark, and system themes. Preference is stored in
localStorage.
<!-- Select-based toggle -->
<select data-toggle="theme">
<option value="system">System</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
<!-- Or button toggle (cycles modes) -->
<button data-toggle="theme">Toggle</button>
How it works:
data-toggle="theme"binds the element- Preference saved to
vanduo-theme-preferencekey - Sets
[data-theme="dark"]on<html> - System mode removes the attribute, deferring to
prefers-color-scheme
Data Attributes Reference
JavaScript components are configured via data-* attributes:
| Attribute | Component |
|---|---|
data-modal="#id" |
Modal trigger |
data-dismiss="modal" |
Modal close button |
data-tooltip="text" |
Tooltip content |
data-placement="top|right|bottom|left" |
Tooltip position |
data-toggle="theme" |
Theme switcher |
data-toggle="font" |
Font switcher |
data-collapsible |
Collapsible container |
data-speed="0.5" |
Parallax layer speed |
JavaScript API
All components register with the global Vanduo object:
// Re-initialize a component after DOM changes
Vanduo.reinit('dropdown');
// Destroy all component instances (cleanup)
Vanduo.destroyAll();
// Register a custom component
Vanduo.register('myComponent', {
init: function() { /* ... */ }
});
// Show a toast notification
Vanduo.components.toast.show({
title: 'Success',
message: 'Item saved.',
type: 'success'
});
CSS State Classes:
.is-open— open state (modals, dropdowns, sidenav).is-active— active state (tabs, accordion items).disabled— disabled state
Icons
Vanduo includes Phosphor Icons — a flexible icon family with 1,500+ icons in 6 weights. Icons are bundled locally with no external dependencies.
Quick Start
Include the icons stylesheet and use <i> elements with the
appropriate classes:
<!-- Include default weights (regular + fill) -->
<link rel="stylesheet" href="css/icons/icons.css">
<!-- Use icons -->
<i class="ph ph-heart"></i>
<i class="ph-fill ph-star"></i>
<i class="ph ph-house"></i>
Import Options
<!-- Default (regular + fill) - Recommended -->
<link rel="stylesheet" href="css/icons/icons.css">
<!-- All 6 weights (~3MB) -->
<link rel="stylesheet" href="css/icons/icons-all.css">
<!-- Individual weights -->
<link rel="stylesheet" href="icons/phosphor/bold/style.css">
<link rel="stylesheet" href="icons/phosphor/light/style.css">
Icon Weights
6 distinct weights for different visual styles:
Regular.ph
Fill.ph-fill
Bold.ph-bold
Light.ph-light
Thin.ph-thin
Duotone.ph-duotone
Note: Only regular and fill weights are loaded by default. Other weights require importing their CSS.
Example Icons
Browse all 1,500+ icons at phosphoricons.com
Styling Icons
Icons are font-based — style them with CSS:
<!-- Size with font-size -->
<i class="ph ph-heart" style="font-size: 48px;"></i>
<!-- Color with color -->
<i class="ph-fill ph-star" style="color: gold;"></i>
<!-- Use CSS variables -->
<i class="ph ph-check" style="color: var(--color-success);"></i>
Icons in Buttons
Icons by Phosphor Icons — MIT Licensed
Color Palette
Vanduo uses the Open Color palette (MIT License) — a battle-tested, accessible color system with 10-step scales for each hue. Perfect for the "no-build" philosophy.
Primary — Cyan (Brand)
The "Water" brand color for Vanduo
Secondary — Teal
Complementary to Cyan for secondary actions
Gray — Neutrals
Used for backgrounds, borders, text, and UI structure
Danger — Red
Error states, destructive actions
Success — Green
Success states, confirmations
Warning — Yellow
Warnings, cautions, attention
Info — Blue
Information, help, neutral feedback
CSS Variable Usage
/* Direct scale access */
.my-element {
background: var(--primary-0); /* Lightest */
color: var(--primary-9); /* Darkest */
}
/* Semantic aliases (recommended) */
.my-button {
background: var(--color-primary);
border-color: var(--color-primary-dark);
}
/* Hover states using scale */
.my-button:hover {
background: var(--primary-6);
}
.my-button:active {
background: var(--primary-7);
}
Theming Guide
To change the primary color to another Open Color hue (e.g., Violet):
:root {
/* Swap Cyan with Violet */
--primary-0: #f3f0ff;
--primary-1: #e5dbff;
--primary-2: #d0bfff;
--primary-3: #b197fc;
--primary-4: #9775fa;
--primary-5: #845ef7;
--primary-6: #7950f2;
--primary-7: #7048e8;
--primary-8: #6741d9;
--primary-9: #5f3dc4;
}
All components using --primary-* or --color-primary will automatically update.
Color palette based on Open Color by Heeyeun Jeong — MIT Licensed
Typography
Headings
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Text Utilities
Primary text color
Secondary text color
Success text color
Warning text color
Error text color
Info text color
Muted text color
Small text
Large text
Bold text
Italic text
Color Utilities
Grid System
A comprehensive 12-column flexbox grid with Fibonacci/Golden Ratio proportional layouts, responsive containers, order utilities, and an interactive toggle between standard and Fibonacci modes.
2XL Breakpoint (1400px)
The grid now supports all 6 breakpoints: base, sm (576px), md (768px), lg (992px), xl (1200px), and 2xl (1400px).
Responsive Containers
Responsive containers are fluid below their breakpoint and fixed-width above. They scale up at each subsequent breakpoint.
.container-sm — fixed from 576px (540px, scales up)
.container-md — fixed from 768px (720px, scales up)
.container-lg — fixed from 992px (960px, scales up)
.container-xl — fixed from 1200px (1140px, scales up)
.container-2xl — fixed from 1400px (1320px)
Order Utilities
Reorder columns visually without changing HTML source order. Responsive variants available at all breakpoints.
.order-3
.order-1
.order-2
.order-last
.order-first
Fibonacci 4-Column (1:2:3:5)
Ratio 1:2:3:5 (total 11 parts). Use .row-fib-4 with .col-fib-1, .col-fib-2, .col-fib-3, .col-fib-5.
Fibonacci 3-Column (3:5:8)
Ratio 3:5:8 (total 16 parts). Use .row-fib-3-alt with .col-fib-3, .col-fib-5, .col-fib-8.
CSS Grid: 4-Column Fibonacci
CSS Grid: 3:5:8 Fibonacci
Fibonacci Gap Utilities
Gap utilities using Fibonacci values. Works with CSS Grid and flex containers using the gap property.
.gap-fib-3 (3px)
.gap-fib-8 (8px)
.gap-fib-21 (21px)
Grid Mode Toggle
Toggle between standard 12-column flexbox and Fibonacci CSS Grid proportions. Uses data-layout-mode attribute with a data-grid-toggle button. The Fibonacci mode auto-detects column count and applies golden ratio (2 cols), 2:3:5 (3 cols), or 1:2:3:5 (4 cols) proportions.
3-column row:
2-column row (becomes golden ratio):
4-column row (becomes 1:2:3:5):
Offset Utilities
Complete offset utilities from 0-11 at all breakpoints. Use .offset-0 to reset an offset at a specific breakpoint.
Golden Ratio Grid
This framework uses the Fibonacci sequence and Golden Ratio (phi = 1.618) as its proportional foundation. Spacing, typography, component dimensions, and grid layouts all derive from these mathematical relationships.
Golden Split (38.2% / 61.8%)
38.2% (1/phi)
61.8% (1 - 1/phi)
Fibonacci 3-Column (2:3:5)
CSS Grid Golden Layout
Fibonacci Spacing Scale
1px
2px
3px
5px
8px
13px
21px
34px
55px
89px
144px
Golden Ratio Type Scale
xs — base / phi
sm — base / sqrt(phi)
base — 16px
lg — base x sqrt(phi)
xl — base x phi
2xl — base x phi^2
Forms
Input Fields
Form Controls
Form Validation States
Cards
Elevated Card
This is an elevated card with shadow. It's the default card style.
Outlined Card
This is an outlined card with border and no shadow.
Filled Card
This is a filled card with background color and no border.
<div class="card">
<div class="card-header">
<h3>Card Title</h3>
</div>
<div class="card-body">
<p>Card content goes here.</p>
</div>
<div class="card-footer">
<button class="btn btn-primary btn-sm">Action</button>
</div>
</div>
<!-- Outlined variant -->
<div class="card card-outlined">...</div>
<!-- Filled variant -->
<div class="card card-filled">...</div>
.card {
background-color: var(--card-bg);
border-radius: var(--card-border-radius);
box-shadow: var(--shadow-md);
overflow: hidden;
}
.card-outlined {
box-shadow: none;
border: 1px solid var(--border-color);
}
.card-filled {
box-shadow: none;
background-color: var(--bg-secondary);
}
Interactive Components
Tooltips
Hover over the buttons to see tooltips:
Dropdown
Modal
<!-- Trigger button -->
<button class="btn btn-primary" data-modal="#my-modal">Open Modal</button>
<!-- Modal structure -->
<div class="modal" id="my-modal">
<div class="modal-backdrop"></div>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">Title</h3>
<button class="modal-close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">Content</div>
<div class="modal-footer">
<button class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
// Open modal programmatically
const modal = Modal.open('#my-modal');
// Close modal
Modal.close('#my-modal');
// Listen for events
document.querySelector('#my-modal')
.addEventListener('modal:open', (e) => {
console.log('Modal opened');
});
Collapsible / Accordion
<div class="accordion">
<div class="accordion-item">
<button class="accordion-header">
<span>Item Title</span>
<span class="accordion-icon"></span>
</button>
<div class="accordion-body">
<div class="accordion-content">
Item content goes here
</div>
</div>
</div>
</div>
// Accordion auto-initializes on page load
// Click accordion headers to toggle
// Programmatic control:
const accordion = document.querySelector('.accordion');
const item = accordion.querySelector('.accordion-item');
// Open item
item.classList.add('is-open');
// Close item
item.classList.remove('is-open');
Collections
Collection List
-
JDJohn DoeSoftware Engineer
-
JSJane SmithDesigner
-
MJMike JohnsonProduct Manager
Collection with Actions
-
Item with actionClick to view details
-
Another itemWith action button
Tables
Bordered Table
| Name | Role | |
|---|---|---|
| John Doe | john@example.com | Admin |
| Jane Smith | jane@example.com | User |
| Mike Johnson | mike@example.com | User |
Striped Table
| Product | Price | Stock |
|---|---|---|
| Product A | $29.99 | 50 |
| Product B | $39.99 | 30 |
| Product C | $49.99 | 20 |
Hover Table
| ID | Status | Date |
|---|---|---|
| #001 | Active | 2024-01-15 |
| #002 | Pending | 2024-01-16 |
| #003 | Failed | 2024-01-17 |
Badges
Badge Variants
Badge Sizes
Pill Badge
Alerts
Alert Variants
<div class="alert alert-success">
<strong>Success!</strong> Your action was completed.
</div>
<!-- Variants: alert-primary, alert-success, alert-warning, alert-error, alert-info -->
<!-- Dismissible alert -->
<div class="alert alert-warning alert-dismissible">
<strong>Warning!</strong> Please review.
<button type="button" class="alert-close" aria-label="Close"></button>
</div>
.alert {
padding: var(--alert-padding-y) var(--alert-padding-x);
border-radius: var(--alert-border-radius);
border-left: 4px solid;
}
.alert-success {
background-color: var(--color-success-alpha-10);
border-color: var(--color-success);
color: var(--color-success-dark);
}
Dismissible Alerts
Chips & Tags
Chip Variants
Chip Sizes & Outline
Outline Primary Outline Success Outline Error
Dismissible Chips
Avatars
Avatar Sizes
Avatar with Status
Avatar Group
Skeleton Loaders
Basic Skeletons
Skeleton Card
Tabs
Basic Tabs
Content for Tab 1. This is the first tab panel.
Content for Tab 2. This is the second tab panel.
Content for Tab 3. This is the third tab panel.
Boxed Tabs
Overview content goes here.
Details content goes here.
Settings content goes here.
Pills Tabs
Home tab content. Pills style gives a more button-like appearance.
Profile tab content.
Messages tab content.
Settings tab content.
Toast Notifications
Toast Types
Toast Options
Preloader & Progress Bars
Spinners
Progress Bars
Colored Progress Bars
Striped & Animated Progress
Striped:
Animated Striped:
Indeterminate:
Progress Sizes
Extra small (.progress-xs):
Small (.progress-sm):
Large (.progress-lg):
Extra large (.progress-xl):
Grow Spinner & Colors
Growing spinner:
Colored spinners: