Angular Offcanvas Component

Offcanvas

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 viewport
  • placement="top" places offcanvas on the top of the viewport
  • placement="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

jsx
import { OffcanvasComponent } from '@coreui/angular'

Props

PropertyDefaultType
ariaModaltrueboolean

Set aria-modal html attr for offcanvas

backdroptrueboolean, 'static'

Apply a backdrop on the body while offcanvas is open.

container5.7.21+document.bodyElement, object, null

Appends the offcanvas to a specific element. You can pass an HTML element or function that returns a single element. By default, document.body.

darkfalseboolean

Sets a darker color scheme. If the colorScheme is set to 'dark', the dark theme will be applied.

id`offcanvas-${this.placement()}-${nextId++}`string

Html id attribute, required for programmatic visibility change.

keyboardtrueboolean

Closes the offcanvas when the escape key is pressed

placement'start'string

Offcanvas placement

portal5.7.21+falseboolean

Generates offcanvas using a portal

responsive4.3.10+trueboolean, 'sm', 'md', 'lg', 'xl', 'xxl'

Responsive offcanvas property hides content outside the viewport from a specified breakpoint and down.

role'dialog'string

Default role for offcanvas

scrollfalseboolean

Allow body scrolling while offcanvas is visible.

visiblefalseboolean

Toggle the visibility of offcanvas component.

Events

Event name
visibleChange

Event triggered on visible change.

  • $event boolean

c-offcanvas-body

component

jsx
import { OffcanvasBodyComponent } from '@coreui/angular'

c-offcanvas-header

component

jsx
import { OffcanvasHeaderComponent } from '@coreui/angular'

cOffcanvasTitle

directive

jsx
import { OffcanvasTitleDirective } from '@coreui/angular'

cOffcanvasToggle

directive

jsx
import { OffcanvasToggleDirective } from '@coreui/angular'
PropertyDefaultType
cOffcanvasToggleundefinedstring

Html id attr of offcanvas to toggle.