mirror of
https://github.com/twbs/bootstrap.git
synced 2025-02-06 04:08:22 +01:00
Scrollable modal (#27769)
This commit is contained in:
parent
41f85b64bf
commit
de0bb1e052
@ -51,6 +51,7 @@ const Event = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ClassName = {
|
const ClassName = {
|
||||||
|
SCROLLABLE : 'modal-dialog-scrollable',
|
||||||
SCROLLBAR_MEASURER : 'modal-scrollbar-measure',
|
SCROLLBAR_MEASURER : 'modal-scrollbar-measure',
|
||||||
BACKDROP : 'modal-backdrop',
|
BACKDROP : 'modal-backdrop',
|
||||||
OPEN : 'modal-open',
|
OPEN : 'modal-open',
|
||||||
@ -60,6 +61,7 @@ const ClassName = {
|
|||||||
|
|
||||||
const Selector = {
|
const Selector = {
|
||||||
DIALOG : '.modal-dialog',
|
DIALOG : '.modal-dialog',
|
||||||
|
MODAL_BODY : '.modal-body',
|
||||||
DATA_TOGGLE : '[data-toggle="modal"]',
|
DATA_TOGGLE : '[data-toggle="modal"]',
|
||||||
DATA_DISMISS : '[data-dismiss="modal"]',
|
DATA_DISMISS : '[data-dismiss="modal"]',
|
||||||
FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',
|
FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',
|
||||||
@ -244,7 +246,12 @@ class Modal {
|
|||||||
this._element.style.display = 'block'
|
this._element.style.display = 'block'
|
||||||
this._element.removeAttribute('aria-hidden')
|
this._element.removeAttribute('aria-hidden')
|
||||||
this._element.setAttribute('aria-modal', true)
|
this._element.setAttribute('aria-modal', true)
|
||||||
|
|
||||||
|
if ($(this._dialog).hasClass(ClassName.SCROLLABLE)) {
|
||||||
|
this._dialog.querySelector(Selector.MODAL_BODY).scrollTop = 0
|
||||||
|
} else {
|
||||||
this._element.scrollTop = 0
|
this._element.scrollTop = 0
|
||||||
|
}
|
||||||
|
|
||||||
if (transition) {
|
if (transition) {
|
||||||
Util.reflow(this._element)
|
Util.reflow(this._element)
|
||||||
|
@ -790,4 +790,31 @@ $(function () {
|
|||||||
})
|
})
|
||||||
.bootstrapModal('show')
|
.bootstrapModal('show')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
QUnit.test('should scroll to top of the modal body if the modal has .modal-dialog-scrollable class', function (assert) {
|
||||||
|
assert.expect(2)
|
||||||
|
var done = assert.async()
|
||||||
|
|
||||||
|
var $modal = $([
|
||||||
|
'<div id="modal-test">',
|
||||||
|
' <div class="modal-dialog modal-dialog-scrollable">',
|
||||||
|
' <div class="modal-content">',
|
||||||
|
' <div class="modal-body" style="height: 100px; overflow-y: auto;">',
|
||||||
|
' <div style="height: 200px" />',
|
||||||
|
' </div>',
|
||||||
|
' </div>',
|
||||||
|
' </div>',
|
||||||
|
'</div>'
|
||||||
|
].join('')).appendTo('#qunit-fixture')
|
||||||
|
|
||||||
|
var $modalBody = $('.modal-body')
|
||||||
|
$modalBody.scrollTop(100)
|
||||||
|
assert.strictEqual($modalBody.scrollTop(), 100)
|
||||||
|
|
||||||
|
$modal.on('shown.bs.modal', function () {
|
||||||
|
assert.strictEqual($modalBody.scrollTop(), 0, 'modal body scrollTop should be 0 when opened')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
.bootstrapModal('show')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -50,17 +50,51 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-dialog-scrollable {
|
||||||
|
display: flex; // IE10/11
|
||||||
|
max-height: calc(100% - #{$modal-dialog-margin * 2});
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
max-height: calc(100vh - #{$modal-dialog-margin * 2}); // IE10/11
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header,
|
||||||
|
.modal-footer {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.modal-dialog-centered {
|
.modal-dialog-centered {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
min-height: calc(100% - (#{$modal-dialog-margin} * 2));
|
min-height: calc(100% - #{$modal-dialog-margin * 2});
|
||||||
|
|
||||||
// Ensure `modal-dialog-centered` extends the full height of the view (IE10/11)
|
// Ensure `modal-dialog-centered` extends the full height of the view (IE10/11)
|
||||||
&::before {
|
&::before {
|
||||||
display: block; // IE10
|
display: block; // IE10
|
||||||
height: calc(100vh - (#{$modal-dialog-margin} * 2));
|
height: calc(100vh - #{$modal-dialog-margin * 2});
|
||||||
content: "";
|
content: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure `.modal-body` shows scrollbar (IE10/11)
|
||||||
|
&.modal-dialog-scrollable {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actual modal
|
// Actual modal
|
||||||
@ -159,11 +193,19 @@
|
|||||||
margin: $modal-dialog-margin-y-sm-up auto;
|
margin: $modal-dialog-margin-y-sm-up auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-dialog-scrollable {
|
||||||
|
max-height: calc(100% - #{$modal-dialog-margin-y-sm-up * 2});
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
max-height: calc(100vh - #{$modal-dialog-margin-y-sm-up * 2});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.modal-dialog-centered {
|
.modal-dialog-centered {
|
||||||
min-height: calc(100% - (#{$modal-dialog-margin-y-sm-up} * 2));
|
min-height: calc(100% - #{$modal-dialog-margin-y-sm-up * 2});
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
height: calc(100vh - (#{$modal-dialog-margin-y-sm-up} * 2));
|
height: calc(100vh - #{$modal-dialog-margin-y-sm-up * 2});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,6 +210,79 @@ When modals become too long for the user's viewport or device, they scroll indep
|
|||||||
</div>
|
</div>
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
|
You can also create a scrollable modal that allows scroll the modal body by adding `.modal-dialog-scrollable` to `.modal-dialog`.
|
||||||
|
|
||||||
|
<div id="exampleModalScrollable" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="exampleModalScrollableTitle" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="exampleModalScrollableTitle">Modal title</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
|
||||||
|
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
|
||||||
|
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
|
||||||
|
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
|
||||||
|
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
|
||||||
|
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
|
||||||
|
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
|
||||||
|
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
|
||||||
|
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
|
||||||
|
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
|
||||||
|
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
|
||||||
|
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
|
||||||
|
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
|
||||||
|
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
|
||||||
|
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
|
||||||
|
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
|
||||||
|
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
|
||||||
|
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
<button type="button" class="btn btn-primary">Save changes</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bd-example">
|
||||||
|
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalScrollable">
|
||||||
|
Launch demo modal
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% highlight html %}
|
||||||
|
<!-- Button trigger modal -->
|
||||||
|
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalScrollable">
|
||||||
|
Launch demo modal
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" id="exampleModalScrollable" tabindex="-1" role="dialog" aria-labelledby="exampleModalScrollableTitle" aria-hidden="true">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="exampleModalScrollableTitle">Modal title</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
...
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
<button type="button" class="btn btn-primary">Save changes</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
### Vertically centered
|
### Vertically centered
|
||||||
|
|
||||||
Add `.modal-dialog-centered` to `.modal-dialog` to vertically center the modal.
|
Add `.modal-dialog-centered` to `.modal-dialog` to vertically center the modal.
|
||||||
@ -234,9 +307,36 @@ Add `.modal-dialog-centered` to `.modal-dialog` to vertically center the modal.
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="exampleModalCenteredScrollable" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenteredScrollableTitle" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="exampleModalCenteredScrollableTitle">Modal title</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
|
||||||
|
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
|
||||||
|
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
|
||||||
|
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
|
||||||
|
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||||
|
<button type="button" class="btn btn-primary">Save changes</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="bd-example">
|
<div class="bd-example">
|
||||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalCenter">
|
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalCenter">
|
||||||
Launch demo modal
|
Vertically centered modal
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalCenteredScrollable">
|
||||||
|
Vertically centered scrollable modal
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user