Question

I have a horizontal hover dropdown menu working almost flawlessly. The goal is if I hover over a Link, I will see a row of Sub Links. Each row has X amount of Child Links that should display down one column. However, currently the Child Links display across in a row not down the column under their Sub Link.

HTML:

<div class="menu">
    <ul>
<li><a href='#'>Link 1</a>
    <ul>
    <li><a href='#'>Sub Link 1</a></li>
        <ul>
        <li><a href='#'>Sub Child Link 1</a></li>
        <li><a href='#'>Sub Child Link 2</a></li>
        <li><a href='#'>Sub Child Link 3</a></li>
        </ul>
    <li><a href='#'>Sub Link 2</a></li>
    </ul>
</li>
<li><a href='#'>Link 2</a>
    <ul>
    <li><a href='#'>Sub Link 1</a></li>
    <li><a href='#'>Sub Link 2</a></li>
    <li><a href='#'>Sub Link 3</a></li>
    <li><a href='#'>Sub Link 4</a></li>
    </ul>
</li>
<li><a href='#'>Link 3</a>
    <ul>
    <li><a href='#'>Sub Link 1</a></li>
    <li><a href='#'>Sub Link 2</a></li>
    <li><a href='#'>Sub Link 3</a></li>
    <li><a href='#'>Sub Link 4</a></li>
    </ul>
</li>
</ul>

CSS:

.menu{
    border:none;
    border:0px;
    margin:0px;
    padding:0px;
    border-bottom: 1px solid #ccc;
}
.menu ul{
    background:#fff;
    height:35px;
    list-style:none;
    margin:0;
    padding:0;
}
.menu li{
    float:left;
    padding:0px;
}
.menu li a{
    background:#fff;
    color:#000;
    display:block;
    line-height:35px;
    margin:0px;
    padding:0px 25px;
    text-align:center;
    text-decoration:none;
    text-transform: uppercase;
}

.menu li a:hover {
        border-bottom: 1px solid #ff0000;
}

.menu li a:hover, .menu ul li:hover a{
    background: #fff;
    text-decoration:none;
}
.menu li ul{
    background:#fff;
    display:none;
    height:auto;
    padding:0px;
    margin:0px;
    border:0px;
    position:absolute;
    width:400px;
    z-index:200;
}
.menu li:hover ul{
    display:block;
}
.menu li li {
    background: #fff;
    display:block;
    float:left;
    margin:0px;
    padding:10px;
    width:100px;
}
.menu li:hover li a{
    background:none;
}
.menu li ul a{
    display:block;
    height:30px;
    font-size:12px;
    font-style:normal;
    color: #999;
    margin:0px;
    padding:0px 10px 0px 15px;
    text-align:left;
    text-transform: uppercase;
}
.menu li ul a:hover, .menu li ul li:hover a{
    background:#fff;
    border:0px;
    text-decoration:none;
}
.menu p{
    clear:left;
}
Était-ce utile?

La solution

Okay, so the answer to your question comes in a few parts. All of it is available in this fiddle. Here goes.

The Markup

First, it's easier to deal with things if a sub-menu is nested in it's link's parent li. Also (side note) if your css fails for whatever reason, this will preserve the parent-child relationships. The new basic structure looks like this:

<div class="menu">
    <ul>
        <li>
            <a href='#'>Link</a>
            <ul>
                <li>
                    <a href='#'>Child</a>
                    <ul>
                        <li><a href='#'>Grandchild</a></li>
                    </ul>
                </li>
            </ul>
        <li>
    </ul>
</div>

The Styles

In the fiddle, I have the styles separated into a couple parts, and I'll go over each.

The Reset

This is pretty straight forward. It just resets everything. It's not relevant to the solution, though, really, so I've left it out of the answer. It's in the fiddle if you need it.

The Flavor

In the fiddle, the flavor is just my own personal taste. It's mostly colors, but there is one important bit. We apply the padding to the a elements. This'll help things line up properly and will also provide as a side-effect a nice big clickable area.

.menu a {
    display: block;
    padding: 10px; /* padding on the a */
    color: #000;
}

The Positioning

This is the real core of the answer. What we're doing is what you've already done, except we're un-setting the float on the third-level li. The short answer is just that line, honestly.

.menu li {
    position: relative;
    float: left;
}
.menu li ul { position: absolute; width: 400px; }
.menu li li ul { width: 120px; }
.menu li li li { float: none; } /* this lets columns happen again */

The Hover

To accomplish the hiding in a simpler way, we'll employ the use of the child selector (>). If you've never used it, Chris Coyier explains it very well, but basically it only gets immediate children. That way we can say any ul nested directly under an li should be displayed only if that li is being hovered. We do so like this:

.menu li > ul { display: none; }
.menu li:hover > ul { display: block; }

Edit: The MDN also has a great entry on the child selector. Check it out here.


The Demo

Again, the whole thing is demonstrated in a fiddle at http://jsfiddle.net/4tPcL/. Hope this helps!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top