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}
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
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 :).
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.
.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>
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%;
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>
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 !
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 …
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.