Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Making the sub-options hide when making a css dropdown menu 2

Status
Not open for further replies.

krigbert

Programmer
Jun 2, 2005
95
NO
I'm sort-of following a tutorial from "a list apart"for making css-dropdowns ( ), but even though I've written

Code:
	#nav li ul {
	    display: none;
    }

The sub options simply won't dissappear.

Also, how can you make the hover state of one thing affect something else?
 
Thats if they have ID's
eg
Code:
<div ID="li">test1</div>
else, use
Code:
<style> 
#nav,li,ul{  
     display: none;
           }
</style>
If they're
Code:
<li>test   <ul>test2
 
This might help you


It's a bastardised, cobbled together version of the SuckerFish dropdown technique outlined on ALA.

Basically, you want to be using the :hover psuedoclass. The browser will then take care of the showing/hiding all by itself.

By using the cascading nature of CSS you can specify things like:

Code:
#mainNavigation li:hover ul { 
	display: block;
	background:transparent;
}

What this says is, "for any <ul> element within an <li> element that is being hovered over - show the <ul> element"

So with a structure like this:
Code:
<ul>
  <li>Menu Item 1
    <ul>
       <li>Sub menu item</li>
       <li>Sub menu item</li>
       <li>Sub menu item</li>
    </ul>
  </li>
  <li>Menu Item 2</li>
  <li>Menu Item 3</li>
</ul>

It is possible to reference the submenu as it is a <ul> INSIDE an <li> element. Therefore the above mentioned bit of CSS will show/hide the submenu when it's parent <li> is hovered over.

The nice thing is, you don't need to code anything to hide it, the hover psuedoclass takes care of that.

Now the problem. IE only supports the hover psuedoclass for <a> elements.

The SuckerFish dropdown technique that I used in the example above includes some javascript that allows IE to simulate the hover psuedoclass. It's only about 20 lines if I recall correctly.

Foamcow Heavy Industries - Web design and ranting
Target Marketing Communications - Advertising, Direct Marketing and Public Relations
I wonder what possesses people to make those animated gifs. Do you just get up in the morning and think, "You know what web design r
 
In reply to Foamcow:

I know how to make the stuff appear again, the trouble is getting it to dissappear in the first place :p

That's also why I asked how you can make the hover state of one thing affect another. I was thinking of using css rollovers and using a transparant gif-image with links to # on them and hover states to make the sub-options appear.

Sorry if I'm not being clear.

Now, replying to Tommy:

It's like this:

Code:
    <ul id="nav">
	    <li><a href="#">Design Services</a></li>
	    <ul>
		  <li><a href="#"> Product Design </a>|</li> 

et.c.

When I put one or both commas in, per your tip, everything dissappears, without the commas, everything's there. What I want is "design services" and all the other nav li's to be there while the "Product design" and all the other nav li ul li's go away.

Also: the reason I want to use CSS is to avvoid JavaScript. If not, I could just download any of the bajillions of JavaScript dropdown menus that are available in tutorials online :p
 
You were being clear :)

Perhaps I wasn't.

Set the submenus to be hidden using this

Code:
#mainNavigation li ul {
    display: none;
}

This will, by default, set any <ul> element that is INSIDE an <li> element to be invisible. In fact, it won't exist at all so won't take up any space in the layout either.


Then, using the CSS psuedoclass :hover we can make it appear

Code:
#mainNavigation li:hover ul {
    display: block;
}

That says, "When the mouse is over an <li> element which CONTAINS a <ul>, change the display property of the <ul> to block (visible+occupying space)".


We don't need to worry about hiding it again, as when the mouse ISN'T in the <li> the <ul> reverts back to having a display property of "none".

This works in standards compliant browsers like Firefox, but won't work in IE. This is because IE ONLY understands the :hover psuedoclass for <a> elements.

Therefore, we use Javascript to cycle through the DOM and "tweak" it to allow us to imitate the hover behaviour.


Foamcow Heavy Industries - Web design and ranting
Target Marketing Communications - Advertising, Direct Marketing and Public Relations
I wonder what possesses people to make those animated gifs. Do you just get up in the morning and think, "You know what web design r
 
Also: the reason I want to use CSS is to avvoid JavaScript. If not, I could just download any of the bajillions of JavaScript dropdown menus that are available in tutorials online :p

Not really true.
Many of the "bajillions of Javascript dropdowns" use javascript to actually perform the link action. This means they will not function with non js enabled clients. Also the links will not be followed by search engines crawlers etc.

Using Javascript in the way I described will not effect the ability for links within the site to be followed as they are still conventional links. The js only serves to mimic a behaviour that IE doesn't properly support (yet).

Foamcow Heavy Industries - Web design and ranting
Target Marketing Communications - Advertising, Direct Marketing and Public Relations
I wonder what possesses people to make those animated gifs. Do you just get up in the morning and think, "You know what web design r
 
You're wrong, I wasn't being clear :D

While your post did make some things clearer in my mind, it didn't say anything but what I intended to do. So I'm guessing I've mucked up somewhere in my code, but I can't seem to find it.

Here's what's in the html document:

Code:
<div id="container">
    <ul id="nav">
	    <li><a href="#">Design Services</a></li>
	    <ul>
		  <li><a href="#"> Product Design </a>|</li> 
		  <li><a href="#"> Development</a> |</li>
		  <li><a href="#"> Production</a></li>
		</ul>
		<li><a href="#">Products</a></li>
		<ul>
		    <li><a href="#">Products1 </a>|</li>
			<li><a href="#"> Products2 </a>|</li>
			<li><a href="#"> Products3</a></li>
	    </ul>
		<li><a href="#">Components</a></li>
		<ul>
		    <li><a href="#">Click</a></li>
		</ul>
		<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#">Projects</a></li>
		<ul>
		    <li><a href="#">Finished Projects</a> |</li>
			<li><a href="#"> Ongoing Projects</a> |</li>
			<li><a href="#"> Polka striped bananas with hats</a></li>
		</ul>
		<li><a href="#">Contact</a></li>
		<ul>
		    <li><a href="#">Email us</a> |</li>
			<li><a href="#"> View contact information</a></li>
	    </ul>
	</ul>
	</div>
Yes it contains some placeholder text :p

Here's what's in the css document:

Code:
	#nav {
		position: relative;
		top: 0px;
		height: 56px;
		width: 597px;
	}
	
	#nav li ul {
	    display: none;
		position: relative;
		top: 20px;
		left: 0px;
		padding-top: 10px;
    }
	
    #nav li ul a{
	  float: left;
      width: auto;
      margin-right: 15px;
	}
	nav li:hover ul{
	    display: block;
		z-index: 6000;
	}
	

#nav li.ona:hover, #nav li.on:hover a {
  background: #29497b;
}

  

	#nav li a{
	    font:Verdana, Arial, Helvetica, sans-serif;
	    display: block;
		font-size: 10px;
    }

Now, if I place a comma between li and ul in the #nav li ul line, it all dissappears, but as it is now, everyhing is there. I'm seriously not getting it :|
 
You are correct, it disappears and should disappear. Because putting a comma between them means ennumerating them. Basically what you are saying is: #nav, li and ul should have this setting. Since that setting is [tt]display: none;[/tt] everything disappears. Nice and simple. Without the commas, it means something completely else. It means that ul element that lies inside the li element that lies inside #nav element should have that settings. That makes only the inner uls disappear.

Let's move on. [tt]nav li:hover ul[/tt] is erroneous. It claims that ul element inside a li element (which has a mouse pointer over it) inside a nav element should do something. However, there is no nav element in html and you don't have a nav element in your code. Correctly, that line should read [tt]#nav li:hover ul[/tt]. This way it means any element with an id of nav, which equates to your top ul. Almost there.

[tt]#nav li.ona:hover, #nav li.on:hover a[/tt]. This declaration plays no role in the code as it relates to a link element within a li element with a class called on when it is hovered over by the mouse and another li element with a class of ona (again howevered). Your html code has no classes applied to li elements, so this will never be executed.

Lastly, please understand that your code will only work in modern standards compliant browsers (around 15% of the market) and not on any of the IE versions (most of the remaining market share). IE does not support :hover state for anything but a element, as I believe FoamCow has stated many times so far.
 
Your subnavs are outside your list elements.
Try this
Code:
<div id="container">
    <ul id="nav">
        <li><a href="#">Design Services</a>
          <ul>
            <li><a href="#"> Product Design </a>|</li>
            <li><a href="#"> Development</a> |</li>
            <li><a href="#"> Production</a></li>
          </ul>
        [COLOR=red]</li>[/color]
        <li><a href="#">Products</a>
          <ul>
              <li><a href="#">Products1 </a>|</li>
              <li><a href="#"> Products2 </a>|</li>
              <li><a href="#"> Products3</a></li>
          </ul>
        [COLOR=red]</li>[/color]
        <li><a href="#">Components</a>
          <ul>
              <li><a href="#">Click</a></li>
          </ul>
        [COLOR=red]</li>[/color]
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#">Projects</a>
          <ul>
              <li><a href="#">Finished Projects</a> |</li>
              <li><a href="#"> Ongoing Projects</a> |</li>
              <li><a href="#"> Polka striped bananas with hats</a></li>
          </ul>
        [COLOR=red]</li>[/color]
        <li><a href="#">Contact</a>
          <ul>
              <li><a href="#">Email us</a> |</li>
              <li><a href="#"> View contact information</a></li>
          </ul>
        [COLOR=red]</li>[/color]
    </ul>
    </div>

That way your sub <ul>'s are children of your <li> elements and the CSS I posted should work with them.

Foamcow Heavy Industries - Web design and ranting
Target Marketing Communications - Advertising, Direct Marketing and Public Relations
I wonder what possesses people to make those animated gifs. Do you just get up in the morning and think, "You know what web design r
 
Cheers Vrag.

Krigbert,
Get it working in FF etc and then I'll post the JS to get it working in IE.

Alternately, look at the example page I linked to way back up there and just take the code as a starting point.
Then mess with the CSS and see what happens.
That's a good way to learn!

Foamcow Heavy Industries - Web design and ranting
Target Marketing Communications - Advertising, Direct Marketing and Public Relations
I wonder what possesses people to make those animated gifs. Do you just get up in the morning and think, "You know what web design r
 
Thanks for the help :) Seems it was just messy code after all. As for the IE thing, I knew about that, that's one of the reasons I asked "how can you make the hover state of one thing affect something else?" in my first post.

What I thought to do was to use the main options' a elements to make the other options change. Or to illustrate with some code that doesn't work:

Code:
	#nav li a:hover ul{
	    display: block;
	    z-index: 6000;
	}

I now think I know why that doesn't work (the ul element obviously isn't nested within the a element :p) but hopefully it gets my point across. I'm guessing that there is no way (at least no pure css way) of making that work?

Current state:

The htm (well, actually it's php) file contains what foamcow posted. The css file is like this after a bit of cleaning:

Code:
	#nav {
		position: relative;
		top: 0px;
		height: 56px;
		width: 597px;
	}
	#nav li{
	        float: left;
		display: block;
		height: 30px;
	}
	
	#nav li ul {
	        display: none;
		position: absolute;
		top: 15px;
		left: 0px;
		padding-top: 10px;
		height: 30px;
    }
	
    #nav li ul a{
	  float: left;
          width: auto;
          margin-right: 15px;
	  color:#0099CC;
	}
	
	#nav li:hover ul{
	        display: block;
		z-index: 6000;
		color: #000000;
	}

	#nav li a{
	        font:Verdana, Arial, Helvetica, sans-serif;
		color:#000000;
		text-decoration: none;
	        display: block;
		font-size: 10px;
    }
	
	#nav li a:hover{
	    color:#0099CC;
	}

Thanks for all the help so far, I think I've really gotten a better understanding of css now :)
 
Argh, sorry to ressurect the old thread, but could you post that JavaScript? I tried the stuff from ALA, but it doesn't seem to work.



The stuff from ALA:

Code:
startList = function() {
if (document.all && document.getElementById) {
navRoot = document.getElementById("nav");
for (i=0; i<navRoot.childNodes.length; i++) {
  node = navRoot.childNodes[i];
  if (node.nodeName=="li") {
  node.onMouseOver=function() {
  this.className+="over";
    }
  node.onMouseOut=function() {
  this.className=this.className.replace
      ("over", "");
   }
   }
  }
 }
}
window.onload=startList;

Also:
Code:
	#nav li:hover ul, #nav li.over ul{
	    display: block;
		z-index: 6000;
		color: #C0BFBE;
	}

	#nav li a:hover, #nav li:hover a, #nav li.over a{
	    color:#0099CC;
	}
 
It's the same script.

It does work. Although I had problems with it in the past.

Carefully check the id's of your elements.
That version of the script is looking for elements inside an element called "nav". If your navigation elements are in a differently named element then it won't work.

Foamcow Heavy Industries - Web design and ranting
Target Marketing Communications - Advertising, Direct Marketing and Public Relations
I wonder what possesses people to make those animated gifs. Do you just get up in the morning and think, "You know what web design r
 
All divs are the same name as in the example. Everything is lowercase, even. I also checked if the css worked by giving one of the li's the over class (li class="over"), and it worked.
 
Er, don't misinterpret that as "the menu worked", btw, because it certainly didn't. What happened was that the sub-options of that particular li showed - the mouseovers still don't work...
 
Afraid not, but here's an abbreviated version of everything. The HTML document:
Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"  "[URL unfurl="true"]http://www.w3.org/TR/html4/strict.dtd">[/URL]


    <script type="text/JavaScript" src="js.js"></script>
    <link href="meny.css" rel="stylesheet" type="text/css">
<div id="container">
    <ul id="nav">
	    <li><a href="#" onMouseOver="this.className+='over'">Design Services&nbsp;</a>
	      <ul>
		  <li><a href="#"><img src="images/graa.gif" width="1px" height="10px" alt="seperator">&nbsp;Product Design</a></li> 
		  <li><a href="#"><img src="images/graa.gif" width="1px" height="10px" alt="seperator">&nbsp;&nbsp;Development</a></li>
		  <li><a href="#"><img src="images/graa.gif" width="1px" height="10px" alt="seperator">&nbsp;&nbsp;Production</a></li>
		  </ul>
		</li>
        </ul>
    </div>
js.js:

Code:
//Fixing the menu for ie

startList = function() {
if (document.all && document.getElementById) {
navRoot = document.getElementById("nav");
for (i=0; i<navRoot.childNodes.length; i++) {
  node = navRoot.childNodes[i];
  if (node.nodeName=="LI") {
  node.onMouseOver=function() {
  this.className+="over";
    }
  node.onMouseOut=function() {
  this.className=this.className.replace
      ("over", "");
   }
   }
  }
 }
}
window.onload=startList;

menu.css:
Code:
#container {
	width: 597px;
	height: 56px;
	top: 34px;
	*top: 50px;
	left: 50%;
	margin-left: -501px;
	z-index: 310;
	position: absolute;
}

	#nav {
		position: relative;
		top: 0px;
		height: 56px;
		width: 800px;
		font-family: Verdana, Arial, Helvetica, sans-serif;
	}
	#nav li{
	    float: left;
		display: block;
		height: 30px;
	}
	
	#nav li ul {
	    display: none;
		position: absolute;
		top: 15px;
		left: 10px;
		padding-top: 10px;
		height: 30px;
		width: 600px;
    }
	
    #nav li ul a{
	  float: left;
      width: auto;
      margin-right: 15px;
	  color:#0099CC;
	}
	
	#nav li:hover ul, #nav li.over ul{
	    display: block;
		z-index: 6000;
		color: #C0BFBE;
	}

	#nav li a{
	    font: Verdana, Arial, Helvetica, sans-serif;
		color:#000000;
		text-decoration: none;
	    display: block;
		font-size: 12px;
    }
	
	#nav li a:hover, #nav li:hover a, #nav li.over a{
	    color:#0099CC;
	}

Hope posting as big chunks of code as this is allowed :p
 
Problem was solved by me in a very unelegant way by turning the <li>s into <li onMouseOver="this.className+=' over';" onmouseout="this.className=this.className.replace(' over', 'hide');">

It's clumsy, but it works.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top