Reputation: 3
I'm trying to add a second level to a dropdown menu using CSS. Its an immutable requirement that when hovering over the trigger text that the menu complex displays, and the first level (Options >>>, menu X) looks fine, but no matter what I do, I can't prevent the options level (option X, etc), from displaying at the top level. I need these options to display to the side on hover over Options >>>. I haven't included the second level CSS code cause not one of all the things I've tried have come close to working, so I'm not sure what to even include.
<!DOCTYPE html>
<html lang="en">
<head>
<style type="text/css">
.menu {
width: 150px;
position: relative;
}
.menu * {
display:block;
padding:0; margin:0;
}
.menu ul {
display:none;
}
.menu:hover ul {
display:block;
position:absolute;
width:100%;
top:100%;
border:solid 1px black;
background: white;
}
.menu li a {
font-size: 14px;
font-family: arial, sans-serif;
font-weight: bold;
padding:15px 0px 15px 15px;
color: white;
background-color: black;
text-decoration: none;
}
.menu a:hover {
background-color: white;
color: black;
}
</style>
</head>
<body>
<div class='menu'>
<span class='triggerclass' style='width:150px'>Trigger</span>
<ul>
<li><a href="#">Home</a></li>
<li><a href='#'>Options >>></a>
<ul>
<li><a href="#">Option 1</a></li>
<li><a href="#">Option 2</a></li>
<li><a href="#">Option 3</a></li>
</ul>
</li>
<li><a href="#">Menu 1</a></li>
<li><a href="#">Menu 2</a></li>
<li><a href="#">Menu 3</a></li>
<li><a href="#">Menu 4</a></li>
</ul>
</div>
</body>
</html>
Upvotes: 0
Views: 2507
Reputation: 21725
I believe what you are looking for is a flyout menu. There are plenty of tutorials on the web to do this with just CSS.
Here's the CSS I added to your code in the jsFiddle I linked to in the comment below your question.
CSS
.menu li {
position: relative;
}
.menu:hover li:hover ul {
display: block;
position: absolute;
left: 150px;
top: 0;
}
The reason the code you posted doesn't work is for a few key reasons and those are what make a CSS flyout menu work.
First, the li
containing a submenu should have position: relative
set as that submenu will use position: absolute
. This allows you to position the submenu based on the li
's position in the document when you use absolute positioning.
Once this is done, position the submenu based on the parent li
. Using top: 0; left: 0;
for the submenu would place it's upper left hand corner under that of the upper left hand corner of the parent li
. While this aligns the top of the submenu with the top of the parent li
it hides the submen. To fix this you move the submenu left the width of the parent li
, left: 150px
.
Second, you need to display the submenu when an li
containing a menu is hovered with li:hover ul
.
That's about it.
This can be a little confusing if you are not used to using the CSS position property.
Hope this helps!
**EDIT**
OP asked how to contain the submenu display to only a single submenu so that a submenu(s) of a submenu (and so on) are not displayed. Simple, use the Child Selector.
CSS
.menu:hover li:hover > ul
See the updated jsFiddle.
Upvotes: 1
Reputation: 3034
Seeing your code or knowing what exactly isn't working would be very helpful.
Forewarning: this code looks pretty complex and there are some moving parts, but once you have it in place, adding new menus, submenus and "super" submenus is a snap - all you have to do is add an unordered list and assign the appropriate classes. Really easy. The complex part is the jQuery rememebring which supersubmenu is currently showing and to manage what happens when people move their mouse all over the place.
That said, try this idea: Display the first list element in each menu "section", and set all others, underneath it, to display:none. Give them specific classes, and set hover of top element to display other list elements. If you need a "third" layer, create a SEPARATE list that is completely hidden. Add a SEPARATE class to the "submenu" item that will trigger the display of the third layer, then add an event handler for the second layer's hover that will display the third. Difficult to explain, but here's an example:
HTML:
<div style="display:table-cell; margin:auto; border:none;" runat="server" id="divMenu">
<ul class="MainMenu">
<li class="MainMenu NoSuperSub">ES</li>
<li class="MainMenu SubMenu Link NoSuperSub" data-url="WebPage.aspx" style="display:none;">Go To A Page</li>
<li class="MainMenu SubMenu SubWithSub" data-menu="AnotherMenu" style="display:none;">Open Another Menu</li>
</ul>
</div>
<ul class="MainMenu SuperSubMenu" id="AnotherMenu" style="display:none; margin:auto; border:none;">
<li class="MainMenu SubMenu Link SuperSubMenu" data-url="WebPage.aspx" style="display:none;">Another WebPage</li>
</ul>
Javascript:
//Global Variables
var SuperSubMenuName;
var CurrentMenu;
var TopPosition;
var LeftPosition;
var ViewingSuperSubMenu = false;
var SetTimeOutFunction;
//Event Handlers
$("li.MainMenu").mouseover(function (e) {
$(this).css("display", "inline-block");
$(this).siblings().css("display", "inline-block");
});
$("ul.MainMenu").mouseout(function (e) {
$(this).children("li").each(function () {
if ($(this).prop("class").toString().indexOf("SubMenu") >= 0)
$(this).css("display", "none");
});
});
$(".Link").click(function (e) {
$("#PostBackURL").val($(this).data("url"));
$("#PostBackValue").val("MenuSelection");
$("#aspnetForm").submit();
});
$("li.SubWithSub").mouseover(function (e) {
HideSuperSubMenu();
CurrentMenu = $(this).parent("ul").parent("div");
position = getPosition(this);
TopPosition = position.y - 108 ;
LeftPosition = position.x + 117;
SuperSubMenuName = "#" + $(this).data("menu");
ShowSuperSubMenu();
ViewingSuperSubMenu = false;
clearTimeout(SetTimeOutFunction);
SetTimeOutFunction = setTimeout(HideSuperSubMenuIfNotViewing, 1000);
});
$("ul.SuperSubMenu").mouseover(function (e) {
CurrentMenu.children("ul").children("li").each(function () {
$(this).css("display", "inline-block");
});
ViewingSuperSubMenu = true;
});
$("ul.SuperSubMenu").mouseout(function (e) {
CurrentMenu.children("ul").children("li").each(function () {
if ($(this).prop("class").toString().indexOf("SubMenu") >= 0)
$(this).css("display", "none");
});
ViewingSuperSubMenu = false;
});
$("li.NoSuperSub").mouseover(function (e) {
HideSuperSubMenu();
});
//Functions
function ShowSuperSubMenu(){
$(SuperSubMenuName).css({top: TopPosition, left: LeftPosition, position: "absolute"});
$(SuperSubMenuName).css("display", "table-cell");
$(SuperSubMenuName).children("li").each(function () {
$(this).css("display", "inline-block");
});
}
function HideSuperSubMenu() {
$(SuperSubMenuName).css("display", "none");
$(SuperSubMenuName).children("li").each(function () {
$(this).css("display", "none");
});
}
function HideSuperSubMenuIfNotViewing() {
if (ViewingSuperSubMenu == false)
HideSuperSubMenu();
}
function getPosition(element) {
var xPosition = 0;
var yPosition = 0;
while (element) {
xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
element = element.offsetParent;
}
return { x: xPosition, y: yPosition };
}
Upvotes: 0