Scrollbar padding is not placed on .navbar-fixed-top, .navbar-fixed-bottom when opening Modal.
Closed this issue · 6 comments
Describe the bug
If the <body> element contains a navbar (.navbar-fixed-top or .navbar-fixed-bottom) and the <body> has a fixed scrollbar (overflow-y: scroll), then when opening a UIV Modal, the navbar content moves to the right instead of staying in its fixed position.
To Reproduce
Steps to reproduce the behavior:
- Create a body element with a FIXED navbar inside (.navbar-fixed-top or .navbar-fixed-bottom), possibly using UIV's <Navbar>.
- Add overflow-y: scroll CSS to the <body> element.
- Add a <Modal> UIV element to the <body>
- Open the modal.
Expected behavior
The navbar should not move. Instead, an amount of padding-right equal to the scrollbar width should be placed on the .navbar-fixed-top or .navbar-fixed-bottom after the <body>'s scrollbar is taken away (taken away via class .modal-open).
UIV is already adding a padding-right of the scrollbar width to the <body> element when opening the modal in its toggleBodyOverflow
method:
export function toggleBodyOverflow (enable) {
const MODAL_OPEN = 'modal-open'
const body = document.body
if (enable) {
removeClass(body, MODAL_OPEN)
body.style.paddingRight = null
} else {
const browsersWithFloatingScrollbar = isIE10() || isIE11()
const documentHasScrollbar = hasScrollbar(document.documentElement) || hasScrollbar(document.body)
if (documentHasScrollbar && !browsersWithFloatingScrollbar) {
body.style.paddingRight = `${getScrollbarWidth()}px`
}
addClass(body, MODAL_OPEN)
}
}
however the same is not done for the .navbar-fixed-top and .navbar-fixed-bottom. This is in contrast to Bootstrap's own bootstrap.js
, which does specifically target .navbar-fixed-top and .navbar-fixed-bottom for padding corrections when opening modals.
It would be appreciated if the same padding-right correction logic could be done for fixed navbars, similar to bootstrap.js
.
Screenshots
Before modal open (blue part is navbar-fixed-top):
After modal open:
It is a little jarring when a navbar with a lot of content moves when opening and closing a modal.
Additional context
UIV version is 0.36.1
, although looking at github I think this would still be a problem in the latest.
Would very much appreciate a 0.X fix as I have not upgraded to 1.X just yet.
Looks like the original jQuery version of Bootstrap does not add padding to navbar-fixed-*
, too:
You can workarround this by adding such css to your project:
.modal-open .navbar-fixed-top, .modal-open .navbar-fixed-bottom {
padding-right: 15px;
}
I don't know if I should add the additional logics to toggleBodyOverflow
, because somebody might not want this behaviour.
Hi @wxsms
Can you please double verify your example used the bootstrap.js
modal implementation and not the UIV implementation of modal. Also verify you are not using a browser with a zero-width scrollbar (such as IE10 or IE11).
I have verified that the Bootstrap 3.4.1's bootstrap.js
implementation does add padding to the navbar. See my example below, which is a modal produced by bootstrap.js
and not UIV. As you can see the .navbar-fixed-top
element is given a padding-right equal to the scrollbar.
There is code in Bootstrap 3.4.1 's bootstrap.js
which is checking for .navbar-fixed-top
& .navbar-fixed-bottom
and gives them padding equal to the scrollbar width when the modal opens:
var Modal = function (element, options) {
...
this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom'
...
}
Modal.prototype.show = function (_relatedTarget) {
...
this.setScrollbar()
this.$body.addClass('modal-open')
...
}
Modal.prototype.setScrollbar = function () {
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
this.originalBodyPad = document.body.style.paddingRight || ''
var scrollbarWidth = this.scrollbarWidth
if (this.bodyIsOverflowing) {
this.$body.css('padding-right', bodyPad + scrollbarWidth)
$(this.fixedContent).each(function (index, element) {
var actualPadding = element.style.paddingRight
var calculatedPadding = $(element).css('padding-right')
$(element)
.data('padding-right', actualPadding)
.css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px')
})
}
}
Unfortunately I tried a fixed-padding CSS solution with .modal-open
. However it doesn't work on IE, as you know IE has zero-width scrollbars which means this padding shouldn't be applied in that scenario. There are possibly other browser versions which do or do not used a 15px-width scrollbar. Ultimately I concluded the cross-browser solution would be to measure the scrollbar width with JS on modal open - which at that point I found Bootstrap was already doing that.
I see. will work on it soon.
pls try v1.1.1
@wxsms Have just upgraded and tried it in Chrome/IE/Firefox and it works well. The navbar does not move when opening a modal.
Thank you for your quick response and continued support for the UIV library.
@StefanCardnell welcome. pls give this project a star if you found it helpful.