0

I'm building a drop down menu for a project I'm working on, but I don't get it working entirely as is should. I want it to show the sub-menus when I hover the root-level menus, and then close again after a short delay when the menu or sub-menu is not hovered anymore. Most of it works; the sub-menus are showed when root-level items are hovered and it is hidden when I stop hovering the root-level item. The problem is that the sub-menus are also hidden when I move my cursor from the root-level item to a sub-menu item other than the first and hover that. This is obviously not good, so help would be appreciated.

I created a JSFiddle with the code which shows the issue more clearly.

So, here's my code:

menu.htm

<div id=m_wrapper>
    <ul id=menu>
        <li onMouseOver="show_sub_menu('0')" onMouseOut="start_timer()">Item 1
            <div id=s0 onMouseOver="show_sub_menu('0')" onMouseOut="start_timer()">
                <a href=#>Item 1.1</a>
                <a href=#>Item 1.2</a>
                <a href=#>Item 1.3</a>
            </div>
        </li>
    </ul>
</div>

menu.css

#m_wrapper {
    position:relative;
    display:table;
}
#menu {
    position:relative;
}
#menu li {
    width:100px;
    position:relative;
    float:left;
    list-style-type:none;
}
#menu div {
    position:absolute;
    visibility:hidden;
    display:inherit;
    width:100%;
    z-index:30
}
#menu div a {
    position:relative;
    display:block;
    z-index:35;
}

menu.js

var countdown = 300;
var timer = null;
var menu_item = null;

window.show_sub_menu = function(cath) {
    if (menu_item) {
        menu_item.style.visibility = 'hidden'; //Make sure to show one menu at a time
    }

    menu_item = window.document.getElementById("s" + cath);
    menu_item.style.visibility = 'visible'; //Show menu

    if (timer) {
        window.clearTimeout(timer); //Reset timer, so menu is kept open
        timer = null;
    }
};

window.start_timer = function() {
    timer = window.setTimeout(close_sub_menu, countdown);
};

window.close_sub_menu = function() {
    menu_item.style.visibility = 'hidden';
};
EscalatedQuickly
  • 400
  • 4
  • 22
  • Do you want pure javascript? is jQuery preferrable? – Dhaval Marthak Apr 18 '13 at 11:16
  • @The-Val: I have never worked with jQuery before to be honest, so pure javascript would be best. – EscalatedQuickly Apr 18 '13 at 11:21
  • 1
    You should start using little bits of jQuery. The selectors are much easier to read, they're basically the same as css e.g. `$('#id')` selects the element with the id "id" `$('.class')` selects all elements with the class "class" `$('.class li)` selects all li inside elements with the class "class". – gaynorvader Apr 18 '13 at 11:23
  • @Psyberion Can i change your HTML somehow to achieve this one? i mean for the demo purpose, then you can modify it as per your convinience. :) – Dhaval Marthak Apr 18 '13 at 11:25
  • @The-Val: Go ahead! I appreciate any help! :) – EscalatedQuickly Apr 18 '13 at 11:27
  • @gaynorvader: I see! As I mentioned before, I have never worked with it before, but I should probably look into it. I don't really have the time now I'm afraid.. But thanks! – EscalatedQuickly Apr 18 '13 at 11:28
  • what differ between this and your code http://jsfiddle.net/dolours/mTa6j/ – Dolo Apr 18 '13 at 11:29
  • @Dolours there is no difference, as we both have replied in that thread :) – Dhaval Marthak Apr 18 '13 at 11:33
  • @Psyberion See this link, i have achieved this one using `jQuery` http://stackoverflow.com/questions/16059593/hover-content-of-a-hover/16060088?noredirect=1#comment22919456_16060088 – Dhaval Marthak Apr 18 '13 at 11:35
  • @Psyberion: I appreciate that, I was in the same boat for a long time until someone pointed out how easy the selectors were to use, then I slowly started building up my knowledge from there. – gaynorvader Apr 18 '13 at 11:36
  • @gaynorvader: Yes, I can clearly see how it would be good to know JQuery. But you gotta start somewhere, and since it's based on JavaScript that might be good to know first :) – EscalatedQuickly Apr 18 '13 at 12:45

5 Answers5

1

first of all You should avoid <div> in <li> tags, because is not semantic.

Quite good is multi level menu build only with html and css styles.

HTML

 <div id=m_wrapper>
     <ul id=menu>
            <li>Item 1
                <ul>
                    <li><a href=#>Item 1.1</a></li>
                    <li><a href=#>Item 1.2</a></li>
                    <li><a href=#>Item 1.3</a></li>
                </ul>
            </li>
            <li>Item 2</li>
     </ul>
 </div>

CSS STYLES

#m_wrapper, #menu, #menu li  {
    position:relative; 
}
#m_wrapper {
    display:table; 
}
#menu li {
    float:left;
    width:100px;
    list-style-type:none;
}
#menu li ul {
    display: none;
}
#menu li:hover ul {
    display: block;
    margin: 0 10px;
    padding: 0;
}
Bartek Bielawa
  • 562
  • 4
  • 10
1

you don't have to make it that complex.

ofcourse you can do same through javascript, but see how easy, readable and simple it is through jQuery.

See this DEMO

Just use following script

$('#menu li').hover(
    function(){
            $(this).stop().animate({height: '100px'},1000,function(){});
            $(this).find('div').show(600);
        }//gets called upon mousehover
    ,
    function(){
            $(this).stop().animate({height: '20px'},1000,function(){});
        } //gets called upon mouseout
  ); //hover ends

and also, I don't know why you have written tonns of CSS. Just use these:

#menu
{
    list-style:none;
}
#menu li
{
    width:100px;
    border:1px Solid #CCC;
    text-align:Center;
    cursor:pointer;
    height:20px;
    overflow:hidden;

}
#menu li div
{
    border:1px Solid #CCC;
}
#s0 
{
    height:auto;
}
#s0 a
{
    display:block;
}

There's plenty you can do through it, like selected dropdown item. selection through arrow key and what not. jQuery makes it simple for you.

Manish Mishra
  • 12,163
  • 5
  • 35
  • 59
1

This can quite easily be achieved with HTML and CSS alone. Using CSS transitions we can make the menu fade when we hover off.

Example

I have also put this on JsFiddle

HTML

<nav>
    <ul id="menu">
        <li>
            <a href="#">Home</a>
            <ul>
            <li>Item1</li>
            <li>Item2</li>
            <li>Item3</li>                                
            </ul>
        </li>
        <li><a href="#">About</a></li>
        <li><a href="#">Contact</a></li>
    </ul>
</nav>

CSS

#menu li
{
    position: relative;  
    display: inline;
    list-style: none;
    padding-left: 15px;  
}

#menu ul
{
    margin: 0;
    padding: 0;
    list-style: none;    
    opacity: 0;
    position: absolute;
    top: 20px;
    left: 5px;
    // Transitions for our fade effect.
    -webkit-transition: opacity 2s ease-in-out; 
    -moz-transition: opacity 2s ease-in-out;
    -ms-transition: opacity 2s ease-in-out;
    -o-transition: opacity 2s ease-in-out;
    transition: opacity 2s ease-in-out;   
}

#menu ul li
{
    display: block;    
}

#menu li:hover > ul
{
    opacity: 1;    
    // This stops the transition from happening on hover.
    -webkit-transition: none; 
    -moz-transition: none;
    -ms-transition: none;
    -o-transition: none;
    transition: none;
}
Colin Bacon
  • 15,436
  • 7
  • 52
  • 72
1

A pure CSS drop down menu

http://jsfiddle.net/steelywing/GANeX/8/

.nav {
    background-color: #def;
    height: 20px;
}

.nav * {
    transition: all 0.4s ease 0s;
    -moz-transition: all 0.4s ease 0s;
    -webkit-transition: all 0.4s ease 0s;
    -o-transition: all 0.4s ease 0s;
}
li {
    display: inline-block;
    height: 20px;
}

.dropdown li {
    display: block;
}

.dropdown ul {
    visibility: hidden;
    opacity: 0;
    margin-top: -2px;
}

.dropdown:hover ul {
    visibility: visible;
    opacity: 1;
}
Steely Wing
  • 16,239
  • 8
  • 58
  • 54
0

Remember that.. if You decide to implement the fade version, You should use crosbrowser opacity, like this:

 -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
 filter: alpha(opacity=100);
 -moz-opacity: 1;
 -khtml-opacity: 1;
 opacity: 1;
Bartek Bielawa
  • 562
  • 4
  • 10