Angular v20 - Focus Trap with Angular CDK
How to use Angular CDK a11y Module to create a focus trap for a sidebar component.
What is a Focus Trap?
In web and software development a focus trap is considered as a method to capture the focus inside a specific element, such as a sidebar, a pop-up or a modal dialog.
Setup
In the following sections you will create an Angular App, a custom OffCanvas Component and attach a reference of Angular CDK to achieve a Focus Trap.
Create a new Angular App
Simply run the following an afterwards navigate inside the project.
ng new my-app
Install Dependencies
Now inside your project install the Angular CDK and Bootstrap. We want to create the sidebar using the offcanvas CSS classes provided by Bootstrap.
npm i @angular/cdk bootstrap
Import Bootstrap
To make it easier, import Bootstrap into your index.html via CDN
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css"
rel="stylesheet" />
or inside your main SCSS file
@import 'bootstrap/scss/bootstrap';
Create a custom Angular Component
Create a folder called app-off-canvas and a custom Angular Component which should display the Off Canvas Component.
// app-off-canvas.component.ts;
import { Component } from '@angular/core';
@Component({
selector: 'app-off-canvas',
templateUrl: './app-off-canvas.component.html',
})
export class AppOffCanvasComponent {}
The following template will include the css class “show” to display the offcanvas as soon as it gets rendered to the DOM.
<!-- app-off-canvas.component.html -->
<div class="offcanvas offcanvas-start show" tabindex="-1">
<div class="offcanvas-header">
<h5 class="offcanvas-title">Menu</h5>
</div>
<div class="offcanvas-body">
<ng-content />
</div>
</div>
Import OffCanvas Component
Inside your App Component import the OffCanvas Component and create a showOffCanvas Property to control whether to show or hide the Component.
import { Component } from '@angular/core';
import { AppOffCanvasComponent } from './app-off-canvas/app-off-canvas.component';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
imports: [AppOffCanvasComponent],
})
export class App {
showOffCanvas: boolean = false;
toggleOffCanvas(): void {
this.showOffCanvas = !this.showOffCanvas;
}
}
To call the toggle function integrate a button and attach the toggleOffCanvas function.
Additionally wrap app-off-canvas inside a flow syntax if-block.
<button class="btn btn-primary mt-3" (click)="toggleOffCanvas()">toggle sidebar</button>
@if (showOffCanvas) {
<app-off-canvas (onClose)="toggleOffCanvas()"> some inner content </app-off-canvas>
}
Reference Angular CDK
Now the magic part.
Reference the directive cdkTrapFocus inside your app-off-canvas.component.html (make sure to import the A11yModule Module in your app-off-canvas.component.ts) and let´s add a close button as well.
<!-- app-off-canvas.component.html -->
<div class="offcanvas offcanvas-start show" tabindex="-1" cdkTrapFocus>
<div class="offcanvas-header justify-content-between">
<h5 class="offcanvas-title">Menu</h5>
<button class="btn-close" (click)="handleClickClose()"></button>
</div>
<div class="offcanvas-body">
<ng-content />
</div>
</div>
Test it
Now run the app and click on the button to show the OffCanvas Component. Clicking Tab Key you will see a focus on the close button.
If you want the close button to be focused initially you can reference [cdkTrapFocusAutoCapture]=“true” next to cdkTrapFocus inside app-off-canvas.component.html.
Test it live on Stackblitz