
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@components-1812/offcanvas
Advanced tools

Codepen:
Overview
2 - Panel placement
3 - Panel scroll
4 - Custom icons
5 - Backdrop content
6 - Backdrop static
7 - Panel responsive
npm install @components-1812/offcanvas
Load the component bundle directly from a CDN — this will automatically register the element and inject styles:
<!-- Classic script -->
<script src="https://cdn.jsdelivr.net/npm/@components-1812/offcanvas@0.0.3/dist/index.min.js"></script>
<!-- ES module -->
<script type="module">
import "https://cdn.jsdelivr.net/npm/@components-1812/offcanvas@0.0.3/dist/index.min.js";
</script>
Alternatively, you can manually import, load the styles, and define the element yourself:
<script type="module">
import Offcanvas from "https://cdn.jsdelivr.net/npm/@components-1812/offcanvas@0.0.3/src/Offcanvas.min.js";
// Load the stylesheet from a CDN
Offcanvas.stylesSheets.links.push(
"https://cdn.jsdelivr.net/npm/@components-1812/offcanvas@0.0.3/src/Offcanvas.min.css"
);
//Define with the default tag
Offcanvas.define();
</script>
jsdelivr: Offcanvas package
Offcanvas.js
Offcanvas.css
Offcanvas.min.js
Offcanvas.min.css
Bundle
unpkg: Offcanvas package
Offcanvas.js
Offcanvas.css
Offcanvas.min.js
Offcanvas.min.css
Bundle
If you are using Vite or a Vite-based framework such as Astro, you can import the component in a client-side script:
import '@components-1812/offcanvas';
and use it in your HTML:
<custom-offcanvas open variant="right global" handle-button>
<!-- Panel content -->
<div slot="header">Header</div>
<div>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quod.</p>
</div>
<div slot="footer">Footer</div>
<!--Custom icons -->
<div slot="close-button">❌</div>
<div slot="handle-button" data-rotate-icon>➡️</div>
<!-- Backdrop content -->
<div slot="backdrop" style="position: absolute; top: 0; left: 0;">
<p>This is the backdrop content.</p>
<p>You can add any content here.</p>
</div>
</custom-offcanvas>
If you are using a builder or framework that does not support importing with ?raw,
you can load and register the component using the bundle version in dist/index.min.js, which includes all CSS injected via CSS-in-JS and AdoptedStyleSheets:
import '@components-1812/offcanvas/dist/index.min.js';
For customizing the component definition or manually loading the stylesheets, see [Defining and Adding Stylesheets Manually](#Defining and Adding Stylesheets Manually).
Node
The
distfolder includes minified versions:Offcanvas.min.cssandOffcanvas.min.js, which can be used anywhere.
If you want to add custom stylesheets to the component or need to load stylesheets from a different path, you can do it like this:
Using your builder’s import raw method, CSSStyleSheet, and the component’s AdoptedStyleSheets property:
import Offcanvas from "@components-1812/offcanvas/Offcanvas.js";
import OffcanvasRawCSS from "@components-1812/offcanvas/Offcanvas.css?raw";
//Create a CSSStyleSheet and add it to the component
const OffcanvasCSS = new CSSStyleSheet();
OffcanvasCSS.replaceSync(OffcanvasRawCSS);
Offcanvas.stylesSheets.adopted.push(OffcanvasCSS);
//Define the component with default tag name
Offcanvas.define();
<style> tagUsing a <style> tag inside the shadow root of the component:
import Offcanvas from "@components-1812/offcanvas/Offcanvas.js";
//Add the raw stylesheet to the component
const OffcanvasRawCSS = `:host {
/* ...Offcanvas.css styles... */
}`;
Offcanvas.stylesSheets.raw.push(OffcanvasRawCSS);
//Define the component custom tag name
Offcanvas.define('other-custom-tag-name');
<link> tagUsing a <link> tag inside the shadow root of the component:
import Offcanvas from "@components-1812/offcanvas/Offcanvas.js";
//Add the url source stylesheets to the component
Offcanvas.stylesSheets.links.push('https://cdn.example.com/Offcanvas.css');
//Define the component manually
customElements.define('custom-offcanvas', Offcanvas);
--offcanvas-position: absolute;
--offcanvas-z-index: 8010;
/* Panel */
--offcanvas-panel-width: 300px;
--offcanvas-panel-height: 100%;
--offcanvas-panel-padding: 5px;
--offcanvas-panel-transition: margin 0.3s ease-in-out;
--offcanvas-panel-header-padding: 5px;
--offcanvas-panel-body-padding: 5px;
--offcanvas-panel-footer-padding: 5px;
--offcanvas-shadow: 0 1px 3px 0 #3c40434d, 0 4px 8px 3px #3c404326;
--offcanvas-panel-bg: #222;
--offcanvas-panel-color: #fff;
--offcanvas-panel-header-bg: var(--offcanvas-panel-bg);
--offcanvas-panel-header-color: var(--offcanvas-panel-color);
--offcanvas-panel-footer-bg: var(--offcanvas-panel-bg);
--offcanvas-panel-footer-color: var(--offcanvas-panel-color);
--offcanvas-panel-border-width: 1px;
--offcanvas-panel-border-style: solid;
--offcanvas-panel-border-color: #ccc;
--offcanvas-panel-border: var(--offcanvas-panel-border-width) var(--offcanvas-panel-border-style) var(--offcanvas-panel-border-color);
--offcanvas-panel-border-radius: 0px;
/* Backdrop */
--offcanvas-backdrop-bg: #00000080;
--offcanvas-backdrop-color: #fff;
--offcanvas-backdrop-transition: background-color 0.3s ease-in-out;
/* Close button */
--offcanvas-close-button-width: 40px;
--offcanvas-close-button-height: 40px;
--offcanvas-close-button-padding: 10px;
--offcanvas-close-button-bg: transparent;
--offcanvas-close-button-color: #fff;
--offcanvas-close-button-border: none;
--offcanvas-close-button-font-size: 1.5rem;
--offcanvas-close-button-cursor: pointer;
/* Handle button */
--offcanvas-handle-button-width: 50px;
--offcanvas-handle-button-height: 100px;
--offcanvas-handle-button-padding: 5px;
--offcanvas-handle-button-bg: #444;
--offcanvas-handle-button-color: #fff;
--offcanvas-handle-button-border: none;
--offcanvas-handle-button-border-radius: 10px;
--offcanvas-handle-button-cursor: pointer;
--offcanvas-handle-button-font-size: 1rem;
--offcanvas-handle-button-shadow: var(--offcanvas-shadow);
--offcanvas-panel-width: 100%;
--offcanvas-panel-height: 300px;
--offcanvas-handle-button-width: 100px;
--offcanvas-handle-button-height: 50px;
--offcanvas-panel-shadow: 1px 0 3px 0 #3c40434d, 4px 0 8px 3px #3c404326;
For responsive design, there will be times when you want the panel to occupy the full width of the screen, especially on mobile devices.
You can achieve this by adding a CSS media query like the following:
custom-offcanvas {
@media (width <= 500px) {
--offcanvas-panel-width: 100%;
}
}
This will ensure that the offcanvas panel expands to the full screen width on devices with a width of 500px or less.
See the example: 7 - Panel responsive
You can open the offcanvas panel using the open attribute:
<custom-offcanvas open></custom-offcanvas>
Via JavaScript, you can use the open property (mirrored attribute):
const offcanvas = document.querySelector('custom-offcanvas');
// Open the panel
offcanvas.open = true;
// Close the panel
offcanvas.open = false;
You can also control the panel with the methods: .show(), .hide(), .toggle()
const offcanvas = document.querySelector('custom-offcanvas');
// Show the panel
offcanvas.show();
// Hide the panel
offcanvas.hide();
// Toggle the panel (switch state)
offcanvas.toggle(); // toggle current state
offcanvas.toggle(true); // force open
offcanvas.toggle(false); // force close
The default slot is reserved for the panel body, which contains the main content.
You can also use the following named slots:
slot="header" – for the panel header.
slot="footer" – for the panel footer.
<custom-offcanvas open variant="right" handle-button>
<div slot="header">Header</div>
<div>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, quod.</p>
</div>
<div slot="footer">Footer</div>
</custom-offcanvas>
You can replace the default icons for the close button and the handle button (if present) using:
slot="close-button"
slot="handle-button"
para modificar los iconos por defecto del close button y el handle button (si esta) puedes usar slot="close-button" y slot="handle-button"
<custom-offcanvas open variant="right" handle-button>
<div slot="close-button">❌</div>
<div slot="handle-button" data-rotate-icon>➡️</div>
</custom-offcanvas>
Note
For the handle button, you can add the attribute
data-rotate-iconso that the icon always rotates to point in the correct direction according to the panel position and open/closed state.To work correctly, the icon must initially point to the right.
The backdrop slot allows you to add custom content positioned around the panel for richer interactions or decorations.
Elements in this slot should use position: absolute;
Since the backdrop changes size when the panel opens or closes, the elements will move together with the panel.
<custom-offcanvas open variant="left" handle-button>
<!-- Backdrop content -->
<div slot="backdrop" style="position: absolute; top: 0; left: 0;">
<p>This is the backdrop content.</p>
<p>You can add any content here.</p>
</div>
<div slot="backdrop" style="position: absolute; bottom: 0; right: 0;">
<p>This is another backdrop content.</p>
<p>You can customize the backdrop as needed.</p>
</div>
</custom-offcanvas>
You can also control the visibility of backdrop elements based on the panel state using attributes like:
data-hide-when-closed – hides the element when the panel is closed.
data-hide-when-opened – hides the element when the panel is open.
<custom-offcanvas open variant="left" handle-button>
<!-- Backdrop content -->
<div slot="backdrop" style="position: absolute; top: 0; right: 0;" data-hide-when-closed>
<p>This content will hide when the offcanvas is closed.</p>
</div>
<div slot="backdrop" style="position: absolute; bottom: 0; left: 0;" data-hide-when-opened>
<p>This content will hide when the offcanvas is opened.</p>
</div>
</custom-offcanvas>
See the example: 5 - Backdrop content
You can control whether the offcanvas panel is positioned relative to the viewport or inside its container using the variant attribute:
local (default) – The panel is positioned absolute relative to its nearest positioned ancestor.
global – The panel is positioned fixed relative to the viewport. This is useful for modals or overlays.
<!-- Fixed to the viewport -->
<custom-offcanvas variant="top global"></custom-offcanvas>
<!-- Positioned inside a container -->
<div class="container" style="position: relative;">
<custom-offcanvas variant="left local"></custom-offcanvas>
</div>
The variant attribute defines the position of the offcanvas panel: left, right, top, bottom
<custom-offcanvas variant="left"></custom-offcanvas>
<custom-offcanvas variant="right"></custom-offcanvas>
<custom-offcanvas variant="top"></custom-offcanvas>
<custom-offcanvas variant="bottom"></custom-offcanvas>
See the example: 2 - Panel placement
By default, the panel does not scroll. You can customize the scroll behavior using the following variants:
scroll-full: The entire panel content scrolls.
scroll-inner: All content scrolls except the header
scroll-body: Only the body scrolls; header and footer remain fixed.
<custom-offcanvas variant="scroll-full"></custom-offcanvas>
<custom-offcanvas variant="scroll-inner"></custom-offcanvas>
<custom-offcanvas variant="scroll-body"></custom-offcanvas>
See the example: 3 - Panel scroll
By default, the component does not provide any control to open the panel; you must add it manually.
With the handle-button attribute, the component automatically adds a button inside the backdrop content, centered along the edge of the panel. This button allows users to open and close the panel.
<custom-offcanvas variant="right" handle-button></custom-offcanvas>
backdrop-static: By default, clicking on the backdrop closes the panel.
You can disable this behavior by adding the backdrop-static variant:
<custom-offcanvas variant="backdrop-static"></custom-offcanvas>
With this variant, clicking on the backdrop won’t close the panel, and the page behind it remains interactive while the panel is open.
backdrop-transparent
If you want to hide the backdrop background when the panel is open, you have two options:
--offcanvas-backdrop-bgbackdrop-transparent variant:<custom-offcanvas variant="backdrop-transparent"></custom-offcanvas>
variant: Panel position or visual style.
left, top, right, bottomscroll-full, scroll-inner, scroll-bodyglobal, localopen (boolean, default false): Whether the panel is open.
handle-button (boolean, default false): Whether to show a floating handle button.
variant (string): Panel position or visual style.
open (boolean): Whether the panel is open.
handleButton (boolean): Whether the handle button is visible.
show(): Opens the panel (open = true).
hide(): Closes the panel (open = false).
toggle(force?: boolean): Toggles the panel. If force is true or false, sets the panel state accordingly.
ready-links: Fired when all external stylesheet links have finished loading. Provides a detail with the results of each stylesheet.
ready: Dispatched when the component has finished initializing (end of connectedCallback)
VERSION (string): Component version (0.0.3).
DEFAULT_TAG_NAME (string): Default tag name (custom-offcanvas) use it to define the custom element in index.js and define.js
DEFAULT_ICONS (object): Default svg icons for close-button and handle-button.
Offcanvas.DEFAULT_ICONS = {
'close-button': `<svg>...</svg>`,
'handle-button': `<svg data-rotate-icon>...</svg>`
}
stylesSheets (object): Contains links, adopted, and raw stylesheets to apply to the component.
Offcanvas.stylesSheets = {
links: [],//string url css source
adopted: [],//CSSStyleSheet instances
raw: [],//string raw css
};
define(tagName?, stylesSheets?) (function): Defines the custom element and optionally adds stylesheets if the element is not already registered.
Offcanvas.define('custom-offcanvas', {
links: ['https://cdn.example.com/Offcanvas.css'],
adopted: [new CSSStyleSheet()],
raw: [':host { /* ...Offcanvas.css styles... */ }'],
});
Internally, this method calls
window.customElements.define(tagName, Offcanvas)
default: Main content of the panel
header: Header content of the panel
footer: Footer content of the panel
close-button: Icon or content for the close button in the header of the panel
handle-button: Icon or content for the handle button if added
backdrop: Content inside the backdrop (around the panel)
This package is distributed under the MIT license.
Default icons used in this package are sourced from the Bootstrap Icons project, licensed under the MIT license.
© 2019–2024 The Bootstrap Authors
FAQs
A web component for custom offcanvas, lateral panel
We found that @components-1812/offcanvas demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.