0

I have this animated retractable menu bar. I made two menu bars. When one slides out when the icon is clicked, the other slides in. I use hidden-sidenav to change the transition delay to zero for the closing nav so the expanding nav will wait 1s for the closing nav to finish retracting.

The transition I don't like is the icon that moves. It is because I have a box-sizing property and padding for each nav bar. I use box-sizing to center the icon. But I want effect like this . Notice how the links in the nav bar stays fixed.

function closeIt(){
  document.getElementById('mysidenav').classList.add('hidden-sidenav');
  document.getElementById('mysidenav2').classList.remove('hidden-sidenav');
}
function openIt(){
  document.getElementById('mysidenav').classList.remove('hidden-sidenav');
  document.getElementById('mysidenav2').classList.add('hidden-sidenav');
}
*{
  margin:0;
  padding:0;
}
html,body{
  height:100%;
  width:100%;
}
.sidenav{
  height:100%;
  width:20%;
  background:#111;
  transition:1s;
  transition-delay:1s;
  transition-timing-function:ease-out;
  overflow-x:hidden;
  box-sizing:border-box;
  padding:calc((20% - 50px)/2);
}
.sidenav a{
  font-size:90px;
  color:#818181;
}
/*SECOND SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIDDDDDDDDDDDDDDDDDDDDEEEEEEE BAR*/
.sidenav2{
  height:100%;
  width:20%; /* Changed to 20%: visible by default. */
  background:#111;
  overflow-x:hidden;
  position:fixed;
  top:0;
  transition:1s;
  transition-timing-function:ease-out;
  transition-delay:1s;
  box-sizing:border-box;
  padding:calc((20% - 50px)/2);
}
.sidenav2 a {
  font-size:50px;
  color:#818181;
}
.hidden-sidenav { /* Must come after .sidenav and .sidenav2 to override them. */
  transition-delay:0s;
  transition-timing-function:ease-in;
  width:0;
  padding:0;
}
<div id='mysidenav'class='sidenav hidden-sidenav'>
  <a onclick='closeIt()'>&times</a>
</div>
    
<div id='mysidenav2'class='sidenav2'>
  <a onclick='openIt()'>&#9776</a>
</div>

1 Answers1

3

In order to make icons fixed, I just added

position:absolute;
left:15px;

to

.sidenav a
.sidenav2 a

Also I removed padding calculations and made positions absolute. Due to font size difference, I also put

top:12px;

to

.sidenav2 a

Hope this helps.

function closeIt(){
  document.getElementById('mysidenav').classList.add('hidden-sidenav');
  document.getElementById('mysidenav2').classList.remove('hidden-sidenav');
  
}
function openIt(){
  document.getElementById('mysidenav').classList.remove('hidden-sidenav');
  document.getElementById('mysidenav2').classList.add('hidden-sidenav');
}


setIconPositions('mysidenav');
setIconPositions('mysidenav2');

function setIconPositions(parentElement) {
var element = document.getElementById(parentElement);
var positionInfo = element.getBoundingClientRect();
var width = positionInfo.width;

var closeIcon = document.getElementById('close-icon');
var openIcon = document.getElementById('open-icon');

closeIcon.style.left = (width/2-getWidthOfText(closeIcon.text, window.getComputedStyle(closeIcon).fontFamily,
window.getComputedStyle(closeIcon).fontSize)/2)+"px";

openIcon.style.left = (width/2-getWidthOfText(openIcon.text, window.getComputedStyle(openIcon).fontFamily,
window.getComputedStyle(openIcon).fontSize)/2)+"px";
}

function getWidthOfText(txt, fontname, fontsize){
    if(getWidthOfText.c === undefined){
        getWidthOfText.c=document.createElement('canvas');
        getWidthOfText.ctx=getWidthOfText.c.getContext('2d');
    }
    getWidthOfText.ctx.font = fontsize + ' ' + fontname;
    return getWidthOfText.ctx.measureText(txt).width;
}
*{
  margin:0;
  padding:0;
}
html,body{
  height:100%;
  width:100%;
}
.sidenav{
  height:100%;
  width:30%;
  background:#111;
  transition:1s;
  transition-delay:1s;
  transition-timing-function:ease-out;
  overflow-x:hidden;
  box-sizing:border-box;
  position:absolute;
  top:0;
}
.sidenav a{
  font-size:90px;
  color:#818181;
  position:absolute;
}


/*SECOND SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIDDDDDDDDDDDDDDDDDDDDEEEEEEE BAR*/
.sidenav2{
  height:100%;
  width:30%; /* Changed to 20%: visible by default. */
  background:#111;
  overflow-x:hidden;
  position:absolute;
  top:0;
  transition:1s;
  transition-timing-function:ease-out;
  transition-delay:1s;
  box-sizing:border-box;
}
.sidenav2 a {
  font-size:50px;
  color:#818181;
  top:12px;
  position:absolute;
}
.hidden-sidenav { /* Must come after .sidenav and .sidenav2 to override them. */
  transition-delay:0s;
  transition-timing-function:ease-in;
  width:0;
  padding:0;
}
<div id='mysidenav'class='sidenav hidden-sidenav'>
  <a id="close-icon" onclick='closeIt()' class='hidden-sidenav'>&times</a>
</div>
    
<div id='mysidenav2'class='sidenav2'>
  <a id="open-icon" onclick='openIt()' class='hidden-sidenav'>&#9776</a>
</div>
Sefa
  • 370
  • 2
  • 11
  • But then the icon isn't responsively centered. – most venerable sir Sep 01 '17 at 22:44
  • Can you at least make it horizontally centered – most venerable sir Sep 01 '17 at 22:44
  • OK, I updated my answer. In order to calculate center position dynamically, you need to calculate both width of the icons and page. After that, I set that dynamically calculated size to left property of icons. – Sefa Sep 02 '17 at 12:02
  • could you please comment getWidthOfText function? Is it a function you created or does it already come with Java, because I see you use it inside of itself (ie, in the if statement). What is c and ctx? – most venerable sir Sep 05 '17 at 15:47
  • 1
    It's a custom function. You can get further information here: https://stackoverflow.com/questions/2057682/determine-pixel-length-of-string-in-javascript-jquery Obviously width of the text changes with font type and font size. So getWidthOfText function calculates rendered width of a given text with provided font type and font size. Briefly, it creates a canvas and makes calculations using measureText pre-defined function. We do this because initially we get width of the left menu, then we get the width of the icon then set its left position to middle by calculating (menuwidth-iconwidth)/2 – Sefa Sep 06 '17 at 08:38