Offcanvas

Offcanvas (오프캔버스)

몇 개의 클래스와 JavaScript 플러그인으로 네비게이션, 쇼핑 카트 등을 위한 숨겨진 사이드바를 프로젝트에 만드는 방법을 다룹니다.

출처: 문서

본문

동작 원리 (How it works)

Offcanvas는 JavaScript로 토글해 뷰포트의 왼쪽, 오른쪽, 위쪽, 아래쪽 가장자리에서 나타날 수 있는 사이드바 컴포넌트입니다. 버튼이나 앵커는 토글하려는 특정 요소에 연결되는 트리거로 사용되며, data 속성을 사용해 JavaScript를 호출합니다.

  • Offcanvas는 modal과 일부 JavaScript 코드를 공유합니다. 개념적으로는 꽤 비슷하지만, 별도의 플러그인입니다.
  • 마찬가지로 offcanvas의 스타일과 크기에 대한 일부 Sass 변수는 modal의 변수에서 상속됩니다.
  • 표시될 때 offcanvas에는 기본 backdrop이 포함되며, 이를 클릭하면 offcanvas를 숨길 수 있습니다.
  • modal과 비슷하게 한 번에 하나의 offcanvas만 표시할 수 있습니다.

주의! CSS가 애니메이션을 처리하는 방식 때문에 .offcanvas 요소에 margin이나 translate을 사용할 수 없습니다. 대신 클래스를 독립적인 래핑 요소로 사용하세요.

이 컴포넌트의 애니메이션 효과는 prefers-reduced-motion 미디어 쿼리에 의존합니다. 접근성 문서의 reduced motion 섹션을 참고하세요.

예시 (Examples)

Offcanvas 컴포넌트 (Offcanvas components)

아래는 기본적으로 표시되는(.offcanvas의 .show를 통해) offcanvas 예시입니다. Offcanvas는 닫기 버튼이 있는 헤더와, 약간의 초기 padding을 위한 선택적 본문 클래스를 지원합니다. 가능하면 닫기 동작이 있는 offcanvas 헤더를 포함하거나, 명시적인 닫기 동작을 제공할 것을 권장합니다.

<div class="offcanvas offcanvas-start show" tabindex="-1" id="offcanvas" aria-labelledby="offcanvasLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasLabel">Offcanvas</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    Content for the offcanvas goes here. You can place just about any Bootstrap component or custom elements here.
  </div>
</div>

라이브 데모 (Live demo)

아래의 버튼을 사용해 .offcanvas 클래스가 있는 요소의 .show 클래스를 토글하는 JavaScript로 offcanvas 요소를 표시하거나 숨깁니다.

  • .offcanvas는 콘텐츠를 숨깁니다(기본)
  • .offcanvas.show는 콘텐츠를 표시합니다

href 속성이 있는 링크나 data-bs-target 속성이 있는 버튼을 사용할 수 있습니다. 두 경우 모두 data-bs-toggle="offcanvas"가 필요합니다.

<a class="btn btn-primary" data-bs-toggle="offcanvas" href="#offcanvasExample" role="button" aria-controls="offcanvasExample">
  Link with href
</a>
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample" aria-controls="offcanvasExample">
  Button with data-bs-target
</button>

<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasExample" aria-labelledby="offcanvasExampleLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasExampleLabel">Offcanvas</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <div>
      Some text as placeholder. In real life you can have the elements you have chosen. Like, text, images, lists, etc.
    </div>
    <div class="dropdown mt-3">
      <button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
        Dropdown button
      </button>
      <ul class="dropdown-menu">
        <li><a class="dropdown-item" href="#">Action</a></li>
        <li><a class="dropdown-item" href="#">Another action</a></li>
        <li><a class="dropdown-item" href="#">Something else here</a></li>
      </ul>
    </div>
  </div>
</div>

Body 스크롤 (Body scrolling)

offcanvas와 그 backdrop이 보일 때 <body> 요소의 스크롤은 비활성화됩니다. <body> 스크롤을 활성화하려면 data-bs-scroll 속성을 사용하세요.

<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasScrolling" aria-controls="offcanvasScrolling">Enable body scrolling</button>

<div class="offcanvas offcanvas-start" data-bs-scroll="true" data-bs-backdrop="false" tabindex="-1" id="offcanvasScrolling" aria-labelledby="offcanvasScrollingLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasScrollingLabel">Offcanvas with body scrolling</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <p>Try scrolling the rest of the page to see this option in action.</p>
  </div>
</div>

Body 스크롤과 backdrop (Body scrolling and backdrop)

보이는 backdrop과 함께 <body> 스크롤을 활성화할 수도 있습니다.

<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasWithBothOptions" aria-controls="offcanvasWithBothOptions">Enable both scrolling & backdrop</button>

<div class="offcanvas offcanvas-start" data-bs-scroll="true" tabindex="-1" id="offcanvasWithBothOptions" aria-labelledby="offcanvasWithBothOptionsLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasWithBothOptionsLabel">Backdrop with scrolling</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <p>Try scrolling the rest of the page to see this option in action.</p>
  </div>
</div>

정적 backdrop (Static backdrop)

backdrop을 static으로 설정하면 offcanvas 바깥을 클릭해도 offcanvas가 닫히지 않습니다.

<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#staticBackdrop" aria-controls="staticBackdrop">
  Toggle static offcanvas
</button>

<div class="offcanvas offcanvas-start" data-bs-backdrop="static" tabindex="-1" id="staticBackdrop" aria-labelledby="staticBackdropLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="staticBackdropLabel">Offcanvas</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <div>
      I will not close if you click outside of me.
    </div>
  </div>
</div>

다크 offcanvas (Dark offcanvas)

v5.3.0에서 폐기됨, v5.2.0에서 추가됨

유틸리티로 offcanvas의 모양을 바꿔 다크 navbar 같은 다른 컨텍스트에 더 잘 맞출 수 있습니다. 여기서는 다크 offcanvas에 제대로 스타일을 적용하기 위해 .offcanvas에 .text-bg-dark를, .btn-close에 .btn-close-white를 추가했습니다. 안에 드롭다운이 있다면 .dropdown-menu에 .dropdown-menu-dark도 추가하는 것을 고려하세요.

주의! 컴포넌트의 다크 변형은 v5.3.0에서 color modes가 도입되면서 폐기되었습니다. 위에서 언급한 클래스를 수동으로 추가하는 대신 루트 요소, 부모 래퍼, 또는 컴포넌트 자체에 data-bs-theme="dark"를 설정하세요.

<div class="offcanvas offcanvas-start show text-bg-dark" tabindex="-1" id="offcanvasDark" aria-labelledby="offcanvasDarkLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasDarkLabel">Offcanvas</h5>
    <button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvasDark" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <p>Place offcanvas content here.</p>
  </div>
</div>

반응형 (Responsive)

v5.2.0에서 추가됨

반응형 offcanvas 클래스는 지정된 브레이크포인트부터 그 아래에서 콘텐츠를 뷰포트 밖으로 숨깁니다. 그 브레이크포인트를 넘어서면 안의 콘텐츠는 평소처럼 동작합니다. 예를 들어 .offcanvas-lg는 lg 브레이크포인트 아래에서는 offcanvas 안의 콘텐츠를 숨기지만, lg 브레이크포인트 위에서는 콘텐츠를 표시합니다. 반응형 offcanvas 클래스는 각 브레이크포인트에 대해 사용할 수 있습니다.

  • .offcanvas
  • .offcanvas-sm
  • .offcanvas-md
  • .offcanvas-lg
  • .offcanvas-xl
  • .offcanvas-xxl

반응형 offcanvas를 만들려면 .offcanvas 기본 클래스를 반응형 변형으로 바꾸고 닫기 버튼에 명시적인 data-bs-target이 있는지 확인하세요.

<button class="btn btn-primary d-lg-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasResponsive" aria-controls="offcanvasResponsive">Toggle offcanvas</button>

<div class="alert alert-info d-none d-lg-block">Resize your browser to show the responsive offcanvas toggle.</div>

<div class="offcanvas-lg offcanvas-end" tabindex="-1" id="offcanvasResponsive" aria-labelledby="offcanvasResponsiveLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasResponsiveLabel">Responsive offcanvas</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#offcanvasResponsive" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <p class="mb-0">This is content within an <code>.offcanvas-lg</code>.</p>
  </div>
</div>

배치 (Placement)

offcanvas 컴포넌트에는 기본 배치가 없으므로 아래 modifier 클래스 중 하나를 추가해야 합니다.

  • .offcanvas-start는 offcanvas를 뷰포트 왼쪽에 배치합니다(위에서 보임)
  • .offcanvas-end는 offcanvas를 뷰포트 오른쪽에 배치합니다
  • .offcanvas-top는 offcanvas를 뷰포트 위쪽에 배치합니다
  • .offcanvas-bottom은 offcanvas를 뷰포트 아래쪽에 배치합니다

아래에서 top, right, bottom 예시를 사용해 보세요.

<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasTop" aria-controls="offcanvasTop">Toggle top offcanvas</button>

<div class="offcanvas offcanvas-top" tabindex="-1" id="offcanvasTop" aria-labelledby="offcanvasTopLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasTopLabel">Offcanvas top</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    ...
  </div>
</div>
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasRight" aria-controls="offcanvasRight">Toggle right offcanvas</button>

<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasRight" aria-labelledby="offcanvasRightLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasRightLabel">Offcanvas right</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    ...
  </div>
</div>
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasBottom" aria-controls="offcanvasBottom">Toggle bottom offcanvas</button>

<div class="offcanvas offcanvas-bottom" tabindex="-1" id="offcanvasBottom" aria-labelledby="offcanvasBottomLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="offcanvasBottomLabel">Offcanvas bottom</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body small">
    ...
  </div>
</div>

접근성 (Accessibility)

offcanvas 패널은 개념적으로 modal 대화상자이므로 .offcanvas에 offcanvas 제목을 가리키는 aria-labelledby="..."를 추가해야 합니다. role="dialog"는 JavaScript로 이미 추가하므로 따로 추가할 필요는 없습니다.

CSS

변수 (Variables)

v5.2.0에서 추가됨

Bootstrap의 진화하는 CSS 변수 접근 방식의 일부로, offcanvas는 이제 향상된 실시간 커스터마이즈를 위해 .offcanvas에 로컬 CSS 변수를 사용합니다. CSS 변수의 값은 Sass로 설정되므로 Sass 커스터마이즈도 여전히 지원됩니다.

--#{$prefix}offcanvas-zindex: #{$zindex-offcanvas};
--#{$prefix}offcanvas-width: #{$offcanvas-horizontal-width};
--#{$prefix}offcanvas-height: #{$offcanvas-vertical-height};
--#{$prefix}offcanvas-padding-x: #{$offcanvas-padding-x};
--#{$prefix}offcanvas-padding-y: #{$offcanvas-padding-y};
--#{$prefix}offcanvas-color: #{$offcanvas-color};
--#{$prefix}offcanvas-bg: #{$offcanvas-bg-color};
--#{$prefix}offcanvas-border-width: #{$offcanvas-border-width};
--#{$prefix}offcanvas-border-color: #{$offcanvas-border-color};
--#{$prefix}offcanvas-box-shadow: #{$offcanvas-box-shadow};
--#{$prefix}offcanvas-transition: #{transform $offcanvas-transition-duration ease-in-out};
--#{$prefix}offcanvas-title-line-height: #{$offcanvas-title-line-height};

Sass 변수

$offcanvas-padding-y:               $modal-inner-padding;
$offcanvas-padding-x:               $modal-inner-padding;
$offcanvas-horizontal-width:        400px;
$offcanvas-vertical-height:         30vh;
$offcanvas-transition-duration:     .3s;
$offcanvas-border-color:            $modal-content-border-color;
$offcanvas-border-width:            $modal-content-border-width;
$offcanvas-title-line-height:       $modal-title-line-height;
$offcanvas-bg-color:                var(--#{$prefix}body-bg);
$offcanvas-color:                   var(--#{$prefix}body-color);
$offcanvas-box-shadow:              $modal-content-box-shadow-xs;
$offcanvas-backdrop-bg:             $modal-backdrop-bg;
$offcanvas-backdrop-opacity:        $modal-backdrop-opacity;

사용법 (Usage)

offcanvas 플러그인은 무거운 작업을 처리하기 위해 몇 가지 클래스와 속성을 활용합니다:

  • .offcanvas는 콘텐츠를 숨깁니다
  • .offcanvas.show는 콘텐츠를 표시합니다
  • .offcanvas-start는 offcanvas를 왼쪽에 숨깁니다
  • .offcanvas-end는 offcanvas를 오른쪽에 숨깁니다
  • .offcanvas-top는 offcanvas를 위쪽에 숨깁니다
  • .offcanvas-bottom은 offcanvas를 아래쪽에 숨깁니다

JavaScript 기능을 트리거하는 data-bs-dismiss="offcanvas" 속성으로 닫기 버튼을 추가하세요. 모든 기기에서 올바르게 동작하려면 <button> 요소를 사용해야 합니다.

data 속성으로 (Via data attributes)

Toggle

자동으로 하나의 offcanvas 요소의 제어를 할당하려면 요소에 data-bs-toggle="offcanvas"와 data-bs-target 또는 href를 추가하세요. data-bs-target 속성은 offcanvas를 적용할 CSS selector를 받습니다. offcanvas 요소에 offcanvas 클래스를 추가해야 합니다. 기본으로 열어두려면 show 클래스를 추가하세요.

Dismiss

닫기는 아래처럼 offcanvas 안의 버튼에 data-bs-dismiss 속성을 사용해 할 수 있습니다:

<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>

또는 아래처럼 추가 data-bs-target을 사용해 offcanvas 밖의 버튼에서도 할 수 있습니다:

<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#my-offcanvas" aria-label="Close"></button>

offcanvas를 닫는 두 방법 모두 지원되지만, offcanvas 밖에서 닫는 것은 ARIA Authoring Practices Guide의 dialog(modal) 패턴과 일치하지 않는다는 점을 기억하세요. 위험을 감수하고 사용하세요.

JavaScript로 (Via JavaScript)

수동으로 활성화하려면:

const offcanvasElementList = document.querySelectorAll('.offcanvas')
const offcanvasList = [...offcanvasElementList].map(offcanvasEl => new bootstrap.Offcanvas(offcanvasEl))

옵션 (Options)

옵션은 data 속성이나 JavaScript로 전달할 수 있으므로, data-bs-animation="{value}"처럼 data-bs-에 옵션 이름을 붙일 수 있습니다. data 속성으로 옵션을 전달할 때는 옵션 이름의 대소문자 형태를 "camelCase"에서 "kebab-case"로 바꿔야 합니다. 예를 들어 data-bs-customClass="beautifier" 대신 data-bs-custom-class="beautifier"를 사용하세요.

Bootstrap 5.2.0부터 모든 컴포넌트는 JSON 문자열로 간단한 컴포넌트 설정을 담을 수 있는 실험적인 예약 data 속성 data-bs-config를 지원합니다. 요소에 data-bs-config='{"delay":0, "title":123}'과 data-bs-title="456" 속성이 있으면 최종 title 값은 456이 되고, 별도의 data 속성이 data-bs-config에 주어진 값을 덮어씁니다. 또한 기존 data 속성도 data-bs-delay='{"show":0,"hide":150}'처럼 JSON 값을 담을 수 있습니다.

최종 설정 객체는 data-bs-config, data-bs-, js object를 병합한 결과이며, 가장 마지막에 주어진 키-값이 나머지를 덮어씁니다.

이름 타입 기본값 설명
backdrop boolean 또는 string static true offcanvas가 열려 있는 동안 body에 backdrop을 적용합니다. 또는 클릭해도 offcanvas가 닫히지 않는 backdrop을 원하면 static을 지정하세요.
keyboard boolean true escape 키를 누르면 offcanvas를 닫습니다.
scroll boolean false offcanvas가 열려 있는 동안 body 스크롤을 허용합니다.

메서드 (Methods)

모든 API 메서드는 비동기이며 전환을 시작합니다. 전환이 시작되는 즉시 호출자에게 반환되지만, 끝나기 전에 반환됩니다. 또한 전환 중인 컴포넌트에 대한 메서드 호출은 무시됩니다. JavaScript 문서에서 자세히 알아보세요.

콘텐츠를 offcanvas 요소로 활성화합니다. 선택적 options object를 받습니다.

생성자를 사용해 offcanvas 인스턴스를 만들 수 있습니다. 예를 들어:

const bsOffcanvas = new bootstrap.Offcanvas('#myOffcanvas')
메서드 설명
dispose 요소의 offcanvas를 파괴합니다.
getInstance DOM 요소와 연결된 offcanvas 인스턴스를 가져올 수 있게 해 주는 정적 메서드입니다.
getOrCreateInstance DOM 요소와 연결된 offcanvas 인스턴스를 가져오거나, 초기화되지 않은 경우 새로 만드는 정적 메서드입니다.
hide offcanvas 요소를 숨깁니다. offcanvas 요소가 실제로 숨겨지기 전에(hidden.bs.offcanvas 이벤트 전에) 호출자에게 반환합니다.
show offcanvas 요소를 표시합니다. offcanvas 요소가 실제로 표시되기 전에(shown.bs.offcanvas 이벤트 전에) 호출자에게 반환합니다.
toggle offcanvas 요소를 표시하거나 숨깁니다. offcanvas 요소가 실제로 표시되거나 숨겨지기 전에(shown.bs.offcanvas 또는 hidden.bs.offcanvas 이벤트 전에) 호출자에게 반환합니다.

이벤트 (Events)

Bootstrap의 offcanvas 클래스는 offcanvas 기능에 연결하기 위한 몇 가지 이벤트를 노출합니다.

이벤트 타입 설명
hide.bs.offcanvas hide 메서드가 호출될 때 즉시 발생하는 이벤트입니다.
hidden.bs.offcanvas offcanvas 요소가 사용자에게 숨겨졌을 때 발생하는 이벤트입니다(CSS 전환이 완료될 때까지 기다립니다).
hidePrevented.bs.offcanvas offcanvas가 표시되고 backdrop이 static인 상태에서 offcanvas 바깥을 클릭할 때 발생하는 이벤트입니다. 또한 escape 키가 눌리고 keyboard 옵션이 false로 설정된 경우에도 발생합니다.
show.bs.offcanvas show 인스턴스 메서드가 호출될 때 즉시 발생하는 이벤트입니다.
shown.bs.offcanvas offcanvas 요소가 사용자에게 보이게 되었을 때 발생하는 이벤트입니다(CSS 전환이 완료될 때까지 기다립니다).
const myOffcanvas = document.getElementById('myOffcanvas')
myOffcanvas.addEventListener('hidden.bs.offcanvas', event => {
  // do something...
})

더 알아보기 (Learn more)