Centered List Navbar with dropdowns

Hello Gang, I am trying to put together a centered navbar like this but with drop downs. CSS is definitely not my expertise so I am hoping someone can give me a hand. I have posted the code I have pieced together below, it is close but not quite there yet. The top level displays as it should but the sublevel spans 100% width which I do not want. Also, due to the fact that the sublevel is identified using the ID and not a class, I am limited to only one drop down. Any help would be greatly appreciated.

HTML:

<div id="navcontainer">
<ul id="navlist">
<li id="active"><a href="#" id="current">Item one</a></li>

<li><a href="#">Item two</a>
<ul id="subnavlist">
<li id="subactive"><a href="#" id="subcurrent">Subitem one</a></li>
<li><a href="#">Subitem two</a></li>
<li><a href="#">Subitem three</a></li>
<li><a href="#">Subitem four</a></li>
</ul>
</li>
<li><a href="#">Item three</a></li>
<li><a href="#">Item four</a></li>
<li><a href="#">Item five</a></li>
</ul>
</div>

CSS:

<style type="text/css">
#navcontainer ul
{
text-align: center;
padding-bottom: 5px;
padding-top: 5px;
padding-left: 0;
margin-top: 0;
/* cancels gap caused by top padding in Opera 7.54 */
margin-left: 0;
background-color: #036;
color: white;
width: 100%;
font-family: Arial,Helvetica,sans-serif;
line-height: 18px;
/* fixes Firefox 0.9.3 */
}

#navcontainer ul li
{
display: inline;
padding-left: 0;
padding-right: 0;
padding-bottom: 5px;
/* matches link padding except for left and right */
padding-top: 5px;
}

#navcontainer ul li a
{
padding-left: 10px;
padding-right: 10px;
padding-bottom: 5px;
padding-top: 5px;
color: white;
text-decoration: none;
border-right: 1px solid #fff;
}

#navcontainer ul li a:hover
{
background-color: #369;
color: white;
}

ul#subnavlist { display: none; }
ul#subnavlist li { float: none; }

ul#subnavlist li a
{
padding: 0px;
margin: 0px;
}

ul#navlist li:hover ul#subnavlist
{
display: block;
position: absolute;
font-size: 8pt;
padding-top: 5px;
}

ul#navlist li:hover ul#subnavlist li a
{
display: block;
width: 10em;
border: none;
padding: 2px;
}


#navcontainer #active { border-left: 1px solid #fff; }

</style>

Hi,
Your code has other problems besides the ones you mentioned.
You have your parent list items set as display:inline; and then you have nested the block level sub ul within the inline element. That is invalid code, you can’t nest block elements inside inline elemnts.

On a side note, the display:none; on the ul is a bad method for hiding the sub ul from an accessibility standpoint. You can’t tab through all the menu items when it is done that way.

You need to use a standard “Suckerfish Dropdown” and hide the sub ul with a large negative margin. To center the widthless parent list items and legally nest the sub ul you can use inline-block as shown in this example below.

Centered inline-block list with suckerfish dropdown

That method is not supported by FF2 though and I have explained it in the demo.

Another way is to use centered widthless floats but you will need overflow:hidden; on the main wrapping div to hide the relative positioning.

Centered and Widthless Floats with Dropdown

View the page source of that example or read this article for a detailed explanation on centered widthless floats.
http://www.pmob.co.uk/pob/centred-float.htm

Hope that helps :slight_smile:

What the OP has done is actually perfectly valid - they’ve nested a (DTD-specified) block-level element in another (DTD-specified) block-level element (although the latter element has since become inline-level due to a CSS declaration). We need to make a distinction here, between an element’s format as defined in the Doctype Declaration, and [URL=“http://www.w3.org/TR/CSS21/visuren.html#display-prop”]element formats that can be defined in CSS.

The expected behavior of a block-level element inside an inline-level element can be derived from the CSS21 Anonymous Block Box specification:

When an inline box contains a block box, the inline box (and its inline ancestors within the same line box) are broken around the block. The line boxes before the break and after the break are enclosed in anonymous boxes, and the block box becomes a sibling of those anonymous boxes. When such an inline box is affected by relative positioning, the relative positioning also affects the block box.

[Example]

Hi james,
Yes you are correct and I did forget about the doctype defining the element format vs. css definition. I’ll admit that I tend to forget about that doctype formatting a lot of the time. :slight_smile:

Now I’m going to take you back to another thread where you agreed that it is discouraged to nest blocks within inline elements. Even though it may be valid with the doctype formatting it can cause problems.

Many thanks for the responses didn’t mean to start a quarrel… :slight_smile:

Rayzur, if I had found the links that you posted, I probably would not have had to create this thread. I have made a couple of tweaks to this and it is working great! I tried this [URL=“http://www.css-lab.com/demos/navbar/cntr-float-drpdwn.html”]one first but for some reason the dropdown was offset to the right by 25px or so? For future reference, any idea what would have caused that? Thanks for your help!

James, that thread that I just linked to led me to create this thread below which was an extension of that original thread.

IE8 Hover Confusion with nested ul in list item

It was in that thread that we found the new IE8 whitespace bug.

Simply correcting someones statement, doesn’t constitute a quarrel.

In fact, I was about to add to my reply, but you beat me to it.

Yes, although it is valid and it’s behavior can be derived from the specification, nesting a block element inside an inline should be strongly discouraged.

It was incorrect of me to state in this quote that the aforementioned behavior wasn’t defined in the specification, since we’ve gathered it is. I fear I may also be wrong in attributing IE8’s behavior (from the post in which this quote is from) to the nesting of a block in an inline, although I’ll need to re-read the original post to determine this.

my whitespace is showing up in FF 3.5.7 and IE8, see attached?

Hi, you did not start any quarrel :slight_smile:
James was correct in his statement and I admitted my oversight. I just wanted to remind him of problems we have already been through. :wink:

As far as your dropdown being offset by 25px we would need to see your code. Obviously you altered something because my link does not show the problem.

EDIT:
If your not using the centered float method then let’s not be concerned about that 25px offset right now.

my whitespace is showing up in FF 3.5.7 and IE8, see attached?
Please post your code.

I showed how to kill the whitespace in my live demo.

#nav li {
    height:24px;/*optional*/
    display: -moz-inline-box;/* for FF2 (inline-box must be used for shrink wrapping)*/
    display:inline-block;/* for modern browsers */
    [B]margin:0 -2px;/*kill whitespace without altering html*/[/B]
    position:relative; 
    color:#FFF;
}

I had already fixed the IE8 bug also as shown here.

                    <li><a href="#">Contact Us</a></li>   
                </ul>    
            [B][COLOR=Black]</li
       [/COLOR][/B][COLOR=DarkGreen][B][COLOR=Black] ></ul>[/COLOR][/B]<!--kill IE8 whitespace bug on last-child--> [/COLOR]   
    </div><!-- end nav -->

Here is the code that produces the whitespace:

CSS:

<style type="text/css">
/*==== Begin Navbar Styles ====*/

#navwrap { /* this is for continuing the main ul BG color on each side */
background:#8293C3;
font-size:.850em;/*base font-size for all menu sizing with ems*/
height:1.75em;
border-top:1px solid #000;
border-bottom:1px solid #000;
}
#floater { /* this allows the widthless floats to center up */
float:left;
position:relative;
left:50%;
}
#nav {
position:relative;
left:-50%; /* this allows the widthless floats to center up */
list-style:none;
margin:0; /* reset the default left margin in IE */
padding:0; /* reset the default left padding in good browsers */
}
#nav li {
position:relative; /* establish stacking context for the AP'd dropdown sublist */
float:left;
padding:0;
font-weight:bold;
background:#8293C3;
}
#nav li a {
float:left;
padding:0 1.5em; /* text padding for left and right only */
line-height:1.75em; /* center the text vertically */
text-decoration:none;
color:#000;
}

#nav li:hover, /* all links on hover */
#nav li.sfhover{ /* IE6 script hover */
color:#FFF;
background:#333;
}
#nav li:hover a, 
#nav li.sfhover a {color:#FFF}

#nav li:hover li a, 
#nav li.sfhover li a {color:#000}

#nav li li:hover a, 
#nav li li.sfhover a {color:#00FFFF} /*sublist with differnt color on hover (cyan)*/

/* ----- Drop Down Styles ----- */

#nav ul {
position:absolute; /* position the sublist to nearest positioned ancestor, the (#nav li) in this case*/
width:10em;
margin-left:-999em;/* hide the sublist */
left:0; /* IE6&7 need this to position the sublist correctly on hover*/
top:1.75em;
list-style:none;
background: #FFF url(fake-image.jpg);/* IE needs some sort of BG on the nested ul */
border:1px solid #000;
}
#nav li li{
float: none;/*reset the float from #nav li*/
display: block;
border:none;
}
#nav li li a{
float: none;/*reset the float from #nav li*/
display: block;
line-height:1.2; /*reset from #nav li a */
padding:.375em .5em;
}
#nav li:hover ul,
#nav li.sfhover ul{ /* IE6 hover faked by the class sfhover */
margin-left: 0; /* show the sublist */
visibility:visible;/* makes IE7 think something changes on hover, fixes IE sticking dropdown */
}
</style>

HTML:

<div id="navwrap">
<div id="floater">
<ul id="nav">
<li><a href="#">Home</a></li>
<li><a href="#">Articles &raquo;</a>

<ul>
<li><a href="#">Link One</a></li>
<li><a href="#">Link Two</a></li>
<li><a href="#">Link Three Long Text String</a></li>
<li><a href="#">Link Four</a></li>
</ul>
</li>

<li><a href="#">News</a></li>
<li><a href="#">Gallery &raquo;</a>
<ul>
<li><a href="#">Link One</a></li>
<li><a href="#">Link Two</a></li>
<li><a href="#">Link Three</a></li>

<li><a href="#">Link Four</a></li>
</ul>
</li>
<li><a href="#">Contact Us</a></li>
<li><a href="#">About</a></li>
</ul>
</div><!-- end floater -->

</div><!-- end navwrap -->

Hi,
So you are using the centered float nav.
That is not whitespace, that is left padding on the sub ul. :slight_smile:

That happened because you removed the universal reset from my example.

* {margin:0;padding:0;}

To fix it without the reset you will need to set padding:0; on the sub ul.

[B]#nav ul[/B] {
position:absolute; /* position the sublist to nearest positioned ancestor, the (#nav li) in this case*/
width:10em;
margin-left:-999em;/* hide the sublist */
[B]padding:0;[/B]
left:0; /* IE6&7 need this to position the sublist correctly on hover*/
top:1.75em;
list-style:none;
background: #FFF url(fake-image.jpg);/* IE needs some sort of BG on the nested ul */
border:1px solid #000;
}

I put the “sfhover” script back in there for IE6 also. You had removed it, it needs to stay there for IE6.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Centered float dropdown</title>

<style type="text/css">
/* {margin:0;padding:0;}*/
#navwrap { /* this is for continuing the main ul BG color on each side */
background:#8293C3;
font-size:.850em;/*base font-size for all menu sizing with ems*/
height:1.75em;
border-top:1px solid #000;
border-bottom:1px solid #000;
}
#floater { /* this allows the widthless floats to center up */
float:left;
position:relative;
left:50%;
}
#nav {
position:relative;
left:-50%; /* this allows the widthless floats to center up */
list-style:none;
margin:0; /* reset the default left margin in IE */
padding:0; /* reset the default left padding in good browsers */
}
#nav li {
position:relative; /* establish stacking context for the AP'd dropdown sublist */
float:left;
padding:0;
font-weight:bold;
background:#8293C3;
}
#nav li a {
float:left;
padding:0 1.5em; /* text padding for left and right only */
line-height:1.75em; /* center the text vertically */
text-decoration:none;
color:#000;
}

#nav li:hover, /* all links on hover */
#nav li.sfhover{ /* IE6 script hover */
color:#FFF;
background:#333;
}
#nav li:hover a, 
#nav li.sfhover a {color:#FFF}

#nav li:hover li a, 
#nav li.sfhover li a {color:#000}

#nav li li:hover a, 
#nav li li.sfhover a {color:#00FFFF} /*sublist with differnt color on hover (cyan)*/

/* ----- Drop Down Styles ----- */

#nav ul {
position:absolute; /* position the sublist to nearest positioned ancestor, the (#nav li) in this case*/
width:10em;
margin-left:-999em;/* hide the sublist */
padding:0;
left:0; /* IE6&7 need this to position the sublist correctly on hover*/
top:1.75em;
list-style:none;
background: #FFF url(fake-image.jpg);/* IE needs some sort of BG on the nested ul */
border:1px solid #000;
}
#nav li li{
float: none;/*reset the float from #nav li*/
display: block;
border:none;
}
#nav li li a{
float: none;/*reset the float from #nav li*/
display: block;
line-height:1.2; /*reset from #nav li a */
padding:.375em .5em;
}
#nav li:hover ul,
#nav li.sfhover ul{ /* IE6 hover faked by the class sfhover */
margin-left: 0; /* show the sublist */
visibility:visible;/* makes IE7 think something changes on hover, fixes IE sticking dropdown */
}
</style>

<!--[if IE 6]>
<script type="text/javascript">// the Suckerfish script inserts class=sfhover on all li inside id=nav on mouseover
sfHover = function() {
    var sfEls = document.getElementById("nav").getElementsByTagName("LI");
    for (var i=0; i<sfEls.length; i++) {
        sfEls[i].onmouseover=function() {
            this.className+=" sfhover";
        }
        sfEls[i].onmouseout=function() {
            this.className=this.className.replace(new RegExp(" sfhover\\\\b"), "");
        }
    }
}
if (window.attachEvent) window.attachEvent("onload", sfHover);
</script>
<![endif]-->

</head>
<body>

<div id="navwrap">
<div id="floater">
<ul id="nav">
<li><a href="#">Home</a></li>
<li><a href="#">Articles &raquo;</a>

<ul>
<li><a href="#">Link One</a></li>
<li><a href="#">Link Two</a></li>
<li><a href="#">Link Three Long Text String</a></li>
<li><a href="#">Link Four</a></li>
</ul>
</li>

<li><a href="#">News</a></li>
<li><a href="#">Gallery &raquo;</a>
<ul>
<li><a href="#">Link One</a></li>
<li><a href="#">Link Two</a></li>
<li><a href="#">Link Three</a></li>

<li><a href="#">Link Four</a></li>
</ul>
</li>
<li><a href="#">Contact Us</a></li>
<li><a href="#">About</a></li>
</ul>
</div><!-- end floater -->

</div><!-- end navwrap -->

</body>
</html>

yes, that was it. sorry I am quite a newb when it comes to CSS… :slight_smile:
I would prefer to use this method since you stated the other is not supported by FF2.
Thanks again for all your help and it looks like I found a very informative site

Ok then, you need to be aware of an overflow problem that the relative positioning causes.

You must set overflow:hidden; on the main wrapping div to prevent a horizontal scrollbar when the viewport width is reduced or the list items extend to far to the right.

[B]#wrapper[/B] {
    width:900px;
    margin:30px auto;
   [B] overflow:hidden; /*important for centered widthless floats*/[/B]
    [B]min-height:300px;/*must be taller than dropdown*/[/B]
    background:#EEF;
    border:1px solid #000;
    border-top:0;
}

I had made note of that in my example and everyone always forgets to put it in there. Then they come back confused about why they are getting a horizontal scrollbar.

Work from this code here and you will not have that problem, but now you can’t have anything hanging out of the wrapper (such as pop up tooltips) because it will be hidden.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Centered float dropdown</title>

<style type="text/css">
/* {margin:0;padding:0;}*/
#wrapper {
    width:900px;
    margin:30px auto;
    overflow:hidden; /*important for centered widthless floats*/
    min-height:300px;/*must be taller than dropdown*/
    background:#EEF;
    border:1px solid #000;
    border-top:0;
}

#navwrap { /* this is for continuing the main ul BG color on each side */
    background:#8293C3;
    font-size:.850em;/*base font-size for all menu sizing with ems*/
    height:1.75em;
    border-top:1px solid #000;
    border-bottom:1px solid #000;
}
#floater { /* this allows the widthless floats to center up */
    float:left;
    position:relative;
    left:50&#37;;
}
#nav {
    position:relative;
    left:-50%; /* this allows the widthless floats to center up */
    list-style:none;
    margin:0; /* reset the default left margin in IE */
    padding:0; /* reset the default left padding in good browsers */
}
#nav li {
    position:relative; /* establish stacking context for the AP'd dropdown sublist */
    float:left;
    padding:0;
    font-weight:bold;
    background:#8293C3;
}
#nav li a {
    float:left;
    padding:0 1.5em; /* text padding for left and right only */
    line-height:1.75em; /* center the text vertically */
    text-decoration:none;
    color:#000;
}

#nav li:hover, /* all links on hover */
#nav li.sfhover{ /* IE6 script hover */
    color:#FFF;
    background:#333;
}
#nav li:hover a, 
#nav li.sfhover a {color:#FFF}

#nav li:hover li a, 
#nav li.sfhover li a {color:#000}

#nav li li:hover a, 
#nav li li.sfhover a {color:#00FFFF} /*sublist with differnt color on hover (cyan)*/

/* ----- Drop Down Styles ----- */

#nav ul {
    position:absolute; /* position the sublist to nearest positioned ancestor, the (#nav li) in this case*/
    width:10em;
    margin-left:-999em;/* hide the sublist */
    padding:0;
    left:0; /* IE6&7 need this to position the sublist correctly on hover*/
    top:1.75em;
    list-style:none;
    background: #FFF url(fake-image.jpg);/* IE needs some sort of BG on the nested ul */
    border:1px solid #000;
}
#nav li li{
    float: none;/*reset the float from #nav li*/
    display: block;
    border:none;
}
#nav li li a{
    float: none;/*reset the float from #nav li*/
    display: block;
    line-height:1.2; /*reset from #nav li a */
    padding:.375em .5em;
}
#nav li:hover ul,
#nav li.sfhover ul{ /* IE6 hover faked by the class sfhover */
    margin-left: 0; /* show the sublist */
    visibility:visible;/* makes IE7 think something changes on hover, fixes IE sticking dropdown */
}
</style>

<!--[if IE 6]>
<script type="text/javascript">// the Suckerfish script inserts class=sfhover on all li inside id=nav on mouseover
sfHover = function() {
    var sfEls = document.getElementById("nav").getElementsByTagName("LI");
    for (var i=0; i<sfEls.length; i++) {
        sfEls[i].onmouseover=function() {
            this.className+=" sfhover";
        }
        sfEls[i].onmouseout=function() {
            this.className=this.className.replace(new RegExp(" sfhover\\\\b"), "");
        }
    }
}
if (window.attachEvent) window.attachEvent("onload", sfHover);
</script>
<![endif]-->

</head>
<body>
<div id="wrapper">
    <div id="navwrap">
        <div id="floater">
            <ul id="nav">
                <li><a href="#">Home</a></li>
                <li><a href="#">Articles &raquo;</a>
                    <ul>
                    <li><a href="#">Link One</a></li>
                    <li><a href="#">Link Two</a></li>
                    <li><a href="#">Link Three Long Text String</a></li>
                    <li><a href="#">Link Four</a></li>
                    </ul>
                </li>
                <li><a href="#">News</a></li>
                <li><a href="#">Gallery &raquo;</a>
                    <ul>
                    <li><a href="#">Link One</a></li>
                    <li><a href="#">Link Two</a></li>
                    <li><a href="#">Link Three</a></li>
                    <li><a href="#">Link Four</a></li>
                    </ul>
                </li>
                <li><a href="#">Contact Us</a></li>
                <li><a href="#">About</a></li>
            </ul>
        </div><!-- end floater -->   
    </div><!-- end navwrap -->
</div><!-- end wrapper -->
</body>
</html>