작동 원리
모달 컴포넌트의 메뉴 옵션이 최근 변경되었으니 사용하기 전에 아래 내용을 꼭 읽어보시기 바랍니다.
- 모달은 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 모달의 예입니다. (즉, position
과 display
가 오버라이드되는 것을 의미합니다) 여기에는 모달 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.relatedTarget
과 HTML data-bs-*
속성를 사용하여 어떤 버튼이 클릭 되었는지에 따라 모달의 내용을 변화시킬 수 있습니다.
다음은 HTML과 JavaScript의 예시가 포함된 라이브 데모입니다. relatedTarget
의 자세한 내용은 모달 이벤트 문서를 참조해 주세요.
<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-target
과 data-bs-toggle
속성을 교묘하게 배치함으로써 여러 모달을 토글할 수 있습니다. 예를 들어 이미 열려있는 로그인 모달에서 비밀번호 재설정의 모달을 열수 있습니다. 여러 개의 모달을 동시에 열 수 없으므로 주의해 주세요. 이 방법으로 손쉽게 두 개의 다른 모달을 표시할 수 있습니다.
<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">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="..."
를 추가해 주세요. 게다가 .modal
에 aria-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);
루프
반응형 전체화면 모달은 $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>
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 메서드는 비동기이며 트렌지션을 시작합니다. 트렌지션은 시작되자마자 끝나기 전에 호출자에게 돌아갑니다. 또한 트렌지션 컴포넌트에 대한 메서드 호출은 무시됩니다.
옵션 전달
모달로서 콘텐츠를 활성화합니다. 옵션의 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-keyboard 가 false 로 설정되어 있는 상태에서 모달 바깥쪽 클릭이나 escape key를 누루면 됩니다. |
var myModalEl = document.getElementById('myModal')
myModalEl.addEventListener('hidden.bs.modal', function (event) {
// do something...
})