Offcanvas
Create hidden navigation panels, shopping carts, and contextual sidebars that slide in from any edge of the viewport with Chassis CSS's offcanvas component.
Overview
Offcanvas creates slide-out panels that appear from any edge of the viewport, perfect for navigation menus, shopping carts, filters, or contextual information that needs to be accessible but not always visible. These panels maintain focus and accessibility while providing smooth animations and flexible positioning.
Built with responsive design principles and keyboard navigation support, offcanvas panels offer flexible sizing options, backdrop controls, and seamless integration with other Chassis CSS components. Each offcanvas consists of:
- Offcanvas container controls visibility and positioning
- Offcanvas header provides structure with title and close button
- Offcanvas body contains the main panel content
Offcanvas
<div class="offcanvas offcanvas-start show" tabindex="-1" id="offcanvas" aria-labelledby="offcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasLabel">Offcanvas</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
Content for the offcanvas goes here. You can place just about any Chassis CSS component or custom elements here.
</div>
</div> Chassis CSS respects user accessibility preferences by automatically disabling animations when the prefers-reduced-motion media query is detected. See the reduced motion guidelines in our accessibility documentation for implementation details.
Implementation
Before implementing offcanvas panels, note these important considerations:
- Offcanvas shares JavaScript functionality with modals but operates as a separate plugin
- When shown, offcanvas includes a default backdrop that can be clicked to hide the panel
- Only one offcanvas can be displayed at a time by default
- Body scrolling is disabled when an offcanvas is visible unless configured otherwise
- Use
marginortranslateon wrapper elements instead of the.offcanvaselement directly due to CSS animation handling
Examples
Explore these practical examples to see Chassis CSS offcanvas in action across different use cases and configurations. Each example demonstrates specific features to help you implement offcanvas panels effectively in your projects.
Live demo
Use the buttons below to show and hide an offcanvas element via JavaScript that toggles the .show class. You can trigger offcanvas with both links using href or buttons using data-cx-target.
Offcanvas
<a class="button primary" data-cx-toggle="offcanvas" href="#offcanvasExample" role="button" aria-controls="offcanvasExample">
Link with href
</a>
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasExample" aria-controls="offcanvasExample">
Button with data-cx-target
</button>
<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasExample" aria-labelledby="offcanvasExampleLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasExampleLabel">Offcanvas</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<div>
Some text as placeholder. In real life you can have the elements you have chosen. Like, text, images, lists, etc.
</div>
<div class="dropdown mt-medium">
<button class="button secondary dropdown-toggle" type="button" data-cx-toggle="dropdown">
Dropdown button
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</div>
</div>
</div> Body scrolling options
Control how the page body behaves when an offcanvas is visible. By default, body scrolling is disabled to focus attention on the offcanvas content.
Enable body scrolling
Use the data-cx-scroll="true" attribute to allow the body to scroll while the offcanvas is open. This is useful for reference panels or filters where users might need to scroll the main content.
Offcanvas with body scrolling
Try scrolling the rest of the page to see this option in action.
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasScrolling" aria-controls="offcanvasScrolling">Enable body scrolling</button>
<div class="offcanvas offcanvas-start" data-cx-scroll="true" data-cx-backdrop="false" tabindex="-1" id="offcanvasScrolling" aria-labelledby="offcanvasScrollingLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasScrollingLabel">Offcanvas with body scrolling</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<p>Try scrolling the rest of the page to see this option in action.</p>
</div>
</div> Body scrolling with backdrop
You can also enable body scrolling while maintaining a visible backdrop for better visual separation.
Backdrop with scrolling
Try scrolling the rest of the page to see this option in action.
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasWithBothOptions" aria-controls="offcanvasWithBothOptions">Enable both scrolling & backdrop</button>
<div class="offcanvas offcanvas-start" data-cx-scroll="true" tabindex="-1" id="offcanvasWithBothOptions" aria-labelledby="offcanvasWithBothOptionsLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasWithBothOptionsLabel">Backdrop with scrolling</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<p>Try scrolling the rest of the page to see this option in action.</p>
</div>
</div> Static backdrop
When backdrop is set to static, the offcanvas will not close when clicking outside of it, ensuring users must explicitly dismiss the panel.
Offcanvas
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#staticBackdrop" aria-controls="staticBackdrop">
Toggle static offcanvas
</button>
<div class="offcanvas offcanvas-start" data-cx-backdrop="static" tabindex="-1" id="staticBackdrop" aria-labelledby="staticBackdropLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="staticBackdropLabel">Offcanvas</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<div>
I will not close if you click outside of me.
</div>
</div>
</div> Customization options
Tailor offcanvas panels to your specific design and functional requirements with these customization options. Chassis CSS provides comprehensive control over positioning, responsive behavior, and visual presentation.
Placement options
Offcanvas panels can slide in from any edge of the viewport. Choose the placement that best fits your layout and user experience needs.
| Placement | Class | Description |
|---|---|---|
| Left | .offcanvas-start | Slides in from the left edge (default LTR) |
| Right | .offcanvas-end | Slides in from the right edge |
| Top | .offcanvas-top | Slides down from the top edge |
| Bottom | .offcanvas-bottom | Slides up from the bottom edge |
Top placement
Offcanvas top
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasTop" aria-controls="offcanvasTop">Toggle top offcanvas</button>
<div class="offcanvas offcanvas-top" tabindex="-1" id="offcanvasTop" aria-labelledby="offcanvasTopLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasTopLabel">Offcanvas top</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
This panel slides down from the top of the viewport.
</div>
</div> Right placement
Offcanvas right
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasRight" aria-controls="offcanvasRight">Toggle right offcanvas</button>
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasRight" aria-labelledby="offcanvasRightLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasRightLabel">Offcanvas right</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
This panel slides in from the right edge.
</div>
</div> Bottom placement
Offcanvas bottom
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasBottom" aria-controls="offcanvasBottom">Toggle bottom offcanvas</button>
<div class="offcanvas offcanvas-bottom" tabindex="-1" id="offcanvasBottom" aria-labelledby="offcanvasBottomLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasBottomLabel">Offcanvas bottom</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body small">
This panel slides up from the bottom of the viewport.
</div>
</div> Responsive behavior
Responsive offcanvas classes hide content outside the viewport from a specified breakpoint and down. Above that breakpoint, the contents within will behave as usual.
| Class | Behavior |
|---|---|
.offcanvas | Always behaves as offcanvas |
.small:offcanvas | Offcanvas below small breakpoint |
.medium:offcanvas | Offcanvas below medium breakpoint |
.large:offcanvas | Offcanvas below large breakpoint |
.xlarge:offcanvas | Offcanvas below xlarge breakpoint |
.2xlarge:offcanvas | Offcanvas below 2xlarge breakpoint |
Responsive offcanvas
This is content within an .large:offcanvas.
<button class="button primary large:d-none" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasResponsive" aria-controls="offcanvasResponsive">Toggle offcanvas</button>
<div class="alert alert-info d-none large:d-block">Resize your browser to show the responsive offcanvas toggle.</div>
<div class="large:offcanvas offcanvas-end" tabindex="-1" id="offcanvasResponsive" aria-labelledby="offcanvasResponsiveLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasResponsiveLabel">Responsive offcanvas</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" data-cx-target="#offcanvasResponsive" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<p class="mb-0">This is content within an <code>.large:offcanvas</code>.</p>
</div>
</div> Accessibility
Since the offcanvas panel is conceptually a modal dialog, be sure to add aria-labelledby="..."—referencing the offcanvas title—to .offcanvas. Note that you don't need to add role="dialog" since we already add it via JavaScript.
CSS
Custom properties
These CSS variables control the component's appearance and can be modified dynamically on the page. Components use cascading variables, allowing seamless variations in size, color, and style without redundant style declarations through component inheritance and the context class system.
--#{$prefix}offcanvas-zindex: #{$zindex-offcanvas};
--#{$prefix}offcanvas-width: #{$offcanvas-horizontal-width};
--#{$prefix}offcanvas-height: #{$offcanvas-vertical-height};
--#{$prefix}offcanvas-padding-x: #{$offcanvas-padding-x};
--#{$prefix}offcanvas-padding-y: #{$offcanvas-padding-y};
--#{$prefix}offcanvas-fg-color: #{$offcanvas-fg-color};
--#{$prefix}offcanvas-bg-color: #{$offcanvas-bg-color};
--#{$prefix}offcanvas-border-width: #{$offcanvas-border-width};
--#{$prefix}offcanvas-border-color: #{$offcanvas-border-color};
--#{$prefix}offcanvas-box-shadow: #{$offcanvas-box-shadow};
--#{$prefix}offcanvas-transition: #{transform $offcanvas-transition-duration ease-in-out};
--#{$prefix}offcanvas-title-line-height: #{$offcanvas-title-line-height};
Sass variables
These Sass variables are also exposed as CSS custom properties using the --cx-
prefix. A Sass variable $variable-name becomes available as --cx-variable-name in CSS, allowing for styles to be modified dynamically on the
page. See the
context components
page for more details.
$offcanvas-padding-y: $modal-window-padding-y;
$offcanvas-padding-x: $modal-window-padding-x;
$offcanvas-horizontal-width: 25rem; //400px;
$offcanvas-vertical-height: 30vh;
$offcanvas-transition-duration: .3s;
$offcanvas-border-color: $modal-window-border-color;
$offcanvas-border-width: $modal-window-border-width;
$offcanvas-title-line-height: map-get($modal-title-font, "line-height");
$offcanvas-bg-color: var(--#{$prefix}bg-main);
$offcanvas-fg-color: var(--#{$prefix}fg-main);
$offcanvas-box-shadow: $modal-window-shadow-xsmall;
$offcanvas-backdrop-color: $modal-backdrop-color;
$offcanvas-backdrop-opacity: $modal-backdrop-opacity;
JavaScript
Chassis CSS provides a comprehensive JavaScript API for controlling offcanvas panels programmatically. You can create, show, hide, and configure offcanvas behavior dynamically for complex interactions.
Data attributes
The simplest way to activate an offcanvas is using data attributes:
<!-- Button to trigger the offcanvas -->
<button data-cx-toggle="offcanvas" data-cx-target="#myOffcanvas">Open panel</button>
<!-- Close button within the offcanvas -->
<button data-cx-dismiss="offcanvas">Close</button>
Initialization
For more control, initialize offcanvas with JavaScript:
// Basic initialization
const myOffcanvas = new chassis.Offcanvas(document.getElementById('myOffcanvas'))
// With a CSS selector
const anotherOffcanvas = new chassis.Offcanvas('#anotherOffcanvas')
// With options
const configuredOffcanvas = new chassis.Offcanvas('#configuredOffcanvas', {
backdrop: 'static',
keyboard: false,
scroll: true
})
Configuration options
Chassis components offer flexible configuration through both data attributes and JavaScript. To use data attributes, prefix any option with data-cx- followed by the option name in kebab-case format (using hyphens instead of camelCase). For example, write data-cx-custom-class="my-class" rather than data-cx-customClass="my-class".
For more complex configurations, Chassis provides the data-cx-config attribute which accepts a JSON string of multiple settings. This approach simplifies markup when configuring several options at once. If the same option appears in both data-cx-config and as a separate data attribute (like data-cx-title), the individual attribute takes precedence. You can also use JSON values in individual attributes, such as data-cx-delay='{"show":100,"hide":200}' for more granular control.
When initializing components, Chassis merges configurations from multiple sources in this priority order: default settings, data-cx-config values, individual data-cx-* attributes, and finally any JavaScript object options. Values defined later in this sequence override earlier ones.
| Option | Type | Default | Description |
|---|---|---|---|
backdrop | boolean, 'static' | true | Apply a backdrop on body while offcanvas is open. Set to 'static' for a backdrop that doesn't close on click. |
keyboard | boolean | true | Closes the offcanvas when escape key is pressed. |
scroll | boolean | false | Allow body scrolling while offcanvas is open. |
Methods
All Chassis CSS component methods are asynchronous and initiate CSS transitions. Methods return immediately when the transition begins, not when it completes. Calling methods on components that are already transitioning will be ignored to prevent conflicts. Learn more about Chassis JavaScript patterns.
| Method | Description |
|---|---|
show() | Shows an offcanvas element. Returns before animation completes. |
hide() | Hides an offcanvas element. Returns before animation completes. |
toggle() | Toggles an offcanvas element to shown or hidden. |
dispose() | Destroys an element's offcanvas functionality. |
getInstance() | Static method to get the offcanvas instance associated with an element. |
getOrCreateInstance() | Static method to get existing offcanvas instance or create a new one. |
Usage example:
// Initialize with options
const offcanvas = new chassis.Offcanvas('#myOffcanvas', {
keyboard: false
})
// Show the offcanvas programmatically
document.getElementById('showButton').addEventListener('click', () => {
offcanvas.show()
})
// Hide after a user action
document.getElementById('completeAction').addEventListener('click', () => {
// Perform action, then hide offcanvas
saveData().then(() => offcanvas.hide())
})
Events
Chassis CSS provides events to hook into offcanvas behavior:
| Event | Description |
|---|---|
show.cx.offcanvas | Fires immediately when the show method is called. |
shown.cx.offcanvas | Fires when an offcanvas element has been made visible (after animations). |
hide.cx.offcanvas | Fires immediately when the hide method is called. |
hidden.cx.offcanvas | Fires when an offcanvas element has been hidden (after animations). |
hidePrevented.cx.offcanvas | Fires when offcanvas hiding is prevented (static backdrop click or keyboard disabled with escape key). |
Event handling example:
const offcanvasElement = document.getElementById('navigationOffcanvas')
// Do something when offcanvas is about to show
offcanvasElement.addEventListener('show.cx.offcanvas', event => {
// Update navigation based on current state
updateNavigation()
})
// Do something when offcanvas is fully shown
offcanvasElement.addEventListener('shown.cx.offcanvas', () => {
// Focus the first navigation item
document.getElementById('firstNavItem').focus()
})
// Clean up when offcanvas is hidden
offcanvasElement.addEventListener('hidden.cx.offcanvas', () => {
// Reset any temporary states
resetTemporaryStates()
})
Examples
Offcanvas components
Below is an offcanvas example that is shown by default (via .show on .offcanvas). Offcanvas includes support for a header with a close button and an optional body class for some initial padding. We suggest that you include offcanvas headers with dismiss actions whenever possible, or provide an explicit dismiss action.
Offcanvas
<div class="offcanvas offcanvas-start show" tabindex="-1" id="offcanvas" aria-labelledby="offcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasLabel">Offcanvas</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
Content for the offcanvas goes here. You can place just about any Chassis CSS component or custom elements here.
</div>
</div> Live demo
Use the buttons below to show and hide an offcanvas element via JavaScript that toggles the .show class on an element with the .offcanvas class.
.offcanvashides content (default).offcanvas.showshows content
You can use a link with the href attribute, or a button with the data-cx-target attribute. In both cases, the data-cx-toggle="offcanvas" is required.
Offcanvas
<a class="button primary" data-cx-toggle="offcanvas" href="#offcanvasExample" role="button" aria-controls="offcanvasExample">
Link with href
</a>
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasExample" aria-controls="offcanvasExample">
Button with data-cx-target
</button>
<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasExample" aria-labelledby="offcanvasExampleLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasExampleLabel">Offcanvas</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<div>
Some text as placeholder. In real life you can have the elements you have chosen. Like, text, images, lists, etc.
</div>
<div class="dropdown mt-medium">
<button class="button secondary dropdown-toggle" type="button" data-cx-toggle="dropdown">
Dropdown button
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</div>
</div>
</div> Body scrolling
Scrolling the <body> element is disabled when an offcanvas and its backdrop are visible. Use the data-cx-scroll attribute to enable <body> scrolling.
Offcanvas with body scrolling
Try scrolling the rest of the page to see this option in action.
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasScrolling" aria-controls="offcanvasScrolling">Enable body scrolling</button>
<div class="offcanvas offcanvas-start" data-cx-scroll="true" data-cx-backdrop="false" tabindex="-1" id="offcanvasScrolling" aria-labelledby="offcanvasScrollingLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasScrollingLabel">Offcanvas with body scrolling</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<p>Try scrolling the rest of the page to see this option in action.</p>
</div>
</div> Body scrolling and backdrop
You can also enable <body> scrolling with a visible backdrop.
Backdrop with scrolling
Try scrolling the rest of the page to see this option in action.
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasWithBothOptions" aria-controls="offcanvasWithBothOptions">Enable both scrolling & backdrop</button>
<div class="offcanvas offcanvas-start" data-cx-scroll="true" tabindex="-1" id="offcanvasWithBothOptions" aria-labelledby="offcanvasWithBothOptionsLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasWithBothOptionsLabel">Backdrop with scrolling</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<p>Try scrolling the rest of the page to see this option in action.</p>
</div>
</div> Static backdrop
When backdrop is set to static, the offcanvas will not close when clicking outside of it.
Offcanvas
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#staticBackdrop" aria-controls="staticBackdrop">
Toggle static offcanvas
</button>
<div class="offcanvas offcanvas-start" data-cx-backdrop="static" tabindex="-1" id="staticBackdrop" aria-labelledby="staticBackdropLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="staticBackdropLabel">Offcanvas</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<div>
I will not close if you click outside of me.
</div>
</div>
</div> Responsive
Added in v5.2.0Responsive offcanvas classes hide content outside the viewport from a specified breakpoint and down. Above that breakpoint, the contents within will behave as usual. For example, .large:offcanvas hides content in an offcanvas below the lg breakpoint, but shows the content above the lg breakpoint. Responsive offcanvas classes are available for each breakpoint.
.offcanvas.small:offcanvas.medium:offcanvas.large:offcanvas.xlarge:offcanvas.2xlarge:offcanvas
To make a responsive offcanvas, replace the .offcanvas base class with a responsive variant and ensure your close button has an explicit data-cx-target.
Responsive offcanvas
This is content within an .large:offcanvas.
<button class="button primary large:d-none" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasResponsive" aria-controls="offcanvasResponsive">Toggle offcanvas</button>
<div class="alert alert-info d-none large:d-block">Resize your browser to show the responsive offcanvas toggle.</div>
<div class="large:offcanvas offcanvas-end" tabindex="-1" id="offcanvasResponsive" aria-labelledby="offcanvasResponsiveLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasResponsiveLabel">Responsive offcanvas</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" data-cx-target="#offcanvasResponsive" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<p class="mb-0">This is content within an <code>.large:offcanvas</code>.</p>
</div>
</div> Placement
There’s no default placement for offcanvas components, so you must add one of the modifier classes below.
.offcanvas-startplaces offcanvas on the left of the viewport (shown above).offcanvas-endplaces offcanvas on the right of the viewport.offcanvas-topplaces offcanvas on the top of the viewport.offcanvas-bottomplaces offcanvas on the bottom of the viewport
Try the top, right, and bottom examples out below.
Offcanvas top
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasTop" aria-controls="offcanvasTop">Toggle top offcanvas</button>
<div class="offcanvas offcanvas-top" tabindex="-1" id="offcanvasTop" aria-labelledby="offcanvasTopLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasTopLabel">Offcanvas top</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
...
</div>
</div> Offcanvas right
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasRight" aria-controls="offcanvasRight">Toggle right offcanvas</button>
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasRight" aria-labelledby="offcanvasRightLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasRightLabel">Offcanvas right</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
...
</div>
</div> Offcanvas bottom
<button class="button primary" type="button" data-cx-toggle="offcanvas" data-cx-target="#offcanvasBottom" aria-controls="offcanvasBottom">Toggle bottom offcanvas</button>
<div class="offcanvas offcanvas-bottom" tabindex="-1" id="offcanvasBottom" aria-labelledby="offcanvasBottomLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasBottomLabel">Offcanvas bottom</h5>
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body small">
...
</div>
</div> Accessibility
Since the offcanvas panel is conceptually a modal dialog, be sure to add aria-labelledby="..."—referencing the offcanvas title—to .offcanvas. Note that you don’t need to add role="dialog" since we already add it via JavaScript.
CSS
This component can be customized using CSS variables, allowing for styles to be modified dynamically on the page. These CSS variables are part of Chassis CSS's design token system, giving design teams control over component appearance. See the design tokens page for more details.
Custom properties
These CSS variables control the component's appearance and can be modified dynamically on the page. Components use cascading variables, allowing seamless variations in size, color, and style without redundant style declarations through component inheritance and the context class system.
--#{$prefix}offcanvas-zindex: #{$zindex-offcanvas};
--#{$prefix}offcanvas-width: #{$offcanvas-horizontal-width};
--#{$prefix}offcanvas-height: #{$offcanvas-vertical-height};
--#{$prefix}offcanvas-padding-x: #{$offcanvas-padding-x};
--#{$prefix}offcanvas-padding-y: #{$offcanvas-padding-y};
--#{$prefix}offcanvas-fg-color: #{$offcanvas-fg-color};
--#{$prefix}offcanvas-bg-color: #{$offcanvas-bg-color};
--#{$prefix}offcanvas-border-width: #{$offcanvas-border-width};
--#{$prefix}offcanvas-border-color: #{$offcanvas-border-color};
--#{$prefix}offcanvas-box-shadow: #{$offcanvas-box-shadow};
--#{$prefix}offcanvas-transition: #{transform $offcanvas-transition-duration ease-in-out};
--#{$prefix}offcanvas-title-line-height: #{$offcanvas-title-line-height};
Sass variables
These Sass variables are also exposed as CSS custom properties using the --cx-
prefix. A Sass variable $variable-name becomes available as --cx-variable-name in CSS, allowing for styles to be modified dynamically on the
page. See the
context components
page for more details.
$offcanvas-padding-y: $modal-window-padding-y;
$offcanvas-padding-x: $modal-window-padding-x;
$offcanvas-horizontal-width: 25rem; //400px;
$offcanvas-vertical-height: 30vh;
$offcanvas-transition-duration: .3s;
$offcanvas-border-color: $modal-window-border-color;
$offcanvas-border-width: $modal-window-border-width;
$offcanvas-title-line-height: map-get($modal-title-font, "line-height");
$offcanvas-bg-color: var(--#{$prefix}bg-main);
$offcanvas-fg-color: var(--#{$prefix}fg-main);
$offcanvas-box-shadow: $modal-window-shadow-xsmall;
$offcanvas-backdrop-color: $modal-backdrop-color;
$offcanvas-backdrop-opacity: $modal-backdrop-opacity;
Javascript
The offcanvas plugin utilizes a few classes and attributes to handle the heavy lifting:
.offcanvashides the content.offcanvas.showshows the content.offcanvas-starthides the offcanvas on the left.offcanvas-endhides the offcanvas on the right.offcanvas-tophides the offcanvas on the top.offcanvas-bottomhides the offcanvas on the bottom
Add a dismiss button with the data-cx-dismiss="offcanvas" attribute, which triggers the JavaScript functionality. Be sure to use the <button> element with it for proper behavior across all devices.
Data attributes
You can use data attributes to control offcanvas behavior without writing JavaScript. The following attributes are available:
Toggle
Add data-cx-toggle="offcanvas" and a data-cx-target or href to the element to automatically assign control of one offcanvas element. The data-cx-target attribute accepts a CSS selector to apply the offcanvas to. Be sure to add the class offcanvas to the offcanvas element. If you’d like it to default open, add the additional class show.
Dismiss
Enable dismissal with the data-cx-dismiss attribute on a button within the offcanvas:
<button type="button" class="close-button" data-cx-dismiss="offcanvas" aria-label="Dismiss"></button>
Or on a button outside the offcanvas using the additional data-cx-target attribute:
<button type="button" class="close-button" data-cx-dismiss="offcanvas" data-cx-target="#my-offcanvas" aria-label="Dismiss offcanvas"></button> closed.cx.offcanvas event to set focus to an appropriate
element.
While both ways to dismiss an offcanvas are supported, keep in mind that dismissing from outside an offcanvas does not match the ARIA Authoring Practices Guide dialog (modal) pattern. Do this at your own risk.
Initialization
Enable manually with:
const offcanvasElementList = document.querySelectorAll('.offcanvas')
const offcanvasList = [...offcanvasElementList].map(offcanvasEl => new chassis.Offcanvas(offcanvasEl))
Options
Chassis components offer flexible configuration through both data attributes and JavaScript. To use data attributes, prefix any option with data-cx- followed by the option name in kebab-case format (using hyphens instead of camelCase). For example, write data-cx-custom-class="my-class" rather than data-cx-customClass="my-class".
For more complex configurations, Chassis provides the data-cx-config attribute which accepts a JSON string of multiple settings. This approach simplifies markup when configuring several options at once. If the same option appears in both data-cx-config and as a separate data attribute (like data-cx-title), the individual attribute takes precedence. You can also use JSON values in individual attributes, such as data-cx-delay='{"show":100,"hide":200}' for more granular control.
When initializing components, Chassis merges configurations from multiple sources in this priority order: default settings, data-cx-config values, individual data-cx-* attributes, and finally any JavaScript object options. Values defined later in this sequence override earlier ones.
| Name | Type | Default | Description |
|---|---|---|---|
backdrop | boolean or the string static | true | Apply a backdrop on body while offcanvas is open. Alternatively, specify static for a backdrop which doesn’t close the offcanvas when clicked. |
keyboard | boolean | true | Closes the offcanvas when escape key is pressed. |
scroll | boolean | false | Allow body scrolling while offcanvas is open. |
Methods
All Chassis CSS component methods are asynchronous and initiate CSS transitions. Methods return immediately when the transition begins, not when it completes. Calling methods on components that are already transitioning will be ignored to prevent conflicts. Learn more about Chassis JavaScript patterns.
Activates your content as an offcanvas element. Accepts an optional options object.
You can create an offcanvas instance with the constructor, for example:
const cxOffcanvas = new chassis.Offcanvas('#myOffcanvas')
| Method | Description |
|---|---|
dispose | Destroys an element’s offcanvas. |
getInstance | Static method which allows you to get the offcanvas instance associated with a DOM element. |
getOrCreateInstance | Static method which allows you to get the offcanvas instance associated with a DOM element, or create a new one in case it wasn’t initialized. |
hide | Hides an offcanvas element. Returns to the caller before the offcanvas element has actually been hidden (i.e. before the hidden.cx.offcanvas event occurs). |
show | Shows an offcanvas element. Returns to the caller before the offcanvas element has actually been shown (i.e. before the shown.cx.offcanvas event occurs). |
toggle | Toggles an offcanvas element to shown or hidden. Returns to the caller before the offcanvas element has actually been shown or hidden (i.e. before the shown.cx.offcanvas or hidden.cx.offcanvas event occurs). |
Events
Chassis CSS’s offcanvas class exposes a few events for hooking into offcanvas functionality.
| Event type | Description |
|---|---|
hide.cx.offcanvas | This event is fired immediately when the hide method has been called. |
hidden.cx.offcanvas | This event is fired when an offcanvas element has been hidden from the user (will wait for CSS transitions to complete). |
hidePrevented.cx.offcanvas | This event is fired when the offcanvas is shown, its backdrop is static and a click outside of the offcanvas is performed. The event is also fired when the escape key is pressed and the keyboard option is set to false. |
show.cx.offcanvas | This event fires immediately when the show instance method is called. |
shown.cx.offcanvas | This event is fired when an offcanvas element has been made visible to the user (will wait for CSS transitions to complete). |
const myOffcanvas = document.getElementById('myOffcanvas')
myOffcanvas.addEventListener('hidden.cx.offcanvas', event => {
// do something...
})