I've a code snippet of a vertical fly-out-menu and would like to avoid the top gap of the sub-menus.
I made some progress with float, position and top but got lost in some dirty code.
That's the desired result:
What's a good/best/common practice to solve the problem? Thanks in advance!
/* Define the body style */
body {
font-family:Arial;
font-size:12px;
}
/* We remove the margin, padding, and list style of UL and LI components */
#menuwrapper ul, #menuwrapper ul li{
margin:0;
padding:0;
list-style:none;
}
/* We apply background color and border bottom white and width to 150px */
#menuwrapper ul li{
background-color:#7f95db;
border-bottom:solid 1px white;
width:150px;
cursor:pointer;
}
/* We apply the background hover color when user hover the mouse over of the li component */
#menuwrapper ul li:hover{
background-color:#6679e9;
position:relative;
}
/* We apply the link style */
#menuwrapper ul li a{
padding:5px 15px;
color:#ffffff;
display:inline-block;
text-decoration:none;
}
/**** SECOND LEVEL MENU ****/
/* We make the position to absolute for flyout menu and hidden the ul until the user hover the parent li item */
#menuwrapper ul li ul{
position:absolute;
display:none;
}
/* When user has hovered the li item, we show the ul list by applying display:block, note: 150px is the individual menu width. */
#menuwrapper ul li:hover ul{
left:150px;
top:0px;
display:block;
}
/* we apply different background color to 2nd level menu items*/
#menuwrapper ul li ul li{
background-color:#cae25a;
}
/* We change the background color for the level 2 submenu when hovering the menu */
#menuwrapper ul li:hover ul li:hover{
background-color:#b1b536;
}
/* We style the color of level 2 links */
#menuwrapper ul li ul li a{
color:#454444;
display:inline-block;
width:120px;
}
/**** THIRD LEVEL MENU ****/
/* We need to hide the 3rd menu, when hovering the first level menu */
#menuwrapper ul li:hover ul li ul{
position:absolute;
display:none;
}
/* We show the third level menu only when they hover the second level menu parent */
#menuwrapper ul li:hover ul li:hover ul{
display:block;
left:150px;
top:0;
}
/* We change the background color for the level 3 submenu*/
#menuwrapper ul li:hover ul li:hover ul li{
background:#86d3fa;
}
/* We change the background color for the level 3 submenu when hovering the menu */
#menuwrapper ul li:hover ul li:hover ul li:hover{
background:#358ebc;
}
/* We change the level 3 link color */
#menuwrapper ul li:hover ul li:hover ul li a{
color:#ffffff;
}
/* Clear float */
.clear{
clear:both;
}
<div id="menuwrapper">
<ul>
<li>Home</li>
<li>Products
<ul>
<li>Product 1
<ul>
<li>Sub Product 1</li>
<li>Sub Product 2</li>
<li>Sub Product 3</li>
</ul>
</li>
<li>Product 2</li>
<li>Product 3</li>
</ul>
</li>
<li>About Us
<ul>
<li>Faqs</li>
<li>Contact Us</li>
<li>Where are we?</li>
</ul>
</li>
<li>Help
</ul>
</div>
How does this look:
https://jsfiddle.net/tobyl/um02Loxc/1/
Relevant code:
#menuwrapper ul {
position: relative;
}
And:
/* We apply the background hover color when user hover the mouse over of the li component */
#menuwrapper ul li:hover{
background-color:#6679e9;
}
say body margin is 0
body{
margin:0;
}
Related
Ive got a 3 leve dropdown menu and the 3rd level sub-menu displays next to the 2nd level menu item like it should, except for a gap.
The 2nd level is set to a width of 100px so I've absolutely positioned the 3rd level to top:0, left:100px so it displays to the right of the 2nd level, but there's a gap. If I change left:100px to left:97px there is no gap. Why is this?
The HTML:
<nav>
<ul>
<li>Menu 1</li>
<li>Menu 2
<ul>
<li>Sub-Menu 1</li>
<li>Sub-Menu 2</li>
<li>Sub-Menu 3</li>
</ul>
</li>
<li>Menu 3</li>
<li>Menu 4
<ul>
<li>Sub-Menu 1</li>
<li>Sub-Menu 2</li>
<li>Sub-Menu 3
<ul>
<li>Sub-Menu 4</li>
<li>Sub-Menu 5</li>
<li>Sub-Menu 6</li>
</ul>
</li>
</ul>
</li>
<li>Menu 5</li>
</ul>
</nav>
The CSS:
/* Initialise for 3 tiers */
nav ul, ul li ul, ul li ul li ul {
margin:0;
padding:0;
}
nav ul li, ul li ul li, ul li ul li ul li {
list-style-type:none;
float:left;
}
/* Link Appearance for 3 tiers */
nav ul li a, ul li ul li a, ul li ul li ul li a {
text-decoration:none;
color:#fff;
background:#666;
padding:5px 10px;
float:left;
}
nav ul li a:hover, ul li ul li a:hover, ul li ul li ul li a:hover {
background:#C00;
}
/* 2nd Tier */
nav ul li {
position:relative;
}
nav ul li > ul {
display:none;
position:absolute;
top:30px;
left:0;
width:100px;
}
nav ul li:hover > ul{
display:block;
}
/* 3rd Tier */
nav ul li ul li {
position:relative;
}
nav ul li ul li:hover > ul {
display:block;
}
nav ul li ul li ul {
display:none;
position:absolute;
top:0;
left:100px;
}
JSFiddle
using percentage instead of pixel for this issue:
try left:100% and check result
nav ul li ul li ul {
display:none;
position:absolute;
top:0;
left:100%;
}
Fiddle
also you don't need to write ul li ul li ul li a or like so.simply you can write:
ul ul ul a{
your CSS code
}
The issue is the gap between the menus. They need to be adjacent or even overlap for this hover trick to work.
So instead of specifying
left: 100px;
do something like
left: 100%;
/* or even */
left: 99%;
This will cause the 3rd layer to be adjacent to the second layer menu, or even overlap the second slightly (for 99%), allowing you to move the mouse without any interruptions that close the menu. And you won't have to worry about the width of the menus either.
Updated fiddle: http://jsfiddle.net/tqEfW/5/
If you want to keep the gap for the look of it, you can give the 3rd layer ul a padding:
nav ul li ul li ul {
....
left: 100%;
padding-left: 4px;
}
Ad demonstrated here: http://jsfiddle.net/tqEfW/9/
That said, from a UX point of view, menus with 3 layers are very hard to use and should be avoided when possible.
If you create CSS selectors like ul.first-level > li or ul.second-level > li it will only select the li that are inmediately after the ul with class first-level (or with class second-level, respectively).
In this way, without interating a lot of ul li ul li ul that can be really hard to read you can control the appearance of any complex nested list.
Its looks like you know how to solve it but your question is why this is happening.
Now in your code you put the width 100px to ul. but the li didn't have nay width. now both width is not same thing. width in ul is the width of this list area. And width in li means width of each individual list item. In your case your
ul li a
{
padding: 5px 10px;
}
now the padding of a do not full the full area. and you put the background color at ul li a so the much area its covering(not sure 'cover' is the appropriate word to mention it) its showing dark in back and around 3px left so its showing white.
If you put
ul li a
{
padding: 5px 10.1px;
}
You will see the li have no gap[#123] between levels of menu.
Instead of setting the background to ul li a if you set it to ul you can see there is no gap[#123]
#123 The actual white area is not gap. The ul is 100px but text including the padding of 10px in left and right not filling the total 100px. Its filling only 97px so when you are putting the width as 97px its showing no white area. But when it is 100px this showing the background on 97px as black and the rest 3px white which looks like a gap.
I got a css menu with 3 levels. You can see my actual code right here http://jsfiddle.net/7rMgu/
As you can see, my secondary level don't keep the light blue background when navigating in the 3rd level. I've looked over the website for similar thread but I just found similar problems with only 2 levels. Also, can someone explain when I should use the '>' in css as I'm a bit confused.
CSS
html{height:100%;background-color:#0d497d;}
body{width:100%;height:100%;margin:0px;padding:0px;color:#575757;font:0.75em "Lucida Grande","Lucida Sans Unicode",Helvetica,Arial,Verdana,sans-serif;}
div.menuAdmin ul{margin:0;padding:0;float:right;height:100%;}
div.menuAdmin ul li{display:block;float:left;height:23px;margin-bottom:0;}
div.menuAdmin ul li a{color:#fff;padding:0.1em 0.3em 0.2em 0.3em;text-decoration:none;font-size:12px;display:block;margin:0.85em 0em 0em 0em;width:130px;background-color: #0d497d;border:1px solid #78B9EF;border-radius:5px;}
div.menuAdmin ul li:hover a{color:#000;border-radius:5px;background-color:#78B9EF;}
div.menuAdmin ul li ul{display:none;}
div.menuAdmin ul li:hover > ul {display:block;height:20px;width:139px;position:absolute;margin:0;}
div.menuAdmin ul li:hover > ul li a {line-height: 20px;color:#fff;text-decoration: none;margin: 0;padding-bottom: 0.1em;background-color: #0d497d;border:1px solid #78B9EF;border-radius:5px;}
div.menuAdmin ul li:hover > ul li a:hover {color:#000;text-decoration:none;text-shadow:none;background-color: #78B9EF;}
div.menuAdmin ul ul li:hover > ul {display:block;position:absolute;left:100%;top:0;width:139px;}
div.menuAdmin ul > ul > ul li:hover > a {color:#444;background-color:#78B9EF;}
HTML
<div class='menuAdmin'>
<ul>
<li>
<a href=''>A</a>
<ul>
<li>
<a href=''>1</a>
<ul>
<li>
<a href=''>A1</a>
</li>
<li>
<a href=''>A2</a>
</li>
<li>
<a href=''>A3</a>
</li>
<li>
<a href=''>A4</a>
</li>
</ul>
</li>
<li>
<a href=''>2</a>
</li>
<li>
<a href=''>3</a>
</li>
<li>
<a href=''>4</a>
</li>
</ul>
</li>
<li>
<a href=''>B</a>
</li>
<li>
<a href=''>C</a>
</li>
<li>
<a href=''>D</a>
</li>
</ul>
</div>
Thanks
To keep the :hover effect you need to make the change on hover the li element not just the a tag, so you have this:
div.menuAdmin ul li:hover > ul li a:hover
Must be:
div.menuAdmin ul li:hover > ul li:hover > a
With the hover on the li element keeps the effect since the ul wich is the submenu is part of the li.
Check the Demo http://jsfiddle.net/7rMgu/1/.
Now your second question when use this >; when you only want to affect the direct children, it let you avoid the same style on nested elements. An example with the same selector I have fix, if you remove the last > check what happen:
http://jsfiddle.net/7rMgu/3/
It changes all a inside the li even if are inside some nested elements.
Here is an updated fiddle:
http://jsfiddle.net/ryanwheale/7rMgu/2/
Essentially, you always want the :hover selector to be on the LI. You had it on the A.
Also, the > selector in CSS means "direct children"... best explained by example:
<div class="my-div">
<p>This should be blue</p>
<div>
<p>This should be green</p>
</div>
</div>
and this css:
.my-div p { color: green }
.my-div > p { color: blue }
You have a few redundant rules, I've tried to boil it down for you:
.menuAdmin ul{ /* all lists */
margin:0;
padding:0;
list-style: none;
}
.menuAdmin li { /* all list items */
margin:0;
padding:0;
}
.menuAdmin > ul { /* first level list*/
float: right;
}
.menuAdmin > ul > li { /* first level list items*/
float: left;
}
.menuAdmin ul ul { /* second and third level list */
position: absolute; /* remove from flow */
display: none; /* hide by default */
}
.menuAdmin ul ul ul { /* third level list */
top: 0;
left: 100%;
}
.menuAdmin li:hover > ul { /* first level list inside of a hovered item */
display: block;
}
.menuAdmin a { /* all links */
color:#fff;
padding:0.1em 0.3em 0.2em 0.3em;
text-decoration:none;
font-size:12px;
display:block;
width:130px;
background-color: #0d497d;
border:1px solid #78B9EF;
border-radius:5px;
}
.menuAdmin li:hover > a { /* links inside hovered list item */
color:#000;
background-color:#78B9EF;
}
As already answered, > means "child" (a.k.a. direct descendant)
See demo at http://jsfiddle.net/7rMgu/5/
I am working on a HTML/CSS drop down menu and now whenever I hover my mouse over the top of the menu not every entry is showing in the drop menu. The top one or two entries are always missing. Here is my HTML:
<!-- Navigation Bar -->
<ul id="navi">
<li>Engines
<ul>
<li>DiniJS</li>
<li>Foxen2D</li>
<li>Vivon3D</li>
</ul>
</li>
<li>Team
<ul>
<li>Rob Myers</li>
<li>Nate Mast</li>
</ul>
</li>
<li>Contact
<ul>
<li>Email</li>
<li>Twitter</li>
</ul>
</li>
</ul>
and here is the CSS:
#navi ul {
list-style:none;
margin:0px;
padding:0px;
}
#navi li {
float:left;
width:120px;
padding-top: 13px;
padding-bottom:8px;
background-color:black;
text-align:center;
font-family:"Courier New";
}
#navi li:hover {
background-color:#303030;
}
#navi li ul li {
float:none;
width:116px;
text-align:left;
padding-left:4px;
border-top:1px solid #303030;
display:none;
font-size:85%;
position:absolute;
z-index:2;
}
#navi li:hover ul li {
display:block;
}
#navi a {
text-decoration:none;
color:red;
}
I am open to any Javascript or JQuery suggestions if that is a better way to go about fixing this. Thank you.
Your problem is that all of the submenu items are stacking one on top of another. Simply moving position: absolute; from the #navi li ul li block to a new #navi li ul block should fix this.
When using nested list items. use class names to target. for your menu use class="sub"
for submenu (ul) and set display none and absolute for the sub ul and not for the li.
I created a dropdown menu through CSS but weirdly all the dropdown menus are aligned to left. I am hoping that all the dropdowns would appear and drop under their parent menu.
The HTML is as follows:-
<div id="menu">
<ul>
<li ng-class="{selected: $index==currPage}" ng-repeat="page in data.pages" class="ng-scope selected">
Introduction
<ul>
<!-- ngRepeat: smenu in data.subMenu[$index].list --><li ng-class="{$index==currMenu}" ng-repeat="smenu in data.subMenu[$index].list" class="ng-scope">
Profile
</li><li ng-class="{$index==currMenu}" ng-repeat="smenu in data.subMenu[$index].list" class="ng-scope">
Background
</li><li ng-class="{$index==currMenu}" ng-repeat="smenu in data.subMenu[$index].list" class="ng-scope">
What is KAM
</li>
</ul>
</li>
...
</div>
Following is the CSS:-
#menu {
/*border-bottom:4px seagreen solid;*/
background-color: #2d394d;
list-style:none;
}
#menu ul {
list-style: none;
}
#menu ul li {
display: inline-block;
float: none;
/*width: 20%;*/
}
#menu ul li a{
font-size: 10pt;
padding:12px 24px 12px 24px;
/*border-right:1px white solid;*/
display:block;
text-decoration: none;
text-align: center;
color:#fff;
text-transform: uppercase;
}
#menu ul li a:hover{
}
#menu ul li.selected a {
background-color: #1b86c2;
color:#fff;
}
/* DropDown Menus */
#menu ul ul{
background:#fff; /* Adding a background makes the dropdown work properly in IE7+. Make this as close to your page's background as possible (i.e. white page == white background). */
background:rgba(255,255,255,0); /* But! Let's make the background fully transparent where we can, we don't actually want to see it if we can help it... */
list-style:none;
position:absolute;
left:-9999px; /* Hide off-screen when not needed (this is more accessible than display:none;) */
}
#menu ul li ul li{
padding-top:1px; /* Introducing a padding between the li and the a give the illusion spaced items */
float:none;
display: block;
}
#nav ul ul a{
white-space:nowrap; /* Stop text wrapping and creating multi-line dropdown items */
}
#menu li:hover ul{ /* Display the dropdown on hover */
left:0; /* Bring back on-screen when needed */
}
#menu li:hover a{ /* These create persistent hover states, meaning the top-most link stays 'hovered' even when your cursor has moved down the list. */
background:#1b86c2;
text-decoration:underline;
}
#menu li:hover ul a{ /* The persistent hover state does however create a global style for links even before they're hovered. Here we undo these effects. */
text-decoration:none;
}
#menu li:hover ul li a:hover{ /* Here we define the most explicit hover states--what happens when you hover each individual link. */
background:#333;
}
You can see the Image showing it here (where the picture shows the drop down for "Cases", it should be under the Cases, but it is shifted to left. "Introduction" sub-menu also shows at the same place):-
It is because of left:0 positioning and parent li's position as being static by default. Yo can fix it by marking it relative so that child ul's left:0 will be relative to the parent li.
#menu ul li {
display: inline-block;
float: none;
/*width: 20%;*/
position:relative; /*Add this*/
}
#menu li:hover ul{ /* Display the dropdown on hover */
/* Bring back on-screen when needed */
left:0;
padding:0; /*Add this if you are not using any reset*/
}
Fiddle
try adding #menu ul li {position: relative;}
Correction:
After looking closer my last answer wasn't quite right. This might not be the best way to fix it. But its a way (or gets it in the ball park anyways).
In your CSS do the following:
#menu {
/*border-bottom:4px seagreen solid;*/
background-color: #2d394d;
height:40px;
list-style:none;
}
#menu ul li ul{
position:relative;
}
Here is a demo:
http://jsfiddle.net/2mtt8/1/
It looks like each of your drop-downs is position absolutely at 0px:
left:0; /* Bring back on-screen when needed */
I suggest positioning each relatively to its parent.
You might consider using display:none to hide drop-downs, rather than positioning them off-screen.
I'm getting some ugly behavior from a menu that contains nested lists.
The parent menu has some broad categories. When the user hovers over one of these list items, a child menu appears below. This is fine.
However, the child items can also have sub menus (I'll refer to these as grandchildren). These also appear on hover, but the entire child menu disappears when the user no longer hovers on the grandchild.
This is best explained with a FIDDLE
Hovering on Parent displays the 3 children. This is good.
Hovering on Child 1 displays the grandchildren. This is also
good.
But now trying to click Child 2 or Child 3 once the grandchildren under child 1 are expanded becomes clumsy. This is
very bad.
How can a decent hover effect be achieved here without this goofy behavior? (A CSS solution would be preferable.)
HTML
<div id="centeredmenu">
<ul>
<li>
<p><span>Parent</span></p>
<ul>
<li>
Child 1
<ul>
<li>grandchild 1</li>
<li>grandchild 2</li>
<li>grandchild 3</li>
</ul>
</li>
<li>Child 2</li>
<li>Child 3</li>
</ul>
</li>
</ul>
CSS
#centeredmenu ul {
clear:left;
float:left;
list-style:none;
margin:0;
padding:0;
position:relative;
left:50%;
text-align:center;
}
#centeredmenu ul li {
display:block;
float:left;
list-style:none;
margin:0;
padding:0;
position:relative;
right:50%;
}
#centeredmenu ul li a {
display:block;
margin:0 0 0 0px;
padding:3px 10px;
background: rgb(240,240,240);
color:#333333;
text-decoration:none;
line-height:2.3em;
border-top: 4px solid transparent;
border-right: 1px solid transparent;
border-bottom: 3px solid transparent;
border-left: 1px solid #848484;
}
/*hides the sub menu*/
#centeredmenu ul li ul li{
display: none;
}
/*displays sub menu on hover*/
#centeredmenu ul li:hover ul li {
display: block;
clear: both;
margin-left: 15px;
}
/*hides sub-sub menu*/
#centeredmenu ul li ul li ul{
display: none;
}
/*displays sub-sub menu on hover*/
#centeredmenu ul li ul li:hover ul {
display: block;
clear: both;
margin-left: 15px;
}
The markup structure of nested lists looks fine.
Using absolute positions on the nested ULs and the z-index tweaks you mentioned should do it.
This CSS only demo looks relevant:
http://line25.com/wp-content/uploads/2012/css-menu/demo/index.html
The problem is that when you mouse out of child1 onto child2, child1 collapses and moves child2 out from under the mouse cursor. You need to absolutely position the grandchildren so they aren't contained within the children.