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 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 customize rootElement
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 tobodyif 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 rootElement = document.getElementById('your-div');
const myModal = new bootstrap.Modal(
document.getElementById('myModal')
, {
backdrop: "static",
rootElement
}
)
myModal.show()
or
const myModal = new bootstrap.Modal(
document.getElementById('myModal')
, {
backdrop: "static",
rootElement: '#your-div'
}
)
myModal.show()