0

I have an off-canvas menu sliding from the left to cover the page. The building blocks of my page are divs. I call javascript functions to open and close the off-canvas menu. My main content remains as it is under the sliding menu. I have problems in finding a solution to dim the main content and to block any click to it.

I tried to use the property background: rgba(0, 0, 0, 0.5) !important; for an additional div with a z-index between off-canvas menu and maincontent, but without any result. Googled around, also here, but didn't find what I'm looking for. And I don't want to use Bootstrap or other libraries, to keep the project as light as possible. This is my code:

<style>
  .sidenav {
    height: 100%;
    width: 220px;
    position: absolute;
    z-index: 999;
    top: 0;
    left: 0;
    overflow-x: hidden;
    -webkit-transform: translate3d(-220px,0,0);
    -webkit-transition: -webkit-transform 0.4s;
    -webkit-transition-timing-function: cubic-bezier(0.7,0,0.3,1);
  }

  .cover {
    position: absolute;
    z-index: 900;
    left: 0px;
    top: 0px;
    display: none;
    width: 100%;
    height: 100%;
    z-index: 900;
    background: rgba(0, 0, 0, 0) !important;
    display: none;
  }

  .maincontent {
position: relative;
    z-index: 20;
    margin: auto;
  }
</style>

<script>
  function openNav() {
    document.getElementById("mySidenav").style.webkitTransform = "translate3d(-1px,0,0)";
    document.getElementById("cover").style.display = "inline";
    document.getElementById("cover").style.background = "rgba(0, 0, 0, 0.5) !important";
  }

  function closeNav() {
    document.getElementById("mySidenav").style.webkitTransform = "translate3d(-220px,0,0)";
    document.getElementById("cover").style.display = "none";
    document.getElementById("cover").style.background = "rgba(0, 0, 0, 0) !important";
  }
</script>

<div id="mySidenav" class="sidenav">
  <a href="javascript:void(0)" id="closebtn" class="closebtn" onclick="closeNav()">&times;</a>
  //menue items are hereunder
</div>
<div id="cover" class="cover">
<div id ="maincontent" class="maincontent">
  //some elements here
  <img id="open_nav" class="fixed-ratio-resize_menu" src="menu.png" alt="menu" onclick="openNav()">
  //all the rest of the page is here
</div>
</div>

Now the menu slides in and out as needed, but I have problems in finding a neat and running solution for: 1) dim the main content area under the menu; 2) intercept any click on main content area and either ignore it either onclick close the menu; 3) block the y scrolling of the main content, since it pulls also the off canvas menu to follow it, thus giving the appearance of a truncated side menu area.

gab
  • 77
  • 1
  • 1
  • 9

1 Answers1

0

First move your main content div outside the cover div. Currently your main content will only be visible when the cover is visible:

function openNav() {
  document.getElementById("mySidenav").style.webkitTransform = "translate3d(-1px,0,0)";
  document.getElementById("cover").style.display = "inline";
  // document.getElementById("cover").style.background = "rgba(0, 0, 0, 0.5) !important";
}

function closeNav() {
  document.getElementById("mySidenav").style.webkitTransform = "translate3d(-220px,0,0)";
  document.getElementById("cover").style.display = "none";
  // document.getElementById("cover").style.background = "rgba(0, 0, 0, 0) !important";
}
.sidenav {
  height: 100%;
  width: 220px;
  position: absolute;
  z-index: 999;
  top: 0;
  left: 0;
  overflow-x: hidden;
  -webkit-transform: translate3d(-220px, 0, 0);
  -webkit-transition: -webkit-transform 0.4s;
  -webkit-transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
  background: #fff;
}

.cover {
  position: absolute;
  z-index: 900;
  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
  z-index: 900;
  background: rgba(0, 0, 0, .5) !important;
  display: none;
}

.maincontent {
  position: relative;
  z-index: 20;
  margin: auto;
}
<div id="mySidenav" class="sidenav">
  <a href="javascript:void(0)" id="closebtn" class="closebtn" onclick="closeNav()">&times;</a> menu items are hereunder
</div>
<div id="cover" class="cover">
</div>
<div id="maincontent" class="maincontent">
  some elements here<br>
  <img id="open_nav" class="fixed-ratio-resize_menu" src="menu.png" alt="menu" onclick="openNav()"> all the rest of the page is here
</div>

Do you want to close the nav when clicking the cover? Then just add your onclick="closeNav()" to the cover:

function openNav() {
  document.getElementById("mySidenav").style.webkitTransform = "translate3d(-1px,0,0)";
  document.getElementById("cover").style.display = "inline";
  // document.getElementById("cover").style.background = "rgba(0, 0, 0, 0.5) !important";
}

function closeNav() {
  document.getElementById("mySidenav").style.webkitTransform = "translate3d(-220px,0,0)";
  document.getElementById("cover").style.display = "none";
  // document.getElementById("cover").style.background = "rgba(0, 0, 0, 0) !important";
}
.sidenav {
  height: 100%;
  width: 220px;
  position: absolute;
  z-index: 999;
  top: 0;
  left: 0;
  overflow-x: hidden;
  -webkit-transform: translate3d(-220px, 0, 0);
  -webkit-transition: -webkit-transform 0.4s;
  -webkit-transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
  background: #fff;
}

.cover {
  position: absolute;
  z-index: 900;
  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
  z-index: 900;
  background: rgba(0, 0, 0, .5) !important;
  display: none;
}

.maincontent {
  position: relative;
  z-index: 20;
  margin: auto;
}
<div id="mySidenav" class="sidenav">
  <a href="javascript:void(0)" id="closebtn" class="closebtn" onclick="closeNav()">&times;</a> menu items are hereunder
</div>
<div id="cover" class="cover" onclick="closeNav()">
</div>
<div id="maincontent" class="maincontent">
  some elements here<br>
  <img id="open_nav" class="fixed-ratio-resize_menu" src="menu.png" alt="menu" onclick="openNav()"> all the rest of the page is here
</div>

Finally, I would recommend to clean up your code and use event listeners instead of onclick properties in your html. Something like this:

var cover = document.getElementById("cover");
var sideNav = document.getElementById("mySidenav");
var closeNavBtn = document.getElementById("closebtn");
var openNavBtn = document.getElementById("open_nav");

function openNav() {
  sideNav.style.webkitTransform = "translate3d(-1px,0,0)";
  cover.style.display = "inline";
}

function closeNav() {
  sideNav.style.webkitTransform = "translate3d(-220px,0,0)";
  cover.style.display = "none";
}

closeNavBtn.addEventListener("click", closeNav);
cover.addEventListener("click", closeNav);
openNavBtn.addEventListener("click", openNav);
.sidenav {
  height: 100%;
  width: 220px;
  position: absolute;
  z-index: 999;
  top: 0;
  left: 0;
  overflow-x: hidden;
  -webkit-transform: translate3d(-220px, 0, 0);
  -webkit-transition: -webkit-transform 0.4s;
  -webkit-transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
  background: #fff;
}

.cover {
  position: absolute;
  z-index: 900;
  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
  z-index: 900;
  background: rgba(0, 0, 0, .5);
  display: none;
}

.maincontent {
  position: relative;
  z-index: 20;
  margin: auto;
}
<div id="mySidenav" class="sidenav">
  <span id="closebtn" class="closebtn">&times;</span> menu items are hereunder
</div>
<div id="cover" class="cover">
</div>
<div id="maincontent" class="maincontent">
  some elements here<br>
  <img id="open_nav" class="fixed-ratio-resize_menu" src="menu.png" alt="menu"> all the rest of the page is here
</div>
TVBZ
  • 564
  • 1
  • 4
  • 15
  • Done, but I get a completely white page. Such as the cover were full of white and opaque. – gab Apr 21 '19 at 08:17
  • Hi @gab. I'm not sure I understand, please clarify. – TVBZ Apr 21 '19 at 08:28
  • EDIT: Sorry, I had a typo. Now the onclick intercept function runs, but the cover is totally transparent, such as it were rgba(0,0,0,0), while the code says it's rgba( 0,0,0,0.5)... – gab Apr 21 '19 at 08:29
  • Ow yeah. Forgot about that. Check out the css. You had `background: rgba(0, 0, 0, 0) !important;` there. Change it to `background: rgba(0, 0, 0, .5);` and remove the cover background from JS. Try to do most of your styling in CSS instead of JS. – TVBZ Apr 21 '19 at 08:33
  • It was my syntax error: it must be background-color: rgba(0, 0, 0, 0.5); instead of background: rgba(0, 0, 0, 0.5);. – gab Apr 21 '19 at 08:37
  • Do you have any idea to block the y scroll of the maincontent? I mean, if the user is on a smartphone in landscape orientation, he must be free to scroll the sidemenu, but never, despite any orientation, to scroll the maincontent. – gab Apr 21 '19 at 08:40
  • Beside any other considerations, when the y scroll is done, the cover area appears to be limited to the previous displayed area, thus beeing scrolled away : ( – gab Apr 21 '19 at 08:45
  • `Background` and `background-color` should both work the same for this. – TVBZ Apr 21 '19 at 09:24
  • Set `position: fixed;` to the cover area instead of `position: absolute;` Then it will not scroll away. – TVBZ Apr 21 '19 at 09:25
  • You can set the `overflow-Y` in your open and close script. Set it to `hidden` to disable the scroll and to `auto`to enable it. Check out here on [W3Schools](https://www.w3schools.com/jsref/prop_style_overflowy.asp). – TVBZ Apr 21 '19 at 09:29
  • You could **for example** use JS to disable the scroll on `body` element when opening nav to completely disable the scroll in your web page (don't forget to unset it when closing nav). And use a CSS rule `overflow-y: auto;` to `.sidenav` (no need to toggle that). – TVBZ Apr 21 '19 at 09:45
  • "position fixed" runs, but no way to make overflowY change. Nor in "cover" nor in "maincontent" div. The page always scrolls. Now with the cover that extends for the full lenght, but nevertheless it scrolls. – gab Apr 21 '19 at 09:55
  • If I add document.getElementById("body").style.overflowY = "hidden !important"; in the openNav function and run the page, I get "Uncaught TypeError: Cannot read property 'style' of null" – gab Apr 21 '19 at 10:28
  • To get the body, you can simply use `document.body` => `document.body.style.overflowY`. But it would be better practice to define your styles with css classes. Then just add/remove class: `document.body.classList.add("some-class")` & `document.body.classList.remove("some-class")` Check out [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList) or [W3Schools](https://www.w3schools.com/jsref/prop_element_classlist.asp). – TVBZ Apr 21 '19 at 21:15