Fixed position elements move when the body is full

I want to open a modal layer that overtakes body scrolling. To achieve this, when the layer is displayed, I set the overflow of the body to hidden, and the overflow to the modal layer. Visually, one scrollbar replaces another.

In the background, I have a top panel with a fixed position and a width of 100%. What happens when the overflow of the body is set to hidden, the width of 100% of the width (top panel) occupies the space of the scroll bar, and its elements move to the right.

How can I prevent these items from moving?

I tried to calculate (javascript) the width of the scrollbar and when setting the overflow of the body: hidden, enter margin-right: "width of the scrollbar" in the top panel. This did not work.

Also tried a dummy div at the right end of the top pane with the overflow set for scrolling, and made it display a scroll bar when opening the layer. The idea was to fill in the gap in the skipped scrollbar using another scrollbar, only on the top container. It almost worked, but created a flicker of 1 or 2px. Not enough.

jsBeginning here with the main problem

var body = $('body'), main = $('.main'), open_modal = $('.open-modal'), close_modal = $('.close-modal'), modal_container = $('.modal-container'), toggleModal = function() { body.toggleClass('body-locked'); modal_container.toggleClass('dp-block'); }; open_modal.on('click', toggleModal); close_modal.on('click', toggleModal); 
+8
javascript html css css3
source share
3 answers

Mostly...

  • When the modal file is open , set the width of the menu to its current width and set the window.onresize event handler, which will resize the menu to the width of the body.

  • When the modal object is closed , remove the fixed width and the window.onresize handler and return the menu to its original state.


In the spirit of less === more I allowed myself to simplify my code as simple as possible.

 var body = $('body'); var menu = $('#topBarFixed'); function toggleModal() { menu.css('width', body.hasClass('locked') ? '' : menu.width()); window.onresize = body.hasClass('locked') ? '' : function () { menu.css('width', body.width()); } body.toggleClass('locked'); } body.on('click', '.open-modal, .close-modal', toggleModal); 
 body { padding-top: 40px; height: 1000px; background: lightblue; } body.locked { height: 100%; overflow: hidden; } .modal-container { display: none; overflow-y: scroll; position: fixed; top: 0; right: 0; height: 100%; width: 100%; background-color: rgba(255, 255, 255, 0.3); z-index: 400; } body.locked .modal-container { display: block !important; } .modal { height: 600px; width: 200px; margin: 50px auto; background: indianred; } #topBarFixed { width: 100%; background-color: lightgray; position: fixed; top: 0; left: 0; text-align:center; display: inline-block; z-index: 200; } .topBarContent { display: inline-flex; flex-direction: row; flex-wrap: nowrap; justify-content: space-between; align-items: center; } .inner1 { width:30px; line-height: 40px; } .open-modal { position: relative; top: 400px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div id="topBarFixed"> <div class="topBarContent"> <div id="inner" class="inner1">div</div> <div id="inner" class="inner1">div</div> <div id="inner" class="inner1">div</div> <div id="inner" class="inner1">div</div> <div id="inner" class="inner1">div</div> </div> </div> <p>Scroll down to open layer</p> <button class="open-modal">Open layer</button> <div class="modal-container"> <div class="modal"> <button class="close-modal">Close layer</button> </div> </div> 
+7
source share

Your problem is that topBarFixed is 100% wide. If this width were fixed, you would not have this problem. In Chrome and Firefox, the following has been tested:

Add this line to the first line of toggleModal:

$(".topBarFixed").width($(".topBarFixed").width());

This will set the width to the actual width (in pixels) of the panel at this point. Then, when you close the layer, set it to 100% .

 close_modal.on('click', function() { toggleModal(); $(".topBarFixed").width("100%"); }); 

The whole code looks like this:

 var body = $('body'), main = $('.main'), open_modal = $('.open-modal'), close_modal = $('.close-modal'), modal_container = $('.modal-container'), toggleModal = function() { $(".topBarFixed").width($(".topBarFixed").width()); body.toggleClass('body-locked'); modal_container.toggleClass('dp-block'); }; open_modal.on('click', toggleModal); close_modal.on('click', function() { toggleModal(); $(".topBarFixed").width("100%"); }); 

And here is jsFiddle: http://jsfiddle.net/wmk05t0b/5/

Edit

Optionally, you can just set a fixed width, and this will do the trick:

 .topBarFixed { width:715px; /*changed from 100%*/ height: 40px; background-color: lightgray; position: fixed; top: 0; left: 0; text-align:center; display: inline-block; z-index: 200; } 
+4
source share

Some errors in your code: id - only one. Use classes if you want to apply the same style to more elements.

 <div class="topBarContent"> <div class="inner1">div</div> <div class="inner1">div</div> <div class="inner1">div</div> <div class="inner1">div</div> <div class="inner1">div</div> </div> 

In any case, this is not what caused your problem. First of all, your body overflow should be sufficient: do not add overflows to your .modal-container unless you want the background page to scroll while the modal is open. Secondly, fix the modal itself and center it using a centered CSS trick (left: 50%, margin-left: -half-of-your-width). CSS: blocked {overflow: scroll; }

 .modal-container { overflow:hidden; position:fixed; display: none; top: 0; right: 0; height: 100%; width: 100%; background-color: rgba(255, 255, 255, 0.3); z-index: 400; } .modal { position: fixed; height: 600px; width: 200px; margin: 50px auto 50px -100px; background: indianred; left:50%; } /*Reset your body, you never know*/ body { margin:0; padding:0 } 

Hope this helps.

-one
source share

All Articles