Centering a dropline in a dropline menu

I am trying to make a PURE CSS drop-line menu. By now I have droplines pretty much down, so I am hoping to add a new twist. I am trying to center the dropline to it’s parent ( not the menu, itself mind you).

I attempted to achieve this by wrapping the sub menu in a div which has a width of 1px; and it’s absolutely positioned to 50% of the container ( which is the parent LI).
Everything would work fine if I could only move the submenu UL leftwards by half its width. this is easy if I wanted to give it an absolute width… ( i did this in the example by using IDs).

My question is could this be done without knowing the width of the submenus?

CSS
.top_menu { padding: 0; background: gray; width:960px; margin:0 auto ; border-bottom: 1.5em solid black}
.top_menu:after{content:“”; display: block; clear: both;}
.top_menu ul { list-style: none inside; margin: 0; padding: 0;float:right; position: relative }/float hack for collapsing menu in IE/
.top_menu li { margin: 0; float: left; padding: .5em; position: relative;}
.top_menu li div { padding-top: 0; position: absolute; width:1px; left:50%; top: 100%; display:none ; text-align: center; background: orange} /submain/
.top_menu li:hover div { display: block}
.top_menu a{text-decoration: none}
.top_menu ul li:hover{background: pink}
.top_menu .submain{background: yellow; font-size: 70%; float: left}
#rs .submain{ float:left ; margin-left:-4.75em}
#prt .submain{ width:17em; margin-left:-8.5em}

MARKUP
<div class=“top_menu”>
<ul>
<li><a href=“#”>item</a></li>
<li><a href=“#”>item</a>
<div id=“prt”>
<ul class=“submain”>
<li><a href=“#”>submenu</a></li>
<li><a href=“#”>stuff</a></li>
<li><a href=“#”>sub</a></li>
<li><a href=“#”>menu</a></li>
<li><a href=“#”>items</a></li>
</ul>
</div>
</li>
<li><a href=“#”>item</a>
<div id=“rs”>
<ul class=“submain”>
<li><a href=“#”>sub</a></li>
<li><a href=“#”>menu</a></li>
<li><a href=“#”>items</a></li>
</ul>
</div>
</li>
<li><a href=“#”>item</a></li>
<li><a href=“#”>item</a></li>
<li><a href=“#”>item</a></li>
</ul>
</div>

Hi, unless you know the dropdowns width horizontallly centering a widthless element (absolute) is impossible.
So to answer you question, no you can’t center it without knowing hte width :). You can center floats without the width, but not absolute elements (unless you just guess with a certain left (or left margin) value :))

I was afraid of that.
I was just trying to see i could find a way around manually calculating widths.

When you mentioned floats, i asumed you mean floating the container div instead of making AP?
I tried floating the .submain ul and then applying a margin… but it didnt work :frowning:
of course if I floated the div that contained the ul it would not work as a drop down…

Unfortunately CSS can’t do this, javascript can though, on hover of the <li> set left:50%; and then figure out the parents width, and divide that in half and just make that a negative number and it will center nicely :).

My floats comment wasn’t meant to be a suggestion :slight_smile:

Hi,

I’m not sure if you are talking about a vertical drop down or whether you wanted a horizontal drop down.

For a (widthless) vertical drop down you can center it quite easily like this.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
.top_menu {
    padding: 0;
    background: gray;
    width:960px;
    margin:0 auto;
    border-bottom: 1.5em solid black
}
.top_menu:after {
    content:"";
    display: block;
    clear: both;
}
.top_menu ul {
    list-style: none inside;
    margin: 0;
    padding: 0;
    float:right;
    position: relative
}/*float hack for collapsing menu in IE*/
.top_menu li {
    margin: 0;
    float: left;
    padding: .5em;
    position: relative;
}
.top_menu li div {
    padding-top: 0;
    position: absolute;
    left:50%;
    top: 100%;
    display:none;
    text-align: center;
    /*background: orange*/
} /*submain*/
.top_menu li:hover div {
    display: block
}
.top_menu a {
    text-decoration: none
}
.top_menu ul li:hover {
    background: pink
}
.top_menu .submain {
    background: yellow;
    font-size: 70%;
    float: left
}
/*#rs .submain {
    float:left;
    margin-left:-4.75em
}
#prt .submain {
    width:17em;
    margin-left:-8.5em
}*/
.top_menu li div ul{position:relative;left:-50%;}
.top_menu li div ul li{white-space:nowrap;display:block;float:none}
</style>
</head>
<body>
<div class="top_menu">
    <ul>
        <li><a href="#">item</a></li>
        <li><a href="#">item</a>
            <div id="prt">
                <ul class="submain">
                    <li><a href="#">submenu item that is longer</a></li>
                    <li><a href="#">stuff</a></li>
                    <li><a href="#">sub</a></li>
                    <li><a href="#">menu</a></li>
                    <li><a href="#">items</a></li>
                </ul>
            </div>
        </li>
        <li><a href="#">item</a>
            <div id="rs">
                <ul class="submain">
                    <li><a href="#">sub</a></li>
                    <li><a href="#">menu</a></li>
                    <li><a href="#">items</a></li>
                </ul>
            </div>
        </li>
        <li><a href="#">item</a></li>
        <li><a href="#">item</a></li>
        <li><a href="#">item</a></li>
    </ul>
</div
>
</body>
</html>


I’m not sure if that’s what you wanted though :slight_smile:

Hi Paul,
I think the OP was wanting a horizontal dropdown, from the looks of it the bottom black border on the .top_menu is for the sub ul to reside in.

With just two little tweaks (and one hack) to your code it should give the desired results. :slight_smile:

.top_menu li div ul{position:relative;left:-50%;[COLOR=Blue]white-space:nowrap[/COLOR]}
.top_menu li div ul li{[COLOR=Blue]display:inline-block;[/COLOR]float:none;}
[COLOR=Blue]*+html[/COLOR] .top_menu li div ul li{[COLOR=Blue]display:inline;[/COLOR]}/*IE7 inline-block trigger*/
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
.top_menu {
    padding: 0;
    background: gray;
    width:960px;
    margin:0 auto;
    border-bottom: 1.5em solid black
}
.top_menu:after {
    content:"";
    display: block;
    clear: both;
}
.top_menu ul {
    list-style: none inside;
    margin: 0;
    padding: 0;
    float:right;
    position: relative
}/*float hack for collapsing menu in IE*/
.top_menu li {
    margin: 0;
    float: left;
    padding: .5em;
    position: relative;
}
.top_menu li div {
    padding-top: 0;
    position: absolute;
    left:50%;
    top: 100%;
    display:none;
    text-align: center;
    /*background: orange*/
} /*submain*/
.top_menu li:hover div {
    display:block
}
.top_menu a {
    text-decoration: none
}
.top_menu ul li:hover {
    background: pink
}
.top_menu .submain {
    background: yellow;
    font-size: 70%;
    float: left
}
/*#rs .submain {
    float:left;
    margin-left:-4.75em
}
#prt .submain {
    width:17em;
    margin-left:-8.5em
}*/
.top_menu li div ul{position:relative;left:-50%;white-space:nowrap}
.top_menu li div ul li{display:inline-block;float:none;}
*+html .top_menu li div ul li{display:inline;}/*IE7 inline-block trigger*/
</style>
</head>
<body>
<div class="top_menu">
    <ul>
        <li><a href="#">item</a></li>
        <li><a href="#">item</a>
            <div id="prt">
                <ul class="submain">
                    <li><a href="#">submenu item that is longer</a></li>
                    <li><a href="#">stuff</a></li>
                    <li><a href="#">sub</a></li>
                    <li><a href="#">menu</a></li>
                    <li><a href="#">items</a></li>
                </ul>
            </div>
        </li>
        <li><a href="#">item</a>
            <div id="rs">
                <ul class="submain">
                    <li><a href="#">sub</a></li>
                    <li><a href="#">menu</a></li>
                    <li><a href="#">items</a></li>
                </ul>
            </div>
        </li>
        <li><a href="#">item</a></li>
        <li><a href="#">item</a></li>
        <li><a href="#">item</a></li>
    </ul>
</div
>
</body>
</html>

One more to add in there Ray :slight_smile:


* html .top_menu li div ul li{display:inline;}/*IE6 inline-block trigger*/

Yeah, I was aware of IE6.
I did not bother with it since there is no script in place for li:hover yet :slight_smile:

I’ll get together an IE6/7. I’m also changing it from display:none/block to a huge left margin/0 margin. It’s a better way (you know that Ray but the OP doesn’t)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript">
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>
<style type="text/css">
.top_menu {
    padding: 0;
    background: gray;
    width:960px;
    margin:0 auto;
    border-bottom: 1.5em solid black
}
.top_menu:after {
    content:"";
    display: block;
    clear: both;
}
.top_menu ul {
    list-style: none inside;
    margin: 0;
    padding: 0;
    float:right;
    position: relative
}/*float hack for collapsing menu in IE*/
.top_menu li {
    margin: 0;
    float: left;
    padding: .5em;
    position: relative;
}
.top_menu li div {
    padding-top: 0;
    position: absolute;
    left:50&#37;;
    top: 100%;
    margin-left:-999em;
    text-align: center;
    /*background: orange*/
} /*submain*/
.top_menu li:hover div, .top_menu ul li.sfhover div{
    margin-left:0
}
.top_menu a {
    text-decoration: none
}
.top_menu ul li:hover, .top_menu ul li.sfhover {
    background: pink
}
.top_menu .submain {
    background: yellow;
    font-size: 70%;
    float: left
}
/*#rs .submain {
    float:left;
    margin-left:-4.75em
}
#prt .submain {
    width:17em;
    margin-left:-8.5em
}*/
.top_menu li div ul{position:relative;left:-50%;white-space:nowrap}
.top_menu li div ul li{display:inline-block;float:none;}

*+html .top_menu li div ul li{display:inline;}/*IE7 inline-block trigger*/
* html .top_menu li div ul li{display:inline;}/*IE6 inline-block trigger*/
</style>
</head>
<body>
<div class="top_menu">
    <ul id="nav">
        <li><a href="#">item</a></li>
        <li><a href="#">item</a>
            <div id="prt">
                <ul class="submain">
                    <li><a href="#">submenu item that is longer</a></li>
                    <li><a href="#">stuff</a></li>
                    <li><a href="#">sub</a></li>
                    <li><a href="#">menu</a></li>
                    <li><a href="#">items</a></li>
                </ul>
            </div>
        </li>
        <li><a href="#">item</a>
            <div id="rs">
                <ul class="submain">
                    <li><a href="#">sub</a></li>
                    <li><a href="#">menu</a></li>
                    <li><a href="#">items</a></li>
                </ul>
            </div>
        </li>
        <li><a href="#">item</a></li>
        <li><a href="#">item</a></li>
        <li><a href="#">item</a></li>
    </ul>
</div
>
</body>
</html>

That’s an IE6/7 version above.

Here is just an IE7 version if you aren’t supporting IE7 (Ray gave one but the one I’m using uses a better hide/show technique

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
.top_menu {
    padding: 0;
    background: gray;
    width:960px;
    margin:0 auto;
    border-bottom: 1.5em solid black
}
.top_menu:after {
    content:"";
    display: block;
    clear: both;
}
.top_menu ul {
    list-style: none inside;
    margin: 0;
    padding: 0;
    float:right;
    position: relative
}/*float hack for collapsing menu in IE*/
.top_menu li {
    margin: 0;
    float: left;
    padding: .5em;
    position: relative;
}
.top_menu li div {
    padding-top: 0;
    position: absolute;
    left:50%;
    top: 100%;
    margin-left:-999em;
    text-align: center;
    /*background: orange*/
} /*submain*/
.top_menu li:hover div{
    margin-left:0
}
.top_menu a {
    text-decoration: none
}
.top_menu ul li:hover{
    background: pink
}
.top_menu .submain {
    background: yellow;
    font-size: 70%;
    float: left
}
/*#rs .submain {
    float:left;
    margin-left:-4.75em
}
#prt .submain {
    width:17em;
    margin-left:-8.5em
}*/
.top_menu li div ul{position:relative;left:-50%;white-space:nowrap}
.top_menu li div ul li{display:inline-block;float:none;}

*+html .top_menu li div ul li{display:inline;}/*IE7 inline-block trigger*/
</style>
</head>
<body>
<div class="top_menu">
    <ul id="nav">
        <li><a href="#">item</a></li>
        <li><a href="#">item</a>
            <div id="prt">
                <ul class="submain">
                    <li><a href="#">submenu item that is longer</a></li>
                    <li><a href="#">stuff</a></li>
                    <li><a href="#">sub</a></li>
                    <li><a href="#">menu</a></li>
                    <li><a href="#">items</a></li>
                </ul>
            </div>
        </li>
        <li><a href="#">item</a>
            <div id="rs">
                <ul class="submain">
                    <li><a href="#">sub</a></li>
                    <li><a href="#">menu</a></li>
                    <li><a href="#">items</a></li>
                </ul>
            </div>
        </li>
        <li><a href="#">item</a></li>
        <li><a href="#">item</a></li>
        <li><a href="#">item</a></li>
    </ul>
</div
>
</body>
</html>

WOW… thanks guys

this one may take me a bit to reverse engineer… but a lot to learn here

It didnt let me edit my last post :/.

Anyhow, it seems to be that the key to this was “whitespace:no-wrap”, I really would not have thought of that. Thanks again.

One question for Ray, I noticed you used “*+html” to hack for IE7 , is the ajacent selector (“+”)the way to make the Holly hack work in IE7? That would be very handy to know !

The holly hack is targeting IE6 via the star html hack and then doing height:1%;

But yes that code targets IE7 only…IE6 doesn’t even understand + :slight_smile:

well the reason that that was confusing to me was that i thought the “*” in IE is actually a parent of the HTML object and not an adjacent element…

I also thought that IE 7 did away with that element all together… so in a sense there was no “Holly hack” for IE7, but BETTER YET… IE& and later happily ignored all Holly hacks …

IE(less than 8) thinks that the HTML element has a parent, one thinks adjacent (IE7) and one thinks a father (parent)

That’s as good as I got. Who knows what IE is thinking. That’s the best judgement anyone can make really (what I just said)

Hi,

When MS brought IE7 out they said the fixed the * html bug. What they meant was they fixed it so that * html didn’t work by simply hard coding a fix. They didn’t fix the fact that IE7 still thought html had a parent and so by adding the adjacent selector into the mix (or the general sibling combinator ~) you can target IE7 only.

Note that you mustn’t use comma separated rules when using the *+html hack or they won’t be recognised.

You don’t need to use the “holly hack” in IE7 anyway because there is a much easier haslayout trigger for IE7 that is safe in all browsers. You just have to add min-height:0 and it doesn’t need to be hidden from anyone.

While I like *+html, the first IE7 hack I saw was something with :first-child.

:first-child+html{/ rules */}
That one? It doesn’t work in quirks mode though, if I remember :slight_smile: