onClick jumping to top of page - javascript

I am coding a simple website with a JS side navbar. When I resize the window to develop at different widths I noticed that the page would jump to the top.
I then noticed that when I click the hamburger icon the page also jumps to the top.
I've looked into it and it appears to be the onClick that is the issue. I have tried to use return false but the issue is still the same.
I have used the code/tutorial provided on w3 schools.
Thanks for any help
Here is my code
HTML:
<nav id="mySidenav" class="sidenav">
×
<img class="sidenavbar-logo-img" src='<?php echo get_template_directory_uri(); ?>/img/logo-NO.png'>
<?php wp_nav_menu( array( 'theme_location' => 'sidenav-menu' ) ); ?>
<div class='sidebar-nav-info'>
<p>Lower Trinity St,
Birmingham,
B9 4AG</p>
<p>Facebook Instagram</p>
</div>
</nav>
<!-- Use any element to open the sidenav -->
<span class="hamburger" onclick="openNav(); return false;">
<i class="fas fa-bars"></i>
</span>
CSS
/* The navigation menu links */
.sidenav ul {
list-style-type: none;
margin-left: 0;
}
.sidenav ul li {
margin: 0;
}
.sidenav a {
padding: 8px 8px 8px 0px;
text-decoration: none;
font-weight: 700;
font-size: 18px;
color: #f1f1f1;
display: block;
transition: 0.3s;
}
/* When you mouse over the navigation links, change their color */
.sidenav a:hover {
color: #818181;
text-decoration: none;
}
/* Position and style the close button (top right corner) */
.sidenav .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
/* Style page content - use this if you want to push the page content to the right when you open the side navigation */
#main {
transition: margin-left .5s;
padding: 20px;
}
/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
#media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;}
}
.sidebar-nav-info {
padding: 30px;
position: absolute;
bottom: 0;
left: 0;
width: 200px;
color: #E2E2E2;
font-size: 12px;
}
/** HAMBURGER ICON **/
span.hamburger {
position: sticky;
top: 30px;
left: 30px;
font-size: 30px;
font-weight: 800;
cursor: e-resize;
}
JS
<script>
/* Set the width of the side navigation to 250px and the left margin of the page content to 250px */
function openNav() {
document.getElementById("mySidenav").style.width = "300px";
document.getElementById("main").style.marginLeft = "300px";
}
/* Set the width of the side navigation to 0 and the left margin of the page content to 0 */
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
document.getElementById("main").style.marginLeft = "0";
}
</script>

As you have suspected, this is caused by the href= in the a tag. By default, a tags navigate the page somewhere, so having either href=# or as yours is written, will just navigate to top of page.
The return false should do the trick, but it is likely not in the correct place. Try putting it inside the closeNav function, as the final statement. Else, you might need to create an event listener for a tags and just respond with the return false. You can also try event.preventDefault() instead of return false (but return false should work - it does more than preventDefault.
Update:
One thing that helps is to avoid using inline javascript (that is, where the js is on the tag itself: onclick="closeNav();return false;"). Instead, create an event listener and do your js there. Here is a technical discussion regarding inline-javascript versus event listeners (the prevailing wisdom being that inline-javascript is more fraught and less desirable, particularly with respect to event bubbling, which is what you are dealing with here.) Here is a more simple article.
So, switch to an event listener structure, like this (untested):
var cbel = document.getElementsByClassname("closebtn");
cbel.addEventListener("click", closeNav, false);
var opel = document.getElementsByClassname("hamburger");
opel.addEventListener("click", openNav, false);
/* Set the width of the side navigation to 250px and the left margin of the page content to 250px */
function openNav() {
document.getElementById("mySidenav").style.width = "300px";
document.getElementById("main").style.marginLeft = "300px";
return false;
}
/* Set the width of the side navigation to 0 and the left margin of the page content to 0 */
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
document.getElementById("main").style.marginLeft = "0";
return false;
}
Final point: I would also recommend that you look into jQuery, because:
1) You are using bootstrap, which uses jQuery itself, so it is already loaded
2) It is much less typing
3) Most people (myself included) find it much simpler. for example, the above code in jQuery would look like this:
$(function(){
$('.closebtn').click(function(){
$("#mySidenav").css('width', '300px');
$("#main").css('margin-left', '300px');
});
});//END document.ready

Related

Unwanted White Space Mobile View HTML / Burger Menu Size

I've recently been making a website and for some reason working on media queries for it to fit mobile view. It has lots of extra white space which is confusing to me.
My problem : Extra white space in mobile view, that im positive is caused by the "MainMenu" dropdown from a "Burger" that I'm using. It seems like MainMenu has a min-width instead of width 100% but I don't know why. Also on Mobile View you can scroll really far out of the webpage and get all this extra white space.
Here is some code of the MainMenu :
CSS -
/* Nav Main Menu */
nav .mainMenu {
display:flex;
list-style: none;
}
nav .mainMenu li a {
display: inline-block;
padding: 30px;
margin:10px;
text-decoration: none;
color: rgb(0, 0, 0);
font-size: 1.5rem;
font-family:'Courier New', Courier, monospace;
}
nav .mainMenu li a:hover {
color: rgb(0, 110, 255);
}
JS Burger Script -
function show(){
mainMenu.style.display = 'flex';
mainMenu.style.top = '0';
}
function close(){
mainMenu.style.top = '-100%';
}
Here is some reference images of my problem :
My Question : How can I remove extra white space on my page, and set the burger menu to width of 100%.
Heres my github/website to check it out fully : https://github.com/ConstantineLinardakis/TwinPlayzOfficial
https://constantinelinardakis.github.io/TwinPlayzOfficial/index.html
The error you are facing isn't because of the Menu. I debugged your website using the dev tools and I found out that
<p> © TwinPlayz 2021</p>
This is the line that is consumingunnecessary space. Add an id to that paragraph like this,
<p id="copyright_text"> © TwinPlayz 2021</p>
And then add the following CSS with the media query
#media (max-width: 600px) {
#copyright_text {
width: 130px; //adjust to your own needs
}
}

How to only run a function that generates a "back to top" button based on screen size?

I have a back-to-top button which appears when users scroll down on the website, however, I would like it if this button only appeared depending on screen size.
As somebody new to javascript, I cannot figure out how to add this in, other than that I am assuming it should be a part of the "if" argument.
HTML:
<button onclick="topFunction()" id="button-top" title="Go to top">Top</button>
CSS code:
#button-top {
display: none;
position: fixed;
bottom: 20px;
right: 30px;
z-index: 99;
border: none;
outline: none;
background-color: #d46900;
color: white;
cursor: pointer;
padding: 15px;
border-radius: 10px;
font-size: 1.5em;
}
#button-top:hover {
color: #1c1c1c;
background-color: #ccc;
}
JS code:
/* BACK TO TOP BUTTON*/
// When the user scrolls down 20px from the top of the document, show the button window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
document.getElementById("button-top").style.display = "block";
} else {
document.getElementById("button-top").style.display = "none";
}
}
// When the user clicks on the button, scroll to the top of the document
function topFunction() {
document.body.scrollTop = 0; // For Safari
document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
}
You should use media queries to show or hide your button depending on the screen size:
/* Hide the button if the width is less than 500px */
#media (max-width: 500px) {
#button-top {
display: none;
}
}
<button type="button" id="button-top">Back to top</button>
You can run the snippet above and resize your browser, once the width is below 500px, the button will disappear.
Not sure what you want.
If you want your button-top button to appear on bigger screen like desktop and disappear on smaller screen like tablets or mobile you can do something like this:
#media only screen and (max-width: 768px) {
#button-top {
display: none;
}
}
but if you want your button-top button to appear after scrolling and disappear after scrolling back to top you can do something like this:
css:
#button-top.show {
visibility: visible;
}
js:
$(document).on("scroll", function () {
if ($(window).scrollTop() > 100) {
$("#button-top").addClass("show");
} else {
$("#button-top").removeClass("show");
}
});

Reference multiple (different) Div Id's using document.getElementById

I'm using script editor web part in SharePoint to create a Full screen overlay navigation feature.
I got the code from https://www.w3schools.com/howto/howto_js_fullscreen_overlay.asp.
I modified it some because I want to have multiple menus to click that use this feature. I tried to upload a pic, but I don't have 10 reputation points:/ Below is a textual representation. I have a Doctrine menu link and a TTP menu link.
Doctrine
TTP
They work; however, no matter which one I click on, they both show the links associated with TTP. I want to click on Doctrine and see the Doctrine links, and click on TTP to see the TTP links. Two separate nav menus that perform the full screen overlay feature (separately).
I know this subject has been beat to death, but I cannot find anything that satisfies my requirement. Below is how I am referencing getElementById.
Note: I replaced my actual links with dummy links.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: 'Lato', sans-serif;
}
.overlay {
height: 0%;
width: 100%;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: rgb(0,0,0);
background-color: rgba(28,65,104, 0.9);
overflow-y: hidden;
transition: 0.5s;
}
.overlay-content {
position: relative;
top: 25%;
width: 100%;
text-align: center;
margin-top: 30px;
}
.overlay a {
padding: 8px;
text-decoration: none;
font-size: 36px;
color: #eccb13;
display: block;
transition: 0.3s;
}
.overlay a:hover, .overlay a:focus {
color: #800000;
}
.overlay .closebtn {
position: absolute;
top: 20px;
right: 45px;
font-size: 60px;
}
#media screen and (max-height: 450px) {
.overlay {overflow-y: auto;}
.overlay a {font-size: 20px}
.overlay .closebtn {
font-size: 40px;
top: 15px;
right: 35px;
}
}
</style>
</head>
<body>
<div id="doctrineNav" class="overlay">
×
<div class="overlay-content">
Car
Bicycle
Boat
Airplane
</div>
</div>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☞ Doctrine</span>
<p></p>
<div id="ttpNav" class="overlay">
×
<div class="overlay-content">
Apple
Orange
Dog
Cat
</div>
</div>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☞ TTP</span>
<script>
function openNav() {
document.getElementById("doctrineNav").style.height = "100%";
}
function closeNav() {
document.getElementById("doctrineNav").style.height = "0%";
}
function openNav() {
document.getElementById("ttpNav").style.height = "100%";
}
function closeNav() {
document.getElementById("ttpNav").style.height = "0%";
}
</script>
</body>
</html>
If I change the script around like below, then no matter which one I click on, they both overlay on top of each other. In other words, I can see the TTP links, but also see the Doctrine links behind it.
<script>
function openNav() {
document.getElementById("doctrineNav").style.height = "100%";
document.getElementById("ttpNav").style.height = "100%";
}
function closeNav() {
document.getElementById("doctrineNav").style.height = "0%";
document.getElementById("ttpNav").style.height = "0%";
}
</script>
The problem is that you've named both sets of functions the same thing. When you declare openNav the second time to show TTP, it replaces the first instance. An easy solution is to just declare two separate sets of functions, e.g.:
function openDoctrine() {
document.getElementById("doctrineNav").style.height = "100%";
}
function closeDoctrine() {
document.getElementById("doctrineNav").style.height = "0%";
}
function openTTP() {
document.getElementById("ttpNav").style.height = "100%";
}
function closeTTP() {
document.getElementById("ttpNav").style.height = "0%";
}
and reference them as appropriate, e.g.:
<div id="doctrineNav" class="overlay">
×
...
</div>
...
<span style="font-size:30px;cursor:pointer" onclick="openDoctrine()">☞ Doctrine</span>
In short, you can't reuse names in JavaScript (how should the engine know which function you're referring to?), so use different names more specific to the different task.
#Ken Bellows has a great answer. One additional thing I find useful is adding an extra class to the elements you want to select. This class should have no extra CSS, the sole purpose will be to allow you to select multiple divs with one line. Then, use the code from here.

Dynamically positioning element on scroll

Goal
To have the page navigation positioned lower on the page when initially loaded. So that it looks like pictured below.
Background
I created a navigational element that is using Headroom.js to control its position. The point of the library is that it moves the desired navigational item out of view when a user is scrolling down so that you can see more content. Then the item shows up when you scroll back up to make it convenient to click on a link if that is what you needed to do.
Current State
I have this current demo on codepen.
That navigational item is at the top of the page but on a lower z-index. So not initially visible.
when you scroll down the element is out of view.
But when you scroll up, it is where it needs to be
Code
HTML
<nav id="page-menu" class="link-header header--fixed slide slide--reset" role="banner">
<ul>
<li>Products</li>
<li>Features</li>
<li>Testimonials</li>
<li>Cases</li>
</ul>
</nav>
CSS
#page-menu {
background-color: #BA222B;
list-style-type: none;
width: 100%;
z-index:10;
}
#page-menu ul {
list-style-type: none;
margin: 0;
position: absolute;
bottom: 5px;
right: 10px;
}
#page-menu ul li {
display: inline-block;
margin-left: 10px;
}
#page-menu ul li a {
text-decoration: none;
color: #fff;
}
.link-header {
background-color:#292f36;
height: 100px;
}
.header--fixed {
position:fixed;
z-index:10;
right:0;
left:0;
top:0px;
}
jQuery
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 150,
classes: {
initial: "slide",
pinned: "slide--reset",
unpinned: "slide--up"
}
}).init();
}());
Full demo on codepen.
Goal :
From what you are describing, you want the read navigation to appear as such on page load:
And move with the gray bar, but and down, as the user scrolls, until it cutoff point reaches the bottom of the gray bar. Then you want things to kick in, and have the red bar slide up and out of view, and then up and down depending on scroll. You want the transition to be smooth.
Method:
The thing to keep in mind for a smooth transition is that you have two states: A top state and a bottom state. You have to design both, you have to figure out the exact height to change over, and you have to make sure that they will be identical at that spot, so appear seamless.
Top State:
We don't need any sort of extra positioning here. We want it to be static in fact, as odd as that might sound.
Bottom State:
We want fixed positioning here. Since we want the changeover to occur right when the red bar touches the top of the window, your CSS in fixed-header is perfect already.
Changeover Height:
The header and the gray nav bar combined are 180px, so that number will be our change over.
Code:
1. Statechange
Lets work backwards and take the state change first. You will need to change from 150px to 180px in a lot of places. For example, your JS code:
Existing JS:
if ($(window).scrollTop() >= 150) {
...
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 150,
New JS:
if ($(window).scrollTop() >= 180) {
...
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 180,
And your header will need an updated height, or a removal of height entirely.
Existing CSS:
header {
height:150px;
position: relative;
z-index:30;
}
New CSS:
header {
position: relative;
z-index:30;
}
2. Top State
The big thing here messing you up is that for some reason the library you are using is applying .header--fixed and link-header on page load. I don't know how to prevent this, but we can just neutralize is by removing them from your CSS.
Remove This CSS:
.link-header {
background-color:#292f36;
height: 100px;
}
.header--fixed {
position:fixed;
z-index:10;
right:0;
left:0;
top:0px;
}
Second, we need to tweak the ul inside your red nav.
Existing CSS:
#page-menu ul {
list-style-type: none;
margin: 0;
position: absolute;
bottom: 5px;
right: 10px;
}
New CSS:
#page-menu ul {
list-style-type: none;
margin: 0 auto;
padding:0;
width:960px;
max-width:100%;
text-align:right;
}
3. Bottom State
Everything works really well here aleady, except that the fixed-header class is getting added to the gray nav as well. We need to tweak our jQuery selector bit.
Existing JS:
if ($(window).scrollTop() >= 180) {
$('nav#page-menu').addClass('fixed-header');
}
else {
$('nav#page-menu').removeClass('fixed-header');
}
NewJS:
if ($(window).scrollTop() >= 180) {
$('header nav').addClass('fixed-header');
}
else {
$('header nav').removeClass('fixed-header');
}
4. Misc Cleanup
Everything looks really good here, except that the lis inside our two navs don't line up. We need to fix some margin-right to bring them into line.
Existing CSS:
#page-menu ul li {
display: inline-block;
margin-left: 10px;
}
New CSS:
#page-menu ul li {
display: inline-block;
margin-left: 10px;
margin-right: 10px;
}
Finally, I noticed that there's a missing closing bracket in your HTML, in the gray nav. It's not hurting much, but it could:
<nav>
<ul>
<li>Dentists</li>
<li>Labs</li>
<li>Patients</li>
<ul> <--- ( Should be </ul> )
</nav>
End Result:
http://codepen.io/anon/pen/qIrhx

Disable scrolling while popup active

I created a jQuery popup by following an online tutorial (http://uposonghar.com/popup.html).
Due to my low knowledge on jQuery I am not able to make it work as of my requirements.
My problem:
I want to disable scroll of webpage while popup is active.
Background fade color of popup while active is not working on full webpage.
CSS:
body {
background: #999;
}
#ac-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255,255,255,.6);
z-index: 1001;
}
#popup{
width: 555px;
height: 375px;
background: #FFFFFF;
border: 5px solid #000;
border-radius: 25px;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
box-shadow: #64686e 0px 0px 3px 3px;
-moz-box-shadow: #64686e 0px 0px 3px 3px;
-webkit-box-shadow: #64686e 0px 0px 3px 3px;
position: relative;
top: 150px; left: 375px;
}
JavaScript:
<script type="text/javascript">
function PopUp(){
document.getElementById('ac-wrapper').style.display="none";
}
</script>
HTML:
<div id="ac-wrapper">
<div id="popup">
<center>
<p>Popup Content Here</p>
<input type="submit" name="submit" value="Submit" onClick="PopUp()" />
</center>
</div>
</div>
<p>Page Content Here</p>
A simple answer, which you could use and would not require you to stop the scroll event would be to set the position of your #ac-wrapper fixed.
e.g.
#ac-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255,255,255,.6);
z-index: 1001;
}
this will keep the container of the popup always visible (aligned top - left) but would still allow scrolling.
But scrolling the page with a popup open is BAD!!! (almost always anyway)
Reason you would not want to allow scrolling though is because if your popup isn't fullscreen or is semi transparent, users will see the content scroll behind the popup. In addition to that, when they close the popup they will now be in a different position on the page.
A solution is that, when you bind a click event in javascript to display this popup, to also add a class to the body with essentially these rules:
.my-body-noscroll-class {
overflow: hidden;
}
Then, when closing the popup by triggering some action or dismissing it with a click, you simply remove the class again, allowing scroll after the popup has closed.
If the user then scrolls while the popup is open, the document will not scroll. When the user closes the popup, scrolling will become available again and the user can continue where they left off :)
To disable scrollbar:
$('body').css('overflow', 'hidden');
This will hide the scrollbar
Background-fade-thing:
I created my own popup-dialog-widget that has a background too. I used the following CSS:
div.modal{
position: fixed;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 9998;
background-color: #000;
display: none;
filter: alpha(opacity=25); /* internet explorer */
-khtml-opacity: 0.25; /* khtml, old safari */
-moz-opacity: 0.25; /* mozilla, netscape */
opacity: 0.25; /* fx, safari, opera */
}
I had a similar problem; wanting to disable vertical scrolling while a "popup" div was displayed.
Changing the overflow property of the body does work, but also mess with the document's width.
I opted jquery to solve this using and used a placeholder for the scrollbar.
This was done without binding to the scroll event, ergo this doesn't change your scrollbar position or cause flickering :)
HTML:
<div id="scrollPlaceHolder"></div>
CSS:
body,html
{
height:100%; /*otherwise won't work*/
}
#scrollPlaceHolder
{
height:100%;
width:0px;
float:right;
display: inline;
top:0;
right: 0;
position: fixed;
background-color: #eee;
z-index: 100;
}
Jquery:
function DisableScrollbar()
{
// exit if page can't scroll
if($(document).height() == $('body').height()) return;
var old_width = $(document).width();
var new_width = old_width;
// ID's \ class to change
var items_to_change = "#Banner, #Footer, #Content";
$('body').css('overflow-y','hidden');
// get new width
new_width = $(document).width()
// update width of items to their old one(one with the scrollbar visible)
$(items_to_change).width(old_width);
// make the placeholder the same width the scrollbar was
$("#ScrollbarPlaceholder").show().width(new_width-old_width);
// and float the items to the other side.
$(items_to_change).css("float", "left");
}
function EnableScrollbar()
{
// exit if page can't scroll
if ($(document).height() == $('body').height()) return;
// remove the placeholder, then bring back the scrollbar
$("#ScrollbarPlaceholder").fadeOut(function(){
$('body').css('overflow-y','auto');
});
}
Hope this helps.
If simple switching of body's 'overflow-y' is breaking your page's scroll position, try to use these 2 functions (jQuery):
// Run this function when you open your popup:
var disableBodyScroll = function(){
window.body_scroll_pos = $(window).scrollTop(); // write page scroll position in a global variable
$('body').css('overflow-y','hidden');
}
// Run this function when you close your popup:
var enableBodyScroll = function(){
$('body').css('overflow-y','scroll');
$(window).scrollTop(window.body_scroll_pos); // restore page scroll position from the global variable
}
Use below code for disabling and enabling scroll bar.
Scroll = (
function(){
var x,y;
function hndlr(){
window.scrollTo(x,y);
//return;
}
return {
disable : function(x1,y1){
x = x1;
y = y1;
if(window.addEventListener){
window.addEventListener("scroll",hndlr);
}
else{
window.attachEvent("onscroll", hndlr);
}
},
enable: function(){
if(window.removeEventListener){
window.removeEventListener("scroll",hndlr);
}
else{
window.detachEvent("onscroll", hndlr);
}
}
}
})();
//for disabled scroll bar.
Scroll.disable(0,document.body.scrollTop);
//for enabled scroll bar.
Scroll.enable();
https://jsfiddle.net/satishdodia/L9vfhdwq/1/
html:-
Open popup
Popup
pop open scroll stop now...when i will click on close automatically scroll running.
close
**css:-**
#popup{
position: fixed;
background: rgba(0,0,0,.8);
display: none;
top: 20px;
left: 50px;
width: 300px;
height: 200px;
border: 1px solid #000;
border-radius: 5px;
padding: 5px;
color: #fff;
}
**jquery**:-
<script type="text/javascript">
$("#open_popup").click(function(){
$("#popup").css("display", "block");
$('body').css('overflow', 'hidden');
});
$("#close_popup").click(function(){
$("#popup").css("display", "none");
$('body').css('overflow', 'scroll');
});
</script>
I had the same problem and found a way to get rid of it, you just have to stop the propagation on touchmove on your element that pops up. For me, it was fullscreen menu that appeared on the screen and you couldn't scroll, now you can.
$(document).on("touchmove","#menu-left-toggle",function(e){
e.stopPropagation();
});
This solution works for me.
HTML:
<div id="payu-modal" class="modal-payu">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<p>Some text in the Modal..</p>
</div>
</div>
CSS:
.modal-payu {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
bottom: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
/* The Close Button */
.close {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
JS:
<script>
var btn = document.getElementById("button_1");
btn.onclick = function() {
modal.style.display = "block";
$('html').css('overflow', 'hidden');
}
var span = document.getElementsByClassName("close")[0];
var modal = document.getElementById('payu-modal');
window.onclick = function(event) {
if (event.target != modal) {
}else{
modal.style.display = "none";
$('html').css('overflow', 'scroll');
}
}
span.onclick = function() {
modal.style.display = "none";
$('html').css('overflow', 'scroll');
}
</script>
I ran into the problem and tried several solutions,
here is the article that solved my problem (https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/) and it is quite simple!
It uses the 'fixed body' solution, which is quite common to find in lots of posts.
The problem with this solution is, when the popup is closed, the body will scroll back to the top.
But the article points out: by manipulating the CSS top and position attributes while using the solution, we can recover the scroll position.
Another issue of the solution is, you can't apply the solution with the multiple popup scenario.
So I added a variable to store the count of the popup, just to make sure the program won't trigger the initiating process nor the reset process at the wrong timing.
Here is the final solution I get:
// freeze or free the scrolling of the body:
const objectCountRef = { current: 0 }
function freezeBodyScroll () {
if (objectCountRef.current === 0) { // trigger the init process when there is no other popup exist
document.body.style.top = `-${window.scrollY}px`
document.body.style.position = 'fixed'
}
objectCountRef.current += 1
}
function freeBodyScroll () {
objectCountRef.current -= 1
if (objectCountRef.current === 0) { // trigger the reset process when all the popup are closed
const scrollY = document.body.style.top
document.body.style.position = ''
document.body.style.top = ''
window.scrollTo(0, parseInt(scrollY || '0') * -1)
}
}
You can also see the demo on my Codepen: https://codepen.io/tabsteveyang/pen/WNpbvyb
Edit
More about the 'fixed body' solution
The approach is mainly about setting the CSS position attribute of the body element into 'fixed' to make it unscrollable.
No matter how far it has been scrolled, when the body is fixed, it will scroll back to the top, which is the behavior that I don't expect to see. (Imagine the user is browsing a long content and almost scrolls to the bottom of the page, suddenly a popup shows up and make the page scroll right back to the top, that's a bad user experience)
The solution from the article
Base on the 'fixed body' approach, additionally, the solution sets the CSS top of the body as the value of '-window.scrollY px' to make the body looks like it stays in the current scrolling position while it is fixed.
Furthermore, the solution uses the CSS top of the body as a temporary reference, so that we can retrieve the scrolling position by the attribute when we want to make the body scrollable again. (Notice you have to multiple the position you get to -1 to make it positive)

Categories