Basic
Offcanvas is a sidebar component that can be toggled to appear from the left, right, or bottom edge of the viewport. Buttons or anchors are used as triggers that are attached to specific elements you toggle.
Use bottom-0
, top-0
and
left-0
classes to place offcanvas on the left of the viewport.
Link with href
Offcanvas
Some text as placeholder. In real life you can have the elements you
have chosen. Like, text, images, lists, etc.
<a
class="me-1.5 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
data-twe-offcanvas-toggle
href="#offcanvasExample"
role="button"
aria-controls="offcanvasExample"
data-twe-ripple-init
data-twe-ripple-color="light">
Link with href
</a>
<button
class="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
type="button"
data-twe-offcanvas-toggle
data-twe-target="#offcanvasExample"
aria-controls="offcanvasExample"
data-twe-ripple-init
data-twe-ripple-color="light">
Button with data-twe-target
</button>
<div
class="invisible fixed bottom-0 left-0 top-0 z-[1045] flex w-96 max-w-full -translate-x-full flex-col border-none bg-white bg-clip-padding text-neutral-700 shadow-sm outline-none transition duration-300 ease-in-out data-[twe-offcanvas-show]:transform-none dark:bg-body-dark dark:text-white"
tabindex="-1"
id="offcanvasExample"
aria-labelledby="offcanvasExampleLabel"
data-twe-offcanvas-init>
<div class="flex items-center justify-between p-4">
<h5
class="mb-0 font-semibold leading-normal"
id="offcanvasExampleLabel">
Offcanvas
</h5>
<button
type="button"
class="box-content rounded-none border-none text-neutral-500 hover:text-neutral-800 hover:no-underline focus:text-neutral-800 focus:opacity-100 focus:shadow-none focus:outline-none dark:text-neutral-400 dark:hover:text-neutral-300 dark:focus:text-neutral-300"
data-twe-offcanvas-dismiss
aria-label="Close">
<span class="[&>svg]:h-6 [&>svg]:w-6">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M6 18L18 6M6 6l12 12" />
</svg>
</span>
</button>
</div>
<div class="flex-grow overflow-y-auto p-4">
<div>
Some text as placeholder. In real life you can have the elements you
have chosen. Like, text, images, lists, etc.
</div>
<div class="relative mt-4" data-twe-dropdown-ref>
<button
class="flex items-center whitespace-nowrap rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 motion-reduce:transition-none dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
type="button"
id="dropdownMenuButton"
data-twe-dropdown-toggle-ref
data-twe-ripple-init
data-twe-ripple-color="light">
Dropdown button
<span class="ms-2 w-2 [&>svg]:h-5 [&>svg]:w-5">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor">
<path
fill-rule="evenodd"
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
clip-rule="evenodd" />
</svg>
</span>
</button>
<ul
class="absolute z-[1000] float-left m-0 hidden min-w-max list-none overflow-hidden rounded-lg border-none bg-white bg-clip-padding text-left text-base shadow-lg data-[twe-dropdown-show]:block dark:bg-surface-dark"
aria-labelledby="dropdownMenuButton1"
data-twe-dropdown-menu-ref>
<li>
<a
class="block w-full whitespace-nowrap bg-white px-4 py-2 text-sm font-normal text-neutral-700 hover:bg-zinc-200/60 focus:bg-zinc-200/60 focus:outline-none active:bg-zinc-200/60 active:no-underline dark:bg-surface-dark dark:text-white dark:hover:bg-neutral-800/25 dark:focus:bg-neutral-800/25 dark:active:bg-neutral-800/25"
href="#"
data-twe-dropdown-item-ref
>Action</a
>
</li>
<li>
<a
class="block w-full whitespace-nowrap bg-white px-4 py-2 text-sm font-normal text-neutral-700 hover:bg-zinc-200/60 focus:bg-zinc-200/60 focus:outline-none active:bg-zinc-200/60 active:no-underline dark:bg-surface-dark dark:text-white dark:hover:bg-neutral-800/25 dark:focus:bg-neutral-800/25 dark:active:bg-neutral-800/25"
href="#"
data-twe-dropdown-item-ref
>Another action</a
>
</li>
<li>
<a
class="block w-full whitespace-nowrap bg-white px-4 py-2 text-sm font-normal text-neutral-700 hover:bg-zinc-200/60 focus:bg-zinc-200/60 focus:outline-none active:bg-zinc-200/60 active:no-underline dark:bg-surface-dark dark:text-white dark:hover:bg-neutral-800/25 dark:focus:bg-neutral-800/25 dark:active:bg-neutral-800/25"
href="#"
data-twe-dropdown-item-ref
>Something else here</a
>
</li>
</ul>
</div>
</div>
</div>
// Initialization for ES Users
import {
Offcanvas,
Ripple,
Dropdown,
initTWE,
} from "tw-elements";
initTWE({ Offcanvas, Ripple, Dropdown });
Placement - top
Use top-0
, left-0
and right-0
classes
to place offcanvas on the top of the viewport.
Offcanvas top
...
<button
class="me-1.5 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
type="button"
data-twe-offcanvas-toggle
data-twe-target="#offcanvasTop"
aria-controls="offcanvasTop"
data-twe-ripple-init
data-twe-ripple-color="light">
Toggle top offcanvas
</button>
<div
class="invisible fixed bottom-0 left-0 right-0 top-0 z-[1045] flex h-1/3 max-h-full max-w-full -translate-y-full flex-col border-none bg-white bg-clip-padding text-neutral-700 shadow-sm outline-none transition duration-300 ease-in-out data-[twe-offcanvas-show]:transform-none dark:bg-body-dark dark:text-white"
tabindex="-1"
id="offcanvasTop"
aria-labelledby="offcanvasTopLabel"
data-twe-offcanvas-init>
<div class="flex items-center justify-between p-4">
<h5 class="mb-0 font-semibold leading-normal" id="offcanvasTopLabel">
Offcanvas top
</h5>
<button
type="button"
class="box-content rounded-none border-none text-neutral-500 hover:text-neutral-800 hover:no-underline focus:text-neutral-800 focus:opacity-100 focus:shadow-none focus:outline-none dark:text-neutral-400 dark:hover:text-neutral-300 dark:focus:text-neutral-300"
data-twe-offcanvas-dismiss
aria-label="Close">
<span class="[&>svg]:h-6 [&>svg]:w-6">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M6 18L18 6M6 6l12 12" />
</svg>
</span>
</button>
</div>
<div class="flex-grow overflow-y-auto p-4">...</div>
</div>
// Initialization for ES Users
import {
Offcanvas,
Ripple,
initTWE,
} from "tw-elements";
initTWE({ Offcanvas, Ripple });
Placement - right
Use top-0
, right-0
, w-96
classes to
place offcanvas on the right of the viewport.
Offcanvas right
...
<button
class="me-1.5 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
type="button"
data-twe-offcanvas-toggle
data-twe-target="#offcanvasRight"
aria-controls="offcanvasRight"
data-twe-ripple-init
data-twe-ripple-color="light">
Toggle right offcanvas
</button>
<div
class="invisible fixed bottom-0 right-0 top-0 z-[1045] flex w-96 max-w-full translate-x-full flex-col border-none bg-white bg-clip-padding text-neutral-700 shadow-sm outline-none transition duration-300 ease-in-out data-[twe-offcanvas-show]:transform-none dark:bg-body-dark dark:text-white"
tabindex="-1"
id="offcanvasRight"
aria-labelledby="offcanvasRightLabel"
data-twe-offcanvas-init>
<div class="flex items-center justify-between p-4">
<h5
class="mb-0 font-semibold leading-normal"
id="offcanvasRightLabel">
Offcanvas right
</h5>
<button
type="button"
class="box-content rounded-none border-none text-neutral-500 hover:text-neutral-800 hover:no-underline focus:text-neutral-800 focus:opacity-100 focus:shadow-none focus:outline-none dark:text-neutral-400 dark:hover:text-neutral-300 dark:focus:text-neutral-300"
data-twe-offcanvas-dismiss
aria-label="Close">
<span class="[&>svg]:h-6 [&>svg]:w-6">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M6 18L18 6M6 6l12 12" />
</svg>
</span>
</button>
</div>
<div class="offcanvas-body flex-grow overflow-y-auto p-4">...</div>
</div>
// Initialization for ES Users
import {
Offcanvas,
Ripple,
initTWE,
} from "tw-elements";
initTWE({ Offcanvas, Ripple });
Placement - bottom
Use bottom-0
, left-0
, right-0
classes
to place offcanvas on the bottom of the viewport.
Offcanvas bottom
...
<button
class="me-1.5 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
type="button"
data-twe-offcanvas-toggle
data-twe-target="#offcanvasBottom"
aria-controls="offcanvasBottom"
data-twe-ripple-init
data-twe-ripple-color="light">
Toggle bottom offcanvas
</button>
<div
class="invisible fixed bottom-0 left-0 right-0 z-[1045] flex h-1/3 max-h-full max-w-full translate-y-full flex-col border-none bg-white bg-clip-padding text-neutral-700 shadow-sm outline-none transition duration-300 ease-in-out data-[twe-offcanvas-show]:transform-none dark:bg-body-dark dark:text-white"
tabindex="-1"
id="offcanvasBottom"
aria-labelledby="offcanvasBottomLabel"
data-twe-offcanvas-init>
<div class="flex items-center justify-between p-4">
<h5
class="mb-0 font-semibold leading-normal"
id="offcanvasBottomLabel">
Offcanvas bottom
</h5>
<button
type="button"
class="box-content rounded-none border-none text-neutral-500 hover:text-neutral-800 hover:no-underline focus:text-neutral-800 focus:opacity-100 focus:shadow-none focus:outline-none dark:text-neutral-400 dark:hover:text-neutral-300 dark:focus:text-neutral-300"
data-twe-offcanvas-dismiss
aria-label="Close">
<span class="[&>svg]:h-6 [&>svg]:w-6">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M6 18L18 6M6 6l12 12" />
</svg>
</span>
</button>
</div>
<div class="small flex-grow overflow-y-auto p-4">...</div>
</div>
// Initialization for ES Users
import {
Offcanvas,
Ripple,
initTWE,
} from "tw-elements";
initTWE({ Offcanvas, Ripple });
Related resources
Tutorials:
Extended Docs:
icons
navbar
sidenav
accordion
buttons
link
list group
social buttons
checkbox
datepicker
radio
range
search
select
switch
timepicker
breakpoints
dark theme
display flex
icons
overflow
position
spacing
sticky
visibility hidden
z index
Generators and builders:
Design System (Figma):
introduction
content should be the star
less is more
power of visual hierarchy
art of prioritization
de emphasize with no mercy
size matters
lowering contrast
low contrast vs low aesthetics
let it breathe
user experience
do not start with the roof
project personality
design system
principles
tips and tricks