party-ring
party-ring

Reputation: 1871

Prevent fixing body from scrolling to the top of the page

I have a button which prevents default and opens a modal. I am trying to make the background behind the modal stay fixed, and then unfix when the modal is closed.

The issue I am having is when I set the background to fixed:

if (modal.classList.contains('is-active')) {
    body.style.position = 'fixed';
}

the page in the background scrolls to the top, and when the modal is closed, the user isn't where they left off. To improve the UX, I would like the user to be returned to where they left off, so in my function I have:

const scrollY = window.pageYOffset;

if (modal.classList.contains('is-active')) {
    body.style.position = 'fixed';
} else {
    body.style.position = '';
    window.scrollTo(0, scrollY);
}

The code above is triggered when the user clicks on the button to open the modal.

However, as the function is reloaded when the modal is closed, and the body position is 'fixed' has changed the scroll position to 0, this overwrites scrollY.

So, this can be solved one of two ways:

a) How do I prevent the scroll position from being changed to 0 when updating the body style position, or

b) how do I keep the value of scrollY?

Upvotes: 2

Views: 1406

Answers (3)

party-ring
party-ring

Reputation: 1871

My final solution (thanks to the answers above for putting me on the right course, and to @Constantin Groß's comment):

Outside of my function I have declared var scrollY;

// Locks the background and makes it not scrollable
if (modal.classList.contains('is-active')) {
    scrollY = window.pageYOffset;
    console.log("open " + scrollY);
    body.classList.toggle('popup-open--body');
} else {
    console.log("closed " + scrollY);
    body.classList.remove('popup-open--body');
    window.scrollTo(0, scrollY);
}

And in my CSS:

.popup-open--body {
  overflow: initial;
  position: fixed;
  width: 100%;
}

Upvotes: 1

Sarah Groß
Sarah Groß

Reputation: 10879

Instead of setting the whole body to fixed positioning, you can do it for the modal instead and just set overflow: hidden on the body. This saves you the trouble of storing and restoring the scroll position upon opening/closing the modal.

function openModal() {
  document.body.classList.add('show-modal');
}

function hideModal() {
  document.body.classList.remove('show-modal');
}
#modal {
 position: fixed;
 top: 0;
 right: 0;
 bottom: 0;
 left: 0;
 background: rgba(0,0,0,0.33);
 display: none;
 padding: 3em;
}

body.show-modal {
  overflow: hidden;
}

body.show-modal #modal {
 display: block;
}
this is the top...<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
long content<br>
<button id="button" onClick="openModal()">open modal</button>

<div class="modal" id="modal"><button id="close" onClick="hideModal()">close modal</button></div>

Upvotes: 0

Kasabucki Alexandr
Kasabucki Alexandr

Reputation: 630

My suggestion is:

if (modal.classList.contains('is-active')) {
   body.classList.toggle('is-modal-open');
}

Somewhere at css:

.is-modal-open {
      position: absolute;
      height: 100vh;
      width: 100vw;
      overflow: hidden;
}

Upvotes: 0

Related Questions