Cascader
Material Design 3 multi-level dropdown selection with horizontal panels
Cascader
Cascader is a multi-level dropdown component that displays options in horizontal adjacent panels. Each selection reveals the next level of options, making it ideal for hierarchical data like location (Country → State → City), categories, or organizational structures. Uses the native HTML Popover API for dropdown behavior.
Basic Usage
Basic Cascader
html
<div class="cascader">
<button class="cascader-trigger" popovertarget="cascader-1">
<span class="cascader-placeholder">Select location</span>
<svg class="cascader-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<div class="cascader-dropdown" id="cascader-1" popover="auto">
<div class="cascader-panels">
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option cascader-option-active">
<span class="cascader-option-label">United States</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
<button class="cascader-option">
<span class="cascader-option-label">Canada</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
<button class="cascader-option">
<span class="cascader-option-label">Mexico</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option">
<span class="cascader-option-label">California</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
<button class="cascader-option">
<span class="cascader-option-label">Texas</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
<button class="cascader-option">
<span class="cascader-option-label">New York</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
</div>
</div>
</div>With Selection
Display the selected path in the trigger:
Cascader with Selection
html
<div class="cascader">
<button class="cascader-trigger" popovertarget="cascader-selected">
<span class="cascader-value">
<span class="cascader-path">
United States
<span class="cascader-path-separator">/</span>
California
<span class="cascader-path-separator">/</span>
Los Angeles
</span>
</span>
<svg class="cascader-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<button class="cascader-clear" aria-label="Clear selection">
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
<div class="cascader-dropdown" id="cascader-selected" popover="auto">
<div class="cascader-panels">
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option cascader-option-selected">
<span class="cascader-option-label">United States</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
<button class="cascader-option">
<span class="cascader-option-label">Canada</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option cascader-option-selected">
<span class="cascader-option-label">California</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
<button class="cascader-option">
<span class="cascader-option-label">Texas</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option cascader-option-selected">
<span class="cascader-option-label">Los Angeles</span>
</button>
<button class="cascader-option">
<span class="cascader-option-label">San Francisco</span>
</button>
<button class="cascader-option">
<span class="cascader-option-label">San Diego</span>
</button>
</div>
</div>
</div>
</div>
</div>With Panel Headers
Add headers to identify each level:
Cascader with Headers
Category
Subcategory
html
<div class="cascader">
<button class="cascader-trigger" popovertarget="cascader-headers">
<span class="cascader-placeholder">Select category</span>
<svg class="cascader-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<div class="cascader-dropdown" id="cascader-headers" popover="auto">
<div class="cascader-panels">
<div class="cascader-panel">
<div class="cascader-panel-header">Category</div>
<div class="cascader-options">
<button class="cascader-option cascader-option-active">
<span class="cascader-option-label">Electronics</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
<button class="cascader-option">
<span class="cascader-option-label">Clothing</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
<div class="cascader-panel">
<div class="cascader-panel-header">Subcategory</div>
<div class="cascader-options">
<button class="cascader-option">
<span class="cascader-option-label">Smartphones</span>
</button>
<button class="cascader-option">
<span class="cascader-option-label">Laptops</span>
</button>
<button class="cascader-option">
<span class="cascader-option-label">Tablets</span>
</button>
</div>
</div>
</div>
</div>
</div>Variants
Outlined (Default)
Outlined Cascader
html
<div class="cascader cascader-outlined">
<button class="cascader-trigger" popovertarget="cascader-outlined">
<span class="cascader-placeholder">Select option</span>
<svg class="cascader-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<div class="cascader-dropdown" id="cascader-outlined" popover="auto">
<div class="cascader-panels">
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option">
<span class="cascader-option-label">Option 1</span>
</button>
</div>
</div>
</div>
</div>
</div>Filled
Filled Cascader
html
<div class="cascader cascader-filled">
<button class="cascader-trigger" popovertarget="cascader-filled">
<span class="cascader-placeholder">Select option</span>
<svg class="cascader-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<div class="cascader-dropdown" id="cascader-filled" popover="auto">
<div class="cascader-panels">
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option">
<span class="cascader-option-label">Option 1</span>
</button>
</div>
</div>
</div>
</div>
</div>Sizes
Small
Small Cascader
html
<div class="cascader cascader-sm">
<button class="cascader-trigger" popovertarget="cascader-sm">
<span class="cascader-placeholder">Select</span>
<svg class="cascader-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<div class="cascader-dropdown" id="cascader-sm" popover="auto">
<div class="cascader-panels">
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option">
<span class="cascader-option-label">Small Option</span>
</button>
</div>
</div>
</div>
</div>
</div>Large
Large Cascader
html
<div class="cascader cascader-lg">
<button class="cascader-trigger" popovertarget="cascader-lg">
<span class="cascader-placeholder">Select option</span>
<svg class="cascader-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<div class="cascader-dropdown" id="cascader-lg" popover="auto">
<div class="cascader-panels">
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option">
<span class="cascader-option-label">Large Option</span>
</button>
</div>
</div>
</div>
</div>
</div>With Search
Cascader with Search
html
<div class="cascader">
<button class="cascader-trigger" popovertarget="cascader-search">
<span class="cascader-placeholder">Search and select</span>
<svg class="cascader-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<div class="cascader-dropdown" id="cascader-search" popover="auto">
<div class="cascader-search">
<input type="text" name="cascader-search" class="cascader-search-input" placeholder="Search..." aria-label="Search locations" />
</div>
<div class="cascader-panels">
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option">
<span class="cascader-option-label">United States</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
<button class="cascader-option">
<span class="cascader-option-label">Canada</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
</div>
</div>
</div>States
Error State
Error State
Location
Please select a location
html
<div class="form-group">
<span class="form-label form-label-required">Location</span>
<div class="cascader cascader-error">
<button class="cascader-trigger" popovertarget="cascader-error">
<span class="cascader-placeholder">Select location</span>
<svg class="cascader-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<div class="cascader-dropdown" id="cascader-error" popover="auto">
<div class="cascader-panels">
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option">
<span class="cascader-option-label">Option 1</span>
</button>
</div>
</div>
</div>
</div>
</div>
<span class="helper-text helper-text-error">Please select a location</span>
</div>Disabled
Disabled State
html
<div class="cascader cascader-disabled">
<button class="cascader-trigger" disabled>
<span class="cascader-placeholder">Select option</span>
<svg class="cascader-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
</div>Loading
Loading State
html
<div class="cascader cascader-loading">
<button class="cascader-trigger" disabled>
<span class="cascader-placeholder">Loading options...</span>
<span class="cascader-spinner"></span>
</button>
</div>Leaf-Only Selection
Options without arrows are leaf nodes (final selection):
Leaf Selection
html
<div class="cascader">
<button class="cascader-trigger" popovertarget="cascader-leaf">
<span class="cascader-placeholder">Select city</span>
<svg class="cascader-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<div class="cascader-dropdown" id="cascader-leaf" popover="auto">
<div class="cascader-panels">
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option cascader-option-active">
<span class="cascader-option-label">California</span>
<svg class="cascader-option-arrow" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</button>
</div>
</div>
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option">
<span class="cascader-option-label">Los Angeles</span>
</button>
<button class="cascader-option">
<span class="cascader-option-label">San Francisco</span>
</button>
<button class="cascader-option">
<span class="cascader-option-label">San Diego</span>
</button>
<button class="cascader-option">
<span class="cascader-option-label">San Jose</span>
</button>
</div>
</div>
</div>
</div>
</div>API Reference
Class Names
| Class | Description |
|---|---|
.cascader |
Base container (required) |
.cascader-trigger |
Trigger button (use with popovertarget) |
.cascader-value |
Selected value display |
.cascader-placeholder |
Placeholder text when empty |
.cascader-path |
Path breadcrumb display |
.cascader-path-separator |
Separator between path items |
.cascader-arrow |
Dropdown arrow icon |
.cascader-clear |
Clear selection button |
.cascader-dropdown |
Dropdown container (use with popover attribute) |
.cascader-search |
Search input container |
.cascader-search-input |
Search input field |
.cascader-panels |
Horizontal panels container |
.cascader-panel |
Individual level panel |
.cascader-panel-header |
Panel header/title |
.cascader-options |
Options list in panel |
.cascader-option |
Individual option |
.cascader-option-label |
Option label text |
.cascader-option-arrow |
Arrow indicating children |
.cascader-option-active |
Currently highlighted option |
.cascader-option-selected |
Selected option |
.cascader-option-disabled |
Disabled option |
.cascader-empty |
Empty state message |
.cascader-outlined |
Outlined variant |
.cascader-filled |
Filled variant |
.cascader-sm |
Small size |
.cascader-lg |
Large size |
.cascader-error |
Error state |
.cascader-disabled |
Disabled state |
.cascader-loading |
Loading state |
.cascader-spinner |
Loading spinner |
HTML Structure with Popover API
<div class="cascader">
<button class="cascader-trigger" popovertarget="dropdown-id">
<span class="cascader-placeholder">Select option</span>
<svg class="cascader-arrow">...</svg>
</button>
<div class="cascader-dropdown" id="dropdown-id" popover="auto">
<div class="cascader-panels">
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option">
<span class="cascader-option-label">Option 1</span>
<svg class="cascader-option-arrow">...</svg>
</button>
</div>
</div>
<div class="cascader-panel">
<div class="cascader-options">
<button class="cascader-option">
<span class="cascader-option-label">Sub-option</span>
</button>
</div>
</div>
</div>
</div>
</div>
Color Variants
Color Variants
html
<div class="cascader cascader-primary">
<button class="cascader-trigger">Primary Cascader</button>
</div>
<div class="cascader cascader-secondary">
<button class="cascader-trigger">Secondary Cascader</button>
</div>
<div class="cascader cascader-tertiary">
<button class="cascader-trigger">Tertiary Cascader</button>
</div>
<div class="cascader cascader-info">
<button class="cascader-trigger">Info Cascader</button>
</div>
<div class="cascader cascader-success">
<button class="cascader-trigger">Success Cascader</button>
</div>
<div class="cascader cascader-warning">
<button class="cascader-trigger">Warning Cascader</button>
</div>
<div class="cascader cascader-error">
<button class="cascader-trigger">Error Cascader</button>
</div>Ghost Variant
Ghost Cascader
html
<div class="cascader cascader-ghost">
<button class="cascader-trigger">Ghost Cascader (no border)</button>
</div>Related Components
- Select - Single dropdown selection
- Tree Select - Hierarchical tree selection
- Multi-Select - Multiple selection dropdown
- Autocomplete - Search with suggestions