1

I have crafted a pure css toggle menu but noticed it does not work on iOS safari, so after much frustration have decided to make it toggle with Javascript instead. Only problem is I barely have any experience using Javascript, have looked for how-to's online but have had much difficulty getting any of them to work, and i think what i have here is fairly simple as there are no sub menus.

Was wondering if anybody knew an easy way to get this menu to work with Javascript so that the toggle on/off happens with the click of a mouse and also works on most mobile browsers.

The current menu on codepen is here:

http://codepen.io/lemmiwink5/pen/JoKmJb

HTML
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">        

<header class="menu">
  <div tabindex="0" class="drop-menu">
    <i class="fa fa-bars" ></i>   
    <ul class="drop-menu-content">
      <i class="fa fa-sort-asc"></i>
      <li><a href="#">Home</a></li>
      <li><a href="#">Lorem</a></li>
      <li><a href="#">Ipsum</a></li>
      <li><a href="#">Check</a></li>
    </ul>
  </div> 
</header>

CSS
.menu {
    height: 40px;
    width: 40px;
    margin-left: 20px;
    margin-top: 17px;
    position: fixed;
    z-index: 1;
}
.drop-menu {
    position: relative;
    display: inline-block;
    outline: 0;
}
.drop-menu i.fa-bars {
    padding-right: 30px;
    padding-bottom: 14px;
    transition: opacity .2s ease-in-out;
    color: #000;
    font-size: 27px;
}
.drop-menu .fa-bars:hover {
    opacity: 0.6;
}
.drop-menu:focus {
    pointer-events: none;
}
.drop-menu:focus .drop-menu-content {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}
.drop-menu-content {
    position: absolute;
    z-index: 1;
    width: 200px;
    padding: 0;
    background-color: #eee; 
    height: auto; 
    border-radius: 5px;  
    opacity: 0;
    visibility: hidden;
    transition: visibility .5s;
    margin: 0 0 0 -6px;
}  
.drop-menu-content li {
    margin: 5px;
    display: block;
    position: relative;
}
.drop-menu-content li:hover {
    background-color: #222;
}
.drop-menu-content a:hover {
    color: #fff;
}
.drop-menu-content i.fa-sort-asc {
    color: #eee;
    font-size: 30px;
    position: absolute;
    top: -10px;
    left: 10px;
} 
.drop-menu-content a {
    text-decoration: none;
    color: #000;
    padding: 10px 15px;
    display: block;
}

Thanks in advance to anyone and everyone who can help out.

EDIT: New code:

<html>
    <head>
        <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
        <style>
        /*Menu dropdown*/
.drop-menu i.fa-bars {
    padding-right: 30px;
    padding-bottom: 14px;
    transition: opacity .2s ease-in-out;
    color: #fff;
    font-size: 27px;
}
.drop-menu .fa-bars:hover {
    opacity: 0.6;
}
.drop-menu {
    position: relative;
    display: inline-block;
    margin-left: 30px;
    margin-top: 20px;
}
.drop-menu-content {
    position: absolute;
    z-index: 1;
    width: 200px;
    padding: 0;
    background-color: #fff; 
    width: 200px; 
    height: auto; 
    border-radius: 5px;  
    visibility: hidden;
    opacity: 0;
    transition: visibility .5s;
}  
.drop-menu-content li {
    margin: 5px;
    display: block;
    position: relative;
}
ul.drop-menu-content li:hover {
    background-color: #222;
}
ul.drop-menu-content a:hover {
    color: #fff;
}
.drop-menu-content i {
    color: #fff;
    font-size: 30px;
    position: absolute;
    top: -10px;
    left: 10px;
} 
.drop-menu-content a {
    text-decoration: none;
    color: #000;
    padding: 10px 15px;
    display: block;
}
        </style>  
    </head>
    <body>
        <header class="menu">
                <div tabindex="0" class="drop-menu">
                    <i class="fa fa-bars" ></i>   
                    <ul class="drop-menu-content">
                      <i class="fa fa-sort-asc"></i>
                      <li><a href="#">Home</a></li>
                      <li><a href="#">Lorem</a></li>
                      <li><a href="#">Ipsum</a></li>
                      <li><a href="#">Check</a></li>
                    </ul>
                </div>
            </nav>
        </header>
        <script>
            var dropMenu = 0;
            var toggling = false;
            var opacity = 0;
            var menu = document.getElementsByClassName("drop-menu-content");
            window.onload = function() {
                menu.style.opacity = 0;
            }
            function toggle() {
                current = document.getElementsByClassName("drop-menu-content");
                function frame() {
                    if(dropMenu == true) {
                        opacity -= 10;
                        menu[0].style.opacity = opacity / 100;
                    } else {
                        opacity += 10;
                        menu[0].style.opacity = opacity / 100;
                    }
                    if(opacity === 0) {
                        dropMenu = Math.Abs(dropMenu - 1);
                        toggling = false;
                        clearInterval(intervalId);
                    }
                }
                if(!toggling) {
                    toggling = true;
                    var intervalId = setInterval(frame,16);
                }
            }
        </script>
    </body>
</html>

Can't seem to figure out why it isn't working. Just incase you are wondering why everything is in-line, It's because i am creating a tumblr theme :).

2
  • 1
    <i> is not a valid child of <ul>. May be causing browser issues Commented Dec 20, 2014 at 5:24
  • Are you experiencing any specific issues on mobile browsers? I can't really tell from your code. Commented Dec 20, 2014 at 5:30

2 Answers 2

1

Here is how I would make this toggle menu in Javascript, and this will also add some nice fade effect to it.

var dropMenu = 0;
var toggling = false;
var opacity = 0;
var menu = document.getElementsByClassName("drop-menu-content");
window.onload = function() {
    menu.style.opacity = 0;
}
function toggle() {
    function frame() {
        if(dropMenu == true) {
            opacity -= 10;
            menu[0].style.opacity = opacity / 100;
        } else {
            opacity += 10;
            menu[0].style.opacity = opacity / 100;
        }
        if(opacity === 0 || opacity === 100) {
            dropMenu = Math.Abs(dropMenu - 1);
            toggling = false;
            clearInterval(intervalId);
        }
    }
    if(!toggling) {
        toggling = true;
        var intervalId = setInterval(frame,16);
    }
}

So when the menu button is clicked, all you have to do is call the toggle() function and the menu should fade in if it has not or fade out. Pretty much what this does is creates an interval, meaning the 60 times per second (as calculated that 16 milliseconds * 60 is close to 1000) the frame() function is called, which will gradually change the opacity (transparency) of the window.

Sign up to request clarification or add additional context in comments.

2 Comments

Hi Gwiddle Worker. Thanks for that answer, I have added the script into my css sheet in between <script></script> tags just before the closing body but cannot seem to get it to work. Am i also supposed to make further changes in my CSS or HTML ? I know it's quite amateurish what I am asking but i do appreciate your patience, I have just finished a css and html course about 2 weeks ago so will be learning JS soon. My current code i have added as an edit in my question.
I'm sure I made a small error somewhere (I have written very similar code many times and this time I particularly did not fully test it). First off did you add an onclick='toggle()' event to the button? I made a couple edits to the code.
0

You do not need to bother with doing much JS. You can more or less go back to your old method. On top of your hover assignments, assign your hover style(s) to a CSS class; e.g. .hover-class; and bind an event to change the class on touchstart and touchend.

function touchHover(element, mouseenter, mouseleave) {
    element.addEventListener('touchstart', mouseenter, false);
    element.addEventListener('touchend', mouseleave, false);
}

function startHover() {
    this.className += ' hover-class';
}

function endHover() {
    this.className = this.className.replace('hover-class', '');
}

if ("ontouchstart" in window) {
    touchHover(document.getElementById('menu'), startHover, endHover);
}

One of the benefits of this code is that you will not have to make any edits to the JS aside from adding the classes and appending this code to the bottom of your page. No need to add the function to an onClick handler to the HTML - it adds the events programmatically and they can be edited in one place.

3 Comments

Thanks for the help Makaze :) wish i could give 2 answers, but I have to credit that to Gwiddle just by default because he answered first :)
For future reference, you should go with the best solution, not the first one. No problem, but be sure to use the best answer you can get--it's your question.
My Bad Makaze, thanks for the tip, I will not forget :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.