Angular Offcanvas component allows to build hidden sidebars into your project for navigation, shopping carts, etc.
Available in Other JavaScript Frameworks
CoreUI Angular Offcanvas Component is also available for Bootstrap, React, and Vue. Explore framework-specific implementations below:
Examples
Live demo
Use the buttons below to show and hide an offcanvas component.
import { Component } from '@angular/core';
import {
ButtonCloseDirective,
ButtonDirective,
OffcanvasBodyComponent,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
OffcanvasToggleDirective
} from '@coreui/angular';
@Component({
selector: 'docs-offcanvas-live-demo',
templateUrl: './offcanvas-live-demo.component.html',
imports: [
ButtonDirective,
OffcanvasToggleDirective,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
ButtonCloseDirective,
OffcanvasBodyComponent
]
})
export class OffcanvasLiveDemoComponent {}<button cButton cOffcanvasToggle="OffcanvasStart">Toggle offcanvas</button>
<c-offcanvas
placement="start"
id="OffcanvasStart"
>
<c-offcanvas-header>
<h5 cOffcanvasTitle>Offcanvas Header</h5>
<button
cButtonClose
class="text-reset ms-auto"
cOffcanvasToggle="OffcanvasStart"
aria-label="Close"
></button>
</c-offcanvas-header>
<c-offcanvas-body>
<p>
Content for the offcanvas goes here. You can place just about any CoreUI component or custom elements here.
</p>
</c-offcanvas-body>
</c-offcanvas>
Placement
There’s no default placement for offcanvas components, so you must add one of the modifier props below;
placement="start"places offcanvas on the left of the viewport (shown above)placement="end"places offcanvas on the right of the viewportplacement="top"places offcanvas on the top of the viewportplacement="bottom"places offcanvas on the bottom of the viewport
import { Component } from '@angular/core';
import {
ButtonCloseDirective,
ButtonDirective,
OffcanvasBodyComponent,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
OffcanvasToggleDirective
} from '@coreui/angular';
@Component({
selector: 'docs-offcanvas-placement',
templateUrl: './offcanvas-placement.component.html',
imports: [
ButtonDirective,
OffcanvasToggleDirective,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
ButtonCloseDirective,
OffcanvasBodyComponent
]
})
export class OffcanvasPlacementComponent {}<button cButton cOffcanvasToggle="OffcanvasTop" class="me-1">Toggle top offcanvas</button>
<button cButton cOffcanvasToggle="OffcanvasBottom" class="me-1">Toggle bottom offcanvas</button>
<button cButton cOffcanvasToggle="OffcanvasEnd" class="me-1">Toggle end offcanvas</button>
<c-offcanvas
placement="top"
id="OffcanvasTop"
>
<c-offcanvas-header>
<h5 cOffcanvasTitle>Offcanvas Header</h5>
<button
cButtonClose
class="text-reset ms-auto"
cOffcanvasToggle="OffcanvasTop"
aria-label="Close"
></button>
</c-offcanvas-header>
<c-offcanvas-body>
<p>
Content for the offcanvas goes here. You can place just about any CoreUI component or custom elements here.
</p>
</c-offcanvas-body>
</c-offcanvas>
<c-offcanvas
placement="bottom"
id="OffcanvasBottom"
>
<c-offcanvas-header>
<h5 cOffcanvasTitle>Offcanvas Header</h5>
<button
cButtonClose
class="text-reset ms-auto"
cOffcanvasToggle="OffcanvasBottom"
aria-label="Close"
></button>
</c-offcanvas-header>
<c-offcanvas-body>
<p>
Content for the offcanvas goes here. You can place just about any CoreUI component or custom elements here.
</p>
</c-offcanvas-body>
</c-offcanvas>
<c-offcanvas
placement="end"
id="OffcanvasEnd"
>
<c-offcanvas-header>
<h5 cOffcanvasTitle>Offcanvas Header</h5>
<button
cButtonClose
class="text-reset ms-auto"
cOffcanvasToggle="OffcanvasEnd"
aria-label="Close"
></button>
</c-offcanvas-header>
<c-offcanvas-body>
<p>
Content for the offcanvas goes here. You can place just about any CoreUI component or custom elements here.
</p>
</c-offcanvas-body>
</c-offcanvas>Backdrop and Scroll
Scrolling the body element is disabled when an offcanvas and its backdrop are visible. Use the scroll property to toggle body scrolling and backdrop to toggle the backdrop.
import { Component } from '@angular/core';
import {
ButtonCloseDirective,
ButtonDirective,
OffcanvasBodyComponent,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
OffcanvasToggleDirective
} from '@coreui/angular';
@Component({
selector: 'docs-offcanvas-backdrop-scroll',
templateUrl: './offcanvas-backdrop-scroll.component.html',
imports: [
ButtonDirective,
OffcanvasToggleDirective,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
ButtonCloseDirective,
OffcanvasBodyComponent
]
})
export class OffcanvasBackdropScrollComponent {}<button cButton [cOffcanvasToggle]="offcanvasScroll.id()" class="me-1">Enable body scrolling</button>
<button cButton [cOffcanvasToggle]="offcanvasNoBackdrop.id()" class="me-1">Disable backdrop</button>
<c-offcanvas
id="OffcanvasScroll"
[scroll]="true"
placement="start"
#offcanvasScroll
>
<c-offcanvas-header>
<h5 cOffcanvasTitle>Offcanvas Header</h5>
<button
aria-label="Close"
cButtonClose
[cOffcanvasToggle]="offcanvasScroll.id()"
class="text-reset ms-auto"
></button>
</c-offcanvas-header>
<c-offcanvas-body>
<p>
Try scrolling the rest of the page to see this option in action.
</p>
</c-offcanvas-body>
</c-offcanvas>
<c-offcanvas
id="OffcanvasNoBackdrop"
[backdrop]="false"
[scroll]="true"
placement="end"
#offcanvasNoBackdrop
>
<c-offcanvas-header>
<h5 cOffcanvasTitle>Offcanvas Header</h5>
<button
aria-label="Close"
cButtonClose
[cOffcanvasToggle]="offcanvasNoBackdrop.id()"
class="text-reset ms-auto"
></button>
</c-offcanvas-header>
<c-offcanvas-body>
<p>
Try scrolling the rest of the page to see this option in action.
</p>
</c-offcanvas-body>
</c-offcanvas>
Static Backdrop
With backdrop prop set to static, the offcanvas will not close when clicking outside of it nor pressing Esc.
import { Component } from '@angular/core';
import {
ButtonCloseDirective,
ButtonDirective,
OffcanvasBodyComponent,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
OffcanvasToggleDirective
} from '@coreui/angular';
@Component({
selector: 'docs-offcanvas-static-backdrop',
templateUrl: './offcanvas-static-backdrop.component.html',
imports: [
ButtonDirective,
OffcanvasToggleDirective,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
ButtonCloseDirective,
OffcanvasBodyComponent
]
})
export class OffcanvasStaticBackdropComponent {}<button cButton [cOffcanvasToggle]="offcanvasStatic.id()">Toggle static offcanvas</button>
<c-offcanvas
id="OffcanvasStatic"
backdrop="static"
placement="start"
#offcanvasStatic
>
<c-offcanvas-header>
<h5 cOffcanvasTitle>Offcanvas Header</h5>
<button
aria-label="Close"
cButtonClose
[cOffcanvasToggle]="offcanvasStatic.id()"
class="text-reset ms-auto"
></button>
</c-offcanvas-header>
<c-offcanvas-body>
<p>
I will not close if you try to click outside of me or to press escape key.
</p>
</c-offcanvas-body>
</c-offcanvas>Portal
By default, c-offcanvas renders in place in the DOM, moved on top of everything else purely through position: fixed and stacking. When an ancestor establishes its own containing block (e.g. via transform, filter, or perspective), it traps that fixed positioning and clips the offcanvas. Set the portal input to move the offcanvas’s host element into container (an Element, a function returning one, or document.body by default) while it’s visible, and restore it to its original position on close.
import { Component } from '@angular/core';
import {
ButtonCloseDirective,
ButtonDirective,
OffcanvasBodyComponent,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
OffcanvasToggleDirective
} from '@coreui/angular';
@Component({
selector: 'docs-offcanvas-portal',
templateUrl: './offcanvas-portal.component.html',
imports: [
ButtonDirective,
OffcanvasToggleDirective,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
ButtonCloseDirective,
OffcanvasBodyComponent
]
})
export class OffcanvasPortalComponent {}<div class="border rounded p-3" style="max-height: 160px; overflow: auto; transform: translateZ(0);">
<p>This wrapper creates a new containing block (via <code>transform</code>), which normally clips a fixed-position offcanvas to its bounds.</p>
<button cButton [cOffcanvasToggle]="portalOffcanvas.id()">Launch portal offcanvas</button>
<c-offcanvas portal id="portalOffcanvas" #portalOffcanvas>
<c-offcanvas-header>
<h5 cOffcanvasTitle>Offcanvas title</h5>
<button
aria-label="Close"
cButtonClose
[cOffcanvasToggle]="portalOffcanvas.id()"
class="text-reset ms-auto"
></button>
</c-offcanvas-header>
<c-offcanvas-body>
Thanks to the <code>portal</code> input, this offcanvas is moved to <code>document.body</code> while visible, so it escapes the clipped wrapper above instead of being trapped inside it.
</c-offcanvas-body>
</c-offcanvas>
</div>Responsive
Responsive offcanvas hides the content outside the viewport below the specified breakpoint. Above that breakpoint, the content is displayed as usual.
import { Component } from '@angular/core';
import {
AlertComponent,
ButtonCloseDirective,
ButtonDirective,
OffcanvasBodyComponent,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
OffcanvasToggleDirective
} from '@coreui/angular';
@Component({
selector: 'docs-offcanvas-responsive',
templateUrl: './offcanvas-responsive.component.html',
imports: [
ButtonDirective,
OffcanvasToggleDirective,
AlertComponent,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
ButtonCloseDirective,
OffcanvasBodyComponent
]
})
export class OffcanvasResponsiveComponent {}<button cButton class="d-lg-none" [cOffcanvasToggle]="offcanvasResponsive.id()">Toggle offcanvas</button>
<c-alert color="info" class="d-none d-lg-block">Resize your browser to show the responsive offcanvas toggle button.</c-alert>
<c-offcanvas
responsive="lg"
placement="end"
#offcanvasResponsive
>
<c-offcanvas-header>
<h5 cOffcanvasTitle>Responsive offcanvas Header</h5>
<button
aria-label="Close"
cButtonClose
[cOffcanvasToggle]="offcanvasResponsive.id()"
class="text-reset ms-auto"
></button>
</c-offcanvas-header>
<c-offcanvas-body>
<p class="mb-0">This is content within an offcanvas with <code>responsive="lg"</code> property.</p>
</c-offcanvas-body>
</c-offcanvas>Dark offcanvas
With .text-bg-dark utility class you can change the appearance of your offcanvas component.
import { Component } from '@angular/core';
import {
ButtonCloseDirective,
ButtonDirective,
OffcanvasBodyComponent,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
OffcanvasToggleDirective
} from '@coreui/angular';
@Component({
selector: 'docs-offcanvas-dark',
templateUrl: './offcanvas-dark.component.html',
imports: [
ButtonDirective,
OffcanvasToggleDirective,
OffcanvasComponent,
OffcanvasHeaderComponent,
OffcanvasTitleDirective,
ButtonCloseDirective,
OffcanvasBodyComponent
]
})
export class OffcanvasDarkComponent {}<button cButton cOffcanvasToggle="OffcanvasDark">Dark offcanvas</button>
<c-offcanvas
placement="start"
id="OffcanvasDark"
class="text-bg-dark"
>
<c-offcanvas-header>
<h5 cOffcanvasTitle>Dark Offcanvas Header</h5>
<button
cButtonClose
white
cOffcanvasToggle="OffcanvasDark"
aria-label="Close"
class="ms-auto"
></button>
</c-offcanvas-header>
<c-offcanvas-body>
<p>
Content for the dark offcanvas goes here.
</p>
</c-offcanvas-body>
</c-offcanvas>
Accessibility
Since the offcanvas panel is conceptually a modal dialog, be sure to add aria-labelledby="..." —referencing the offcanvas title— to c-offcanvas>. Note that you don’t need to add role="dialog" since we already add it automatically.
API reference
Offcanvas Module
import { OffcanvasModule } from '@coreui/angular';
@NgModule({
imports: [OffcanvasModule,]
})
export class AppModule() { }c-offcanvas
component
import { OffcanvasComponent } from '@coreui/angular'Props
Events
c-offcanvas-body
component
import { OffcanvasBodyComponent } from '@coreui/angular'c-offcanvas-header
component
import { OffcanvasHeaderComponent } from '@coreui/angular'cOffcanvasTitle
directive
import { OffcanvasTitleDirective } from '@coreui/angular'cOffcanvasToggle
directive
import { OffcanvasToggleDirective } from '@coreui/angular'