views:

887

answers:

4

I'm trying to create a two-level horizontal navigation menu (or menubar) that displays the child submenu items when you hover over the parent menu item. If one of the child items is selected, the parent item has a visual indicator that the current page corresponds to one of its child items, and its child items remain displayed.

Child2 is current page:

parent1  *parent2*   parent3
             |
  child1  *child2*  child3

When I hover over parent1 or parent3, their children are displayed as desired. My challenge is that I can't figure out how to hide parent2's children when the other parents' children are being displayed. Is there a CSS way to accomplish this? I know I can use jquery to hide parent2's children when mousing out of parent2 and parent2's children, but I'd rather not have to use javascript for maximum usability.

Here is a live example

CSS:

ul.AspNet-Menu 
{
    position: relative;
}

ul.AspNet-Menu, 
ul.AspNet-Menu ul
{
    margin: 0;
    padding: 0;
    display: block;
}

ul.AspNet-Menu li
{
    position: static;
    list-style: none;
    float: left;
}

ul.AspNet-Menu li a,
ul.AspNet-Menu li span
{
    display: block;
    text-decoration: none;
}
ul.AspNet-Menu ul
{
    visibility: hidden;   
    position: absolute;
}

ul.AspNet-Menu li:hover ul ul,
ul.AspNet-Menu li.AspNet-Menu-Hover ul ul
{
    visibility: hidden;
}

ul.AspNet-Menu li:hover ul,
ul.AspNet-Menu li li:hover ul,
ul.AspNet-Menu li li li:hover ul,
ul.AspNet-Menu li.AspNet-Menu-Hover ul,
ul.AspNet-Menu li li.AspNet-Menu-Hover ul,
ul.AspNet-Menu li li li.AspNet-Menu-Hover ul
{
    visibility: visible;
}

.main-nav2 .AspNet-Menu-Horizontal{
  margin: 0;
  padding: 0;
  font: bold 13px/16px Arial, sans-serif;
  position: absolute;
  top: 21px;
  left: 290px;
}

.main-nav2 ul.AspNet-Menu li {
  display: inline;
}

.main-nav2 ul.AspNet-Menu li a,
.main-nav2 ul.AspNet-Menu li span.AspNet-Menu-NonLink {
  color: #fff;
  background: url(../../nav-bg.gif) no-repeat 0 -24px;
  height: 24px;
  text-decoration: none;
  margin: 0 1px 0 0;
}

.main-nav2 ul.AspNet-Menu li a span,
.main-nav2 ul.AspNet-Menu li span.AspNet-Menu-NonLink span {
  background: url(../../nav-bg-right.gif) no-repeat 100% -24px;
  padding: 4px 12px 4px 12px;
  cursor: pointer;
}

.main-nav2 ul.AspNet-Menu li a:hover,
.main-nav2 ul.AspNet-Menu li a.active {
  background-position: 0 0;
  color: #1b8db3;
}

.main-nav2 ul.AspNet-Menu li a:hover span,
.main-nav2 ul.AspNet-Menu li a.active span {
  background-position: 100% 0;
}

.main-nav2 ul.AspNet-Menu li.AspNet-Menu-Selected a,
.main-nav2 ul.AspNet-Menu li.AspNet-Menu-ChildSelected a
{
  background-position: 0 0;
  color: #1b8db3;
}

.main-nav2 ul.AspNet-Menu li.AspNet-Menu-Selected a span,
.main-nav2 ul.AspNet-Menu li.AspNet-Menu-ChildSelected a span
{
  background-position: 100% 0;
}

.main-nav2 ul.AspNet-Menu li.AspNet-Menu-ChildSelected ul
{
    visibility: visible;
}

.main-nav2 ul.AspNet-Menu ul{
    width:500px;
}

.main-nav2 ul.AspNet-Menu ul li {
  font: 12px/20px Arial, sans-serif;
  padding: 0 5px 0 0; 
  display: inline;
}

.main-nav2 ul.AspNet-Menu ul li a {
  text-decoration: none;
  color: #1b8db3;
  padding: 0 0 0 12px;
  background-image:none;
}

.main-nav2 ul.AspNet-Menu ul li a:hover {
  text-decoration: underline;
}

HTML:

<div class="main-nav2" id="ctl00_MainMenu"> 
  <div class="AspNet-Menu-Horizontal"> 
      <ul class="AspNet-Menu"> 
        <li class="AspNet-Menu-Item"> 
          <a href="javascript:return false;#1"> 
            <span> A Menu Option</span></a> 
          <ul> 
            <li class="AspNet-Menu-Item"> 
              <a href="/CSSMenu/A1.aspx"> 
                A1 SubMenu Option</a> 
            </li> 
            <li class="AspNet-Menu-Item"> 
              <a href="/CSSMenu/A2.aspx"> 
                A2 SubMenu Option</a> 
            </li> 
          </ul> 
        </li> 
        <li class="AspNet-Menu-Item"> 
          <a href="javascript:return false;"> 
            <span> B Menu Option</span></a> 
          <ul> 
            <li class="AspNet-Menu-Item"> 
              <a href="/CSSMenu/B1.aspx"> 
                B1 SubMenu Option</a> 
            </li> 
            <li class="AspNet-Menu-Item"> 
              <a href="/CSSMenu/B2.aspx"> 
                B2 SubMenu Option</a> 
            </li> 
          </ul> 
        </li> 
        <li class=" AspNet-Menu-Selected"> 
          <a href="/CSSMenu/C.aspx"> 
            <span> C Menu Option</span></a> 
        </li> 
      </ul> 
  </div> 
</div> 

Many thanks in advance for any tips or help!

Terry

A: 

If what you want is that when the user clicks a child2 selection the response produces a page with child2 displayed, but child2 should disappear when the user hovers over parent1 or parent3, then you'll need to use JavaScript. The reason being that it's an event that affects more than one node in the DOM in different ways. CSS only affects 1+ nodes in the DOM in the same way, and usually only at page load. The exception are pseudo-classes like :hover which can affect display after page load.

If you need a CSS multi-menu solution, or just want to look at a good one that might help you find what your answer, check out this GRC CSS. I learned a lot from it, and hacked it into a solution I've used numerous times.

Chris
A: 

There is no pseudo class in css to trigger mouse out equivalent event. You have to use javascript to accomplish what you are trying to do. There are lot of menus/plugins available which does exactly what you are doing (What I mean by the statement is no need to reinvent the wheel).

Teja Kantamneni
+2  A: 

The simple solution is attempt to degrade as best as possible. In this case, I'd set a background color on the child menu and jack up z-index on hover only, so the bg will cover other child menus--[edit] they'll still be visible, but the text won't overlap. Then use javascript to make it as you really want.

The more complicated solution means you have to make all child menus take up identical space--one way is to use negative margin and then padding to cover up that space--and let whatever child menu that's displayed cover up the open one, again by greater z-index (applied to the parent on hover).

edit Another thing I use all the time to handle this kind of situation is to do something like the following

ul:hover ul { display:none; } //or in your case, set to invisible
ul li:hover ul { display:block; } //in your case, set to visible

This means the submenu will disappear when the UL is hovered over and, because the li:hover is lower in the cascade and more specific (I usually have to deal with lots of here-state class names--don't think you will), should allow for the submenu to reappear. It's not quite as fine-grained as you want, but nearly.

D_N
Options two and three here are what I would use, and they work great.
Eric Meyer
DN, those suggestions are getting me really close, big thanks!
tblank
A: 

I'm positive you won't be able accomplish this level of fine-grained control solely through CSS. You'll need to change states on your DOM elements with JS.

kRON