How can I attach a button to an off-canvas drawer with Bootstrap 5?

Viewed 549

I'm playing with the Bootstrap 5 off-canvas feature. I am trying to get a button to attach to the side of the off-canvas slide out drawer. So when the drawer is off-canvas, the button is visible. When the button is clicked, the drawer slides out but instead of overlaying the drawer content over the button, the button acts as if it's attached to the slide out drawer and moves with it. Like this:

enter image description here

I'm not sure if this is possible. If so, how would I go about doing this?

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">

<div class="offcanvas offcanvas-start" id="demo">
  <div class="offcanvas-header">
    <h1 class="offcanvas-title">Heading</h1>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas"></button>
  </div>
  <div class="offcanvas-body">
    <p>Some text lorem ipsum.</p>
  </div>
</div>

<div class="container-fluid mt-3">
  <button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#demo">
        Open
    </button>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>

1 Answers

You could apply sideward translation with transition to match that of the sidebar when the panel is open. I'm using a div around the button because the button has transitions on it already, and I'm raising its stacking order to be above the sidebar mask.

.offcanvas-btn-box {
  transition: transform .3s ease-in-out; /* same as what's on the panel */
}

.offcanvas.show + div .offcanvas-btn-box {
  transform: translateX(400px);
  position: relative;
  z-index: 1100;
}


/* optional junk to toggle the button text */
.offcanvas-btn-box .btn span:last-child,
.offcanvas.show + div .offcanvas-btn-box .btn span:first-child {
  display: none;
}

.offcanvas.show + div .offcanvas-btn-box .btn span:last-child {
  display: inline;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">

<div class="offcanvas offcanvas-start" id="demo">
  <div class="offcanvas-header">
    <h1 class="offcanvas-title">Heading</h1>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas"></button>
  </div>
  <div class="offcanvas-body">
    <p>Some text lorem ipsum.</p>
  </div>
</div>

<div class="container-fluid mt-3">
  <div class="offcanvas-btn-box">
    <button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#demo">
        <span>Open</span><span>Close</span>
    </button>
  </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>

Alternatively, put the button inside the panel and position it absolutely. This has the benefit of not cluttering your main page layout.

.offcanvas-btn {
  left: 420px;
  visibility: visible;
}

/* optional junk to toggle the button text */
.offcanvas-btn span:last-child,
.offcanvas.show .offcanvas-btn span:first-child {
  display: none;
}

.offcanvas.show .offcanvas-btn span:last-child {
  display: inline;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">

<div class="offcanvas offcanvas-start" id="demo">
  <button class="btn btn-primary offcanvas-btn position-absolute mt-2" type="button" data-bs-toggle="offcanvas" data-bs-target="#demo">
        <span>Open</span><span>Close</span>
    </button>

  <div class="offcanvas-header">
    <h1 class="offcanvas-title">Heading</h1>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas"></button>
  </div>
  <div class="offcanvas-body">
    <p>Some text lorem ipsum.</p>
  </div>
</div>

<div class="container-fluid mt-4 pt-4">
  Some page content.
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>

Related