내용으로 건너뛰기 문서 내비게이션으로 건너뛰기
// Modal

Bootstrap JavaScript 모달 플러그인을 사용하여 라이트박스, 사용자 알림 또는 사용자 정의 콘텐츠를 만들 수 있습니다.

작동 원리

모달 컴포넌트의 메뉴 옵션이 최근 변경되었으니 사용하기 전에 아래 내용을 꼭 읽어보시기 바랍니다.

  • 모달은 HTML, CSS, 그리고 JavaScript로 빌드됩니다. 모달은 문서 내의 다른 모든 것 위에 배치되어 <body>의 스크롤을 제거하고 모달의 콘텐츠가 스크롤 되도록 합니다.
  • 모달의 “배경” 을 클릭하면 자동으로 모달이 닫힙니다.
  • Bootstrap은 한번에 하나의 모달을 지원합니다. 중첩된 모달은 지원되지 않습니다.
  • 모달은 position: fixed를 사용합니다. 가능한 다른 요소와의 간섭을 피하기 위해, 모달 HTML을 최상단의 위치에 넣어 주세요. 다른 고정 요소안에 .modal을 중첩해 넣으면 문제가 발생할 가능성이 높습니다.
  • 다시 한번 말씀드리지만, position: fixed 때문에 모바일 기기에서 모달을 사용할 때 주의할 사항이 몇가지 있습니다. 자세한 내용은 browser support docs를 참조해 주십시오.
  • HTML5가 시멘틱하게 정의하는 방법 때문에, autofocus HTML 속성은 Bootstrap 모달에 영향을 줄 수 없습니다. 같은 효과를 얻으려면 몇개의 사용자 정의 JavaScript를 사용해 주십시오:
var myModal = document.getElementById('myModal')
var myInput = document.getElementById('myInput')

myModal.addEventListener('shown.bs.modal', function () {
  myInput.focus()
})
이 컴포넌트의 애니메이션 효과는 prefers-reduced-motion 미디어 쿼리에 따라 다릅니다. 접근성 문서의 모션 감소 문단을 참고하세요.

데모와 사용 가이드를 계속해서 읽어 주세요.

예시

모달 컴포넌트

아래는 static 모달의 예입니다. (즉, positiondisplay가 오버라이드되는 것을 의미합니다) 여기에는 모달 header, 모달 body (padding 때문에 필요), 모달 footer (선택)가 포함되어 있습니다. 가능한 한 모달을 닫을 수 있는 것을 포함시키거나 닫을 수 있는 다른 명시적인 요소를 제공하도록 부탁드립니다.

<div class="modal" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Modal title</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <p>Modal body text goes here.</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

라이브 데모

아래 버튼을 눌러 보세요. 모달 화면이 위에서 아래로 나타납니다.

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
  Launch demo modal
</button>

<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

정적 백드롭

백드롭을 static으로 설정하면, 배경을 클릭해도 모달은 닫히지 않습니다. 아래 버튼을 클릭해 시도해 보세요.

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#staticBackdrop">
  Launch static backdrop modal
</button>

<!-- Modal -->
<div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="staticBackdropLabel">Modal title</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Understood</button>
      </div>
    </div>
  </div>
</div>

기다란 콘텐츠 스크롤

사용자의 뷰포트나 기기가 너무 길면 모달 페이지가 자체적으로 스크롤을 생성합니다. 아래 버튼을 클릭해 시도해 보십시오.

또한 .modal-dialog.modal-dialog-scrollable를 추가하는 것으로, 모달 본체를 스크롤할 수 있는 스크롤 가능한 모달로 만들 수 있습니다.

<!-- Scrollable modal -->
<div class="modal-dialog modal-dialog-scrollable">
  ...
</div>

세로 중앙

모달을 중앙에 배치하기 위해서 .modal-dialog.modal-dialog-centered를 추가합니다.

<!-- Vertically centered modal -->
<div class="modal-dialog modal-dialog-centered">
  ...
</div>

<!-- Vertically centered scrollable modal -->
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
  ...
</div>

툴팁과 팝오버

툴팁팝오버는 필요에 따라 모달 안에 배치시킬 수 있습니다. 모달이 닫히면 그 안에 있는 툴팁이나 팝오버도 자동으로 삭제됩니다.

<div class="modal-body">
  <h5>Popover in a modal</h5>
  <p>This <a href="#" role="button" class="btn btn-secondary popover-test" title="Popover title" data-bs-content="Popover body content is set in this attribute.">button</a> triggers a popover on click.</p>
  <hr>
  <h5>Tooltips in a modal</h5>
  <p><a href="#" class="tooltip-test" title="Tooltip">This link</a> and <a href="#" class="tooltip-test" title="Tooltip">that link</a> have tooltips on hover.</p>
</div>

그리드 사용하기

.modal-body 안에 .container-fluid를 중첩시켜 모달 안에 Bootstrap 그리드 시스템을 이용할 수 있습니다. 다른 곳에서 사용하듯이 일반적인 그리드 시스템 클래스를 사용합니다.

<div class="modal-body">
  <div class="container-fluid">
    <div class="row">
      <div class="col-md-4">.col-md-4</div>
      <div class="col-md-4 ms-auto">.col-md-4 .ms-auto</div>
    </div>
    <div class="row">
      <div class="col-md-3 ms-auto">.col-md-3 .ms-auto</div>
      <div class="col-md-2 ms-auto">.col-md-2 .ms-auto</div>
    </div>
    <div class="row">
      <div class="col-md-6 ms-auto">.col-md-6 .ms-auto</div>
    </div>
    <div class="row">
      <div class="col-sm-9">
        Level 1: .col-sm-9
        <div class="row">
          <div class="col-8 col-sm-6">
            Level 2: .col-8 .col-sm-6
          </div>
          <div class="col-4 col-sm-6">
            Level 2: .col-4 .col-sm-6
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

다양한 모달 콘텐츠

같은 모달을 트리거하는 버튼들이 있는데, 그것들이 미묘하게 다른 내용의 모달을 트리거하고 있나요? event.relatedTargetHTML data-bs-* attributes를 사용하여 어떤 버튼이 클릭 되었는지에 따라 모달의 내용을 변화시킬 수 있습니다.

다음은 HTML과 JavaScript의 예시를 넣은 라이브 데모입니다. relatedTarget의 자세한 내용은 read the modal events docs를 참조해 주세요.

<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo">Open modal for @mdo</button>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">Open modal for @fat</button>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@getbootstrap">Open modal for @getbootstrap</button>

<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">New message</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <form>
          <div class="mb-3">
            <label for="recipient-name" class="col-form-label">Recipient:</label>
            <input type="text" class="form-control" id="recipient-name">
          </div>
          <div class="mb-3">
            <label for="message-text" class="col-form-label">Message:</label>
            <textarea class="form-control" id="message-text"></textarea>
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Send message</button>
      </div>
    </div>
  </div>
</div>
var exampleModal = document.getElementById('exampleModal')
exampleModal.addEventListener('show.bs.modal', function (event) {
  // Button that triggered the modal
  var button = event.relatedTarget
  // Extract info from data-bs-* attributes
  var recipient = button.getAttribute('data-bs-whatever')
  // If necessary, you could initiate an AJAX request here
  // and then do the updating in a callback.
  //
  // Update the modal's content.
  var modalTitle = exampleModal.querySelector('.modal-title')
  var modalBodyInput = exampleModal.querySelector('.modal-body input')

  modalTitle.textContent = 'New message to ' + recipient
  modalBodyInput.value = recipient
})

모달 간 토글

data-bs-targetdata-bs-toggle 속성을 교묘하게 배치함으로써 여러 모달을 토글할 수 있습니다. 예를 들어 이미 열려있는 로그인 모달에서 비밀번호 재설정의 모달을 열수 있습니다. 여러 개의 모달을 동시에 열 수 없으므로 주의해 주세요. 이 방법으로 손쉽게 두 개의 다른 모달을 표시할 수 있습니다.

Open first modal
<div class="modal fade" id="exampleModalToggle" aria-hidden="true" aria-labelledby="exampleModalToggleLabel" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalToggleLabel">Modal 1</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        Show a second modal and hide this one with the button below.
      </div>
      <div class="modal-footer">
        <button class="btn btn-primary" data-bs-target="#exampleModalToggle2" data-bs-toggle="modal" data-bs-dismiss="modal">Open second modal</button>
      </div>
    </div>
  </div>
</div>
<div class="modal fade" id="exampleModalToggle2" aria-hidden="true" aria-labelledby="exampleModalToggleLabel2" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalToggleLabel2">Modal 2</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        Hide this modal and show the first with the button below.
      </div>
      <div class="modal-footer">
        <button class="btn btn-primary" data-bs-target="#exampleModalToggle" data-bs-toggle="modal">Back to first</button>
      </div>
    </div>
  </div>
</div>
<a class="btn btn-primary" data-bs-toggle="modal" href="#exampleModalToggle" role="button">Open first modal</a>

애니메이션 변경

$modal-fade-transform 변수는 모달 페이드인 애니메이션 이전 .modal-dialog의 전환 상태를 결정하고, $modal-show-transform 변수는 모달 페이드인 애니메이션 종료시 .modal-dialog의 전환 상태를 결정합니다.

예를 들어, zoom-in애니메이션을 만들고 싶다면 $modal-fade-transform: scale(.8)을 설정합니다.

애니메이션 제거

화면에 페이드인 하는 것이 아니라 단순히 표시만 하는 경우에는, 마크업에서 .fade 클래스를 삭제합니다.

<div class="modal" tabindex="-1" aria-labelledby="..." aria-hidden="true">
  ...
</div>

동적 높이

모달이 열려있는데 높이가 변경된 경우에는 스크롤바가 표시되었을 때 모달의 위치를 재조정하기 위해 myModal.handleUpdate()를 호출해야 합니다.

접근성

반드시 .modal에 모달 타이틀을 참조하는 aria-labelledby="..."를 추가해 주세요. 게다가 .modalaria-describedby를 추가하는 것으로, 모달 다이얼로그의 설명을 줄 수 있습니다. JavaScript로 이미 추가하고 있음으로 role="dialog"를 추가할 필요가 없다는 점에 주의해 주세요.

YouTube 동영상 포함시키키

YouTube 동영상을 모달에 포함시키려면, Bootstrap에는 없는 JavaScript를 추가해 자동으로 재생을 정지하는 등의 처리가 필요합니다. 자세한 내용은 도움이 되는 Stack Overflow 글을 참조해 주세요.

선택적 크기

모달에는 3개의 옵션 크기가 있어, 제어자 클래스를 통해 .modal-dialog로 배치할 수 있습니다. 이들 크기는 좁은 뷰포트에서의 가로 스크롤 바를 피하기 위해 특정 중단점에서 유효하게 됩니다.

Size Class Modal max-width
Small .modal-sm 300px
Default None 500px
Large .modal-lg 800px
Extra large .modal-xl 1140px

제어자 클래스를 가지고 있지 않은 기본 모달은, “medium” 크기의 모달로 보여집니다.

<div class="modal-dialog modal-xl">...</div>
<div class="modal-dialog modal-lg">...</div>
<div class="modal-dialog modal-sm">...</div>

전체화면 모달

.modal-dialog에는 아래와 같은 클래스를 추가하는 것으로, 화면을 꽉채운 모달을 이용할 수 있습니다.

Class Availability
.modal-fullscreen Always
.modal-fullscreen-sm-down Below 576px
.modal-fullscreen-md-down Below 768px
.modal-fullscreen-lg-down Below 992px
.modal-fullscreen-xl-down Below 1200px
.modal-fullscreen-xxl-down Below 1400px
<!-- Full screen modal -->
<div class="modal-dialog modal-fullscreen-sm-down">
  ...
</div>

Sass

변수

$modal-inner-padding:               $spacer;

$modal-footer-margin-between:       .5rem;

$modal-dialog-margin:               .5rem;
$modal-dialog-margin-y-sm-up:       1.75rem;

$modal-title-line-height:           $line-height-base;

$modal-content-color:               null;
$modal-content-bg:                  $white;
$modal-content-border-color:        rgba($black, .2);
$modal-content-border-width:        $border-width;
$modal-content-border-radius:       $border-radius-lg;
$modal-content-inner-border-radius: subtract($modal-content-border-radius, $modal-content-border-width);
$modal-content-box-shadow-xs:       $box-shadow-sm;
$modal-content-box-shadow-sm-up:    $box-shadow;

$modal-backdrop-bg:                 $black;
$modal-backdrop-opacity:            .5;
$modal-header-border-color:         $border-color;
$modal-footer-border-color:         $modal-header-border-color;
$modal-header-border-width:         $modal-content-border-width;
$modal-footer-border-width:         $modal-header-border-width;
$modal-header-padding-y:            $modal-inner-padding;
$modal-header-padding-x:            $modal-inner-padding;
$modal-header-padding:              $modal-header-padding-y $modal-header-padding-x; // Keep this for backwards compatibility

$modal-sm:                          300px;
$modal-md:                          500px;
$modal-lg:                          800px;
$modal-xl:                          1140px;

$modal-fade-transform:              translate(0, -50px);
$modal-show-transform:              none;
$modal-transition:                  transform .3s ease-out;
$modal-scale-transform:             scale(1.02);

루프

Responsive fullscreen modals$breakpoints 맵과 scss/_modal.scss내의 반복에 의해 생성됩니다.

@each $breakpoint in map-keys($grid-breakpoints) {
  $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
  $postfix: if($infix != "", $infix + "-down", "");

  @include media-breakpoint-down($breakpoint) {
    .modal-fullscreen#{$postfix} {
      width: 100vw;
      max-width: none;
      height: 100%;
      margin: 0;

      .modal-content {
        height: 100%;
        border: 0;
        @include border-radius(0);
      }

      .modal-header {
        @include border-radius(0);
      }

      .modal-body {
        overflow-y: auto;
      }

      .modal-footer {
        @include border-radius(0);
      }
    }
  }
}

사용 방법

모달 플러그인은, data 속성이나 JavaScript를 사용하고, 필요에 따라 숨겨서 콘텐츠를 바꿉니다. 또한 기본 스크롤 동작을 덮어쓰고 모달의 바깥쪽을 클릭했을 때 표시된 모달을 삭제하기 위한 클릭 영역을 제공하기 위해서 .modal-backdrop을 생성합니다.

데이터 속성 사용하기

토글

JavaScript를 쓰지 않고 모달을 활성화 시킵니다. 버튼과 같은 컨트롤러 요소에 data-bs-toggle="modal"을 설정하고, 추가로 data-bs-target="#foo" 또는 href="#foo"를 지정하고, 토글하는 특정 모달을 타깃으로 합니다.

<button type="button" data-bs-toggle="modal" data-bs-target="#myModal">Launch modal</button>

해제

해제는 아래와 같이 modal 내에서 버튼의 data 속성을 사용하여 수행할 수 있습니다.

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

또는 아래와 같이 data-bs-target을 사용하여 modal 외부의 버튼에서도 수행할 수 있습니다:

<button type="button" class="btn-close" data-bs-dismiss="modal" data-bs-target="#my-modal" aria-label="Close"></button>
모달을 해제하는 두 가지 방법을 모두 지원하지만 모달 외부에서 해제하는 것은 WAI-ARIA 모달 대화 디자인 패턴과 일치하지 않습니다. 문제가 생길 수도 있다는 점에 주의하세요.

JavaScript 사용하기

JavaScript 한 줄로 모달을 생성합니다:

var myModal = new bootstrap.Modal(document.getElementById('myModal'), options)

옵션

옵션은 data 속성 또는 JavaScript로 줄 수 있습니다. data 속성의 경우는 data-bs-backdrop=""처럼 data-bs-에 옵션명을 추가합니다.

Name Type Default Description
backdrop boolean or the string 'static' true modal-backdrop 요소를 포함합니다. 다른 방법으로서 배경 클릭시 모달을 닫지 않으려면 static 을 지정합니다.
keyboard boolean true escape key 를 누르면 모달을 닫습니다.
focus boolean true 초기화시에 모달에 포커스를 맞춥니다.

메소드

비동기 메서드 및 트렌지션

모든 API 메서드는 비동기이며 트렌지션을 시작합니다. 트렌지션은 시작되자마자 끝나기 전에 호출자에게 돌아갑니다. 또한 트렌지션 컴포넌트에 대한 메서드 호출은 무시됩니다.

자세한 내용은 JavaScript 문서를 참고하세요.

옵션 전달

모달로서 콘텐츠를 활성화합니다. 옵션의 object를 받습니다.

var myModal = new bootstrap.Modal(document.getElementById('myModal'), {
  keyboard: false
})

toggle

모달을 수동으로 바꿉니다. 모달이 실제로 표시 또는 숨기기 전에 호출한 곳으로 돌아갑니다 (즉, shown.bs.modal 또는 hidden.bs.modal 이벤트가 발생하기 전).

myModal.toggle()

show

모달을 수동으로 엽니다. 모달이 실제로 표시되기 전에 호출한 곳으로 돌아갑니다 (즉, shown.bs.modal 이벤트가 발생하기 전).

myModal.show()

또한, 모달 이벤트로 받을 수 있는 DOM 요소를 인수로 건네줄 수도 있습니다.(relatedTarget 속성으로서).

var modalToggle = document.getElementById('toggleMyModal') // relatedTarget
myModal.show(modalToggle)

hide

수동으로 모달을 숨깁니다. 모달이 실제로 숨겨지기 전에 호출한 곳으로 돌아갑니다 (즉, hidden.bs.modal 이벤트가 발생하기 전).

myModal.hide()

handleUpdate

열려 있는 동안에 모달의 높이가 바뀌었을 경우, 모달의 위치를 수동으로 재조정합니다 (즉, 스크롤 바가 표시되어 있는 경우 등).

myModal.handleUpdate()

dispose

모달의 요소를 없앱니다.(DOM 요소에 저장되어 있는 데이터를 삭제합니다)

myModal.dispose()

getInstance

DOM 요소와 연관된 모달 인스턴스를 취득하는 Static 메소드 입니다.

var myModalEl = document.getElementById('myModal')
var modal = bootstrap.Modal.getInstance(myModalEl) // Returns a Bootstrap modal instance

getOrCreateInstance

Static method which allows you to get the modal instance associated with a DOM element, or create a new one in case it wasn’t initialized

var myModalEl = document.querySelector('#myModal')
var modal = bootstrap.Modal.getOrCreateInstance(myModalEl) // Returns a Bootstrap modal instance

이벤트

Bootstrap의 모달 클래스는 모달 기능으로 연결하기 위한 몇 가지 이벤트를 공개하고 있습니다. 모든 모달 이벤트는, 모달 자체(즉, <div class="modal">)에서 발생합니다.

Event type Description
show.bs.modal 이 이벤트는 show 인스턴스/메소드가 불렸을 때 바로 발생합니다. 클릭으로 인해 발생했을 때 클릭된 요소는 이벤트의 relatedTarget 속성으로 이용 가능합니다.
shown.bs.modal 이 이벤트는 모달이 사용자에게 표시될 때 발생합니다.(CSS 트랜지션이 완료되기를 기다립니다) 클릭이 원인인 경우, 클릭된 요소는 이벤트의 relatedTarget 속성으로 이용 가능합니다.
hide.bs.modal 이 이벤트는 hide 인스턴스/메소드가 불렸을 때 바로 발생합니다.
hidden.bs.modal 이 이벤트는 모달을 숨길 때 발생합니다.(CSS 트랜지션이 완료되기를 기다립니다).
hidePrevented.bs.modal 이 이벤트는 모달이 표시되고 그 배경이 static이고, 키보드 옵션 또는 data-bs-keyboardfalse로 설정되어 있는 상태에서 모달 바깥쪽 클릭이나 escape key를 누루면 됩니다.
var myModalEl = document.getElementById('myModal')
myModalEl.addEventListener('hidden.bs.modal', function (event) {
  // do something...
})