When placing a Bootstrap 5.3 modal inside a container other than body
, bootstrap's <div class="modal-backdrop fade show"></div>
, that is a dark half-transparent layer under modal
, is always appended to body
instead of the specified container, giving wrong behavior as explained here or here.
Backdrop's source code has this part:
const Default = {
className: 'modal-backdrop',
clickCallback: null,
isAnimated: false,
isVisible: true, // if false, we use the backdrop helper without adding any element to the dom
rootElement: 'body' // give the choice to place backdrop under different elements
}
However there is no mechanism provided to specify rootElement
in the bootstrap options.
I fixed as follows in bootstrap.bundle.js
version v5.3.3
- Find
class Backdrop extends Config
, there_configAfterMerge(config)
- Replace
config.rootElement = ...
withconfig.rootElement = getElement(config.rootElement) || document.body;
with will fallback tobody
if rootElement is not found, ie. null returned from getElement():
_configAfterMerge(config) {
// use getElement() with the default "body" to get a fresh Element on each instantiation
config.rootElement = getElement(config.rootElement) || document.body;
return config;
}
- Find
class Modal extends BaseComponent
, there_initializeBackDrop()
- add after
isAnimated: this._isAnimated()
a new propertyrootElement: this._config.rootElement
:
_initializeBackDrop() {
return new Backdrop({
isVisible: Boolean(this._config.backdrop),
// 'static' option will be translated to true, and booleans will keep their value,
isAnimated: this._isAnimated(),
rootElement: this._config.rootElement
});
}
When initializing your bootstrap with new bootstrap
add rootElement: <your container: HTMLElement as object or string selector>
, for example:
const myModal = new bootstrap.Modal(
document.getElementById('myModal')
, {
backdrop: "static",
rootElement: '#your-div'
}
)
myModal.show()
Here's my usage in SPA.
// I have a dynamic modal in my SPA, so I'm rendering a modal
// inside a DocumentFragment first and save this modal object
// in a variable so that I can call modal's methods after, like close()
const VALUES = {
modal: {
id: 'my-modal',
obj: null
}
}
const fragment = document.createRange().createContextualFragment(
`<div class="modal fade" id="my-modal" tabindex="-1">
...
</div>`
)
const rootElement = document.getElementById('my-container');
VALUES.modal.obj = new bootstrap.Modal(
fragment.getElementById('my-modal')
, {
backdrop: "static",
rootElement
}
)
rootElement.append(fragment)
VALUES.modal.obj.show()
Top comments (0)