Composed multi-element patterns.
Larger composed patterns built from Graffiti primitives. Navigation, dialogs, forms, and app shells.
Native HTML disclosure element with smooth animations using `<details>` and `<summary>`.
When to use: Expandable sections for FAQ and settings content.
Classes: details, .bordered, .right, .minimal
@starting-style and allow-discrete› arrow indicator that rotates on openUse the name attribute to group accordions:
Only one in the group can be open at a time.
Simple breadcrumb navigation with customizable separators.
When to use: Hierarchy path navigation inside app and docs views.
Classes: .breadcrumbs
Default separator is /. Change with --separator:
Other separator ideas: ›, →, », |, ·
Mark the current page with aria-current="page" on the <li>:
This removes the link styling and shows it as plain text.
::before pseudo-elements--fg-5) and brighten on hover (--fg-7)aria-label="Breadcrumb" on the <nav>aria-current="page" on the current page <li><nav>, <ul>, <li> structureCard footer style pagination with previous/next controls and current page state.
When to use: Paginated result navigation with previous and next controls.
Classes: .pagination
.pagination handles layout only (flex, gap, border-top).button.ghost stylesul get fixed 2rem square sizingaria-label="Pagination" on the <nav>aria-current="page" on the active page linkaria-disabled="true" for disabled controlsNative dropdown menu using HTML popover API and CSS anchor positioning.
When to use: Action menus using popover and anchor positioning.
Classes: .dropdown, .dropdown-menu, .dropdown-header, .end
No JavaScript required for open/close.
popovertarget on the button points to the menu's idpopover attribute enables native popover behavior.dropdown-menu provides styling and positioningVertical navigation for app sidebars with collapsible sections.
When to use: Sectioned app navigation with collapsible groups.
Classes: .sidebar-nav, .sidebar-nav.compact, .sub
Uses native <details>/<summary> for expand/collapse.
Icons are automatically sized to 20px (customizable via --sidebar-nav-icon-size).
--sidebar-nav-icon-size - Icon size (default: 20px)--sidebar-nav-indent - Indentation for nested items (default: 1.5rem)Use .compact when a sidebar needs denser rows:
Compact mode keeps focus and hover behavior, while reducing row padding and icon size.
Combine with .layout-sidebar.fill for the canonical shell:
Notes:
.layout-sidebar.fill is app-shell-oriented by default (--layout-gap: 0, height: 100dvh).app-shell.app-shell, overflow is not forced there, avoiding double-scrollUse this when navigation should remain visible while main content scrolls.
iOS and Android-friendly CSS patterns for PWAs and native-like web apps.
When to use: App shell, bottom nav, bottom sheet, safe areas.
Classes: .app-shell, .bottom-nav, .bottom-sheet, .safe-top, .safe-bottom, .safe-x, .hide-scrollbar, .momentum-scroll
Graffiti provides CSS variables for iOS safe areas (notch, home indicator, status bar):
These use env() which returns the actual safe area on iOS/Android, or 0px on desktop.
Grid-based container that avoids the iOS URL bar 100vh bug:
Features:
100dvh (dynamic viewport height) to avoid iOS URL bar issuesmin-block-size: 0 on shell and direct regions)Behavior:
.layout-sidebar.fill now acts as an app-shell frame by default (--layout-gap: 0, height: 100dvh).app-shell first/second children auto-scroll on larger layouts.app-shell, overflow is not forced on that child; its main handles scrollingFixed tab bar for mobile apps:
Features:
--safe-bottom for home indicatoraria-current="page" or .active classDrawer that slides up from bottom:
Features:
--safe-bottomFor interactive open/close, wrap in <dialog> or use with popover API.
For safe areas to work, include viewport-fit=cover:
Without this, safe area insets may not be reported correctly on iOS.
Full-width site header with navigation.
When to use: Page-level site/app top navigation bar.
Classes: .header, .border, .sticky
<ul> styled as horizontal flex listSite footer with navigation columns, copyright, and legal links.
When to use: Site footer with grouped navigation and legal links.
Classes: .footer
Uses container queries for responsive behavior.
.footer - Container with container-type: inline-size, removes link underlines (shows on hover).grid.auto - Responsive auto-fit grid for nav columns.footer sets container-type: inline-size so child layouts respond to footer width, not viewport.grid.auto uses auto-fit with --grid-min variable for responsive columns.layout-sidebar and .split automatically stack in narrow containers--grid-min - Minimum column width for .grid.auto (default: 150px, recommended: 120px for footer)The footer uses container queries, not media queries:
.layout-sidebar stacks vertically.grid.auto columns wrap based on --grid-min.split stacks when container is < 500px.box - Adds padding and border.stack - Vertical spacing between children.cluster - Horizontal wrapping layout.split - Space-between horizontal layout.layout-sidebar - Two-column layout (stacks in narrow containers).grid.auto - Auto-fit responsive gridHorizontal swipe-to-reveal component using CSS scroll-snap.
When to use: Swipe-to-reveal row actions for touch interactions.
Classes: .swipe, .stop
Reveal action buttons by swiping left or right.
User account dropdown combining avatar trigger with dropdown menu.
When to use: Avatar trigger plus account actions dropdown.
Classes: .avatar, .dropdown
Works with both image and initials avatars.
.dropdown.end - Aligns menu to right edge of avatar.avatar - Circular avatar styling on the button.dropdown-menu - Menu styling.dropdown-header - User name display in menuA confirmation dialog pattern using native `<dialog>` with title, message, and action buttons.
When to use: Destructive or important confirmations using native dialog.
Classes: dialog, .close
.close - Circular close button (positioned top-right automatically).stack - Vertical layout for dialog content.cluster - Horizontal layout for action buttons.h4 - Heading style without using an actual heading element.primary - Primary action buttoncommandfor/command) - no JavaScript for open/close.stack provides consistent vertical spacing between title, message, and buttons.cluster with justify-content: flex-end aligns buttons to the rightActivity feeds, step indicators, and progress tracking with status variants and glow effects.
When to use: Progress steps and chronological activity flows.
Classes: .timeline, .horizontal, .active, .completed, .success, .warning, .error, .info
| Class | Use | Visual |
|---|---|---|
.active | Current step in progress | Bold filled marker with ring |
.completed | Finished step | Green filled marker with glow |
.success | Success status | Green-tinted background with glow |
.warning | Warning status | Yellow-tinted background with glow |
.error | Error status | Red-tinted background with glow |
.info | Info status | Blue-tinted background with glow |
The .marker element can contain:
<span class="marker">1</span><span class="marker"><svg>...</svg></span><span class="marker">✓</span>SVG icons are automatically sized to 1.125rem (18px).
0 0 0 3px spread shadow for colored halo effectA complete login form using Graffiti's base form styles.
When to use: Email/password auth form with native control styling.
Classes: form, .stack
No custom CSS needed.
.stack - Vertical layout with consistent spacing.split - Flexbox with space-between (checkbox left, link right).primary - Primary action button style.error, .success, .warning classes on inputs for validation states<small class="error">Message</small> after inputs for validation messagesAll form inputs are styled automatically. No classes needed on inputs.
When to use: Field rows and form actions.
Classes: .row, .form-option-row, .form-actions
Use .form-option-row on checkbox/radio labels to align controls and text with consistent spacing.
Use .row as a field wrapper to group label + control + help text.
Notes:
.row keeps its spacing utility behavior (margin-block)..row becomes a compact field-group wrapper.Use .form-actions for submit/cancel rows.
Behavior: