I have a standard drop-down menu that uses jQuery to hide the children li elements. However, upon loading the site, the child elements quickly appear and subsequently disappear (sort of like a quick flash). I don't think this is at all related to the flash-of-unstyled-content known issue.
The site is in Hebrew, but that shouldn't affect anything. The site is located here
If you'd like a sample HTML + CSS and the Javascript code, I would gladly post it here.
I was just wondering if anyone has encountered this issue before. I'm seeing it in Chrome, and I haven't really checked if it also happens in IE and Firefox.
Thanks!
EDIT: HTML/CSS/JS shown below:
HTML:
<ul class="menu">
<li>blah
<ul class="sub-menu">
<li>blah</li>
</ul>
</li>
</ul>
CSS:
/* NAVIGATION -- level 1 */
ul.menu { float: right; list-style-type: none; font-size: 15px; margin-top: 50px; }
ul.menu > li{ float: right; display: inline; position: relative; margin-left: 30px; }
ul.menu li > a { display: block; color: #5c5d5f; text-decoration: none; border-bottom: solid 1px #9b9a95; }
ul.menu li:hover > a, ul.menu li a:hover , ul.menu li.current_page_item > a { color: black; }
body.home .current_page_item > a { }
body.home .current_page_item > a:hover { }
/* NAVIGATION -- level 2 */
ul.menu li > div { display: none; width: 157px; height: 171px; margin-right: -10px; position: absolute; opacity:0; background: url(images/subNav_bg.png) no-repeat top right; }
ul.menu li > div span { height: 15px; background: transparent; display: block; } /* used to push down the menu */
JS:
// navigation menu //
// add hasSubMenu to each li that has one //
$('.menu > li').has('ul').addClass('hasSubMenu');
// wrap with <div> //
$('li.hasSubMenu > ul').wrap('<div />');
$('ul.menu li > div').css('display', 'none');
$('ul.menu li > div').prepend('<span></span>');
$('li.hasSubMenu > a').click(function () {
return false;
});
// add class to <div> for extendedBg //
$('li.extendedBg').find('div').addClass('subBg2');
$('li.hasSubMenu').hover(function () {
// hover on
$(this).addClass('hover').find('div').stop().fadeTo("medium", 1, /* when done fading */
function () {
$(this).find('div').css('display', 'block');
//$(this).find('ul').css('display','block');
}
);
}, function () {
// hover off
$(this).removeClass('hover').find('div').stop().fadeOut();
});
Set the dropdown menu as display: none in the page's CSS or directly in the element itself using style="display:none". This will hide it as the page loads.
I have the same issue :( except when i used the css to hide it on load, i now have the problem that it never displays! even when hovering over the parent...
Even before i posted my reply i thought id try one more thing
#navigation ul ul{
display:none;
}
instead of
#navigation ul ul li{
display:none;
}
and now it works perfectly
I recommend setting the style to display:none the the li elements in a style sheet, so that the browser knows to render them initially as not displayed. Then, when jQuery loads, the inline style that jQuery adds will override the display style.
ul li {
display:none;
}
Try:
.mobile-menu:not( .mm-menu ) {
display: none;
}
where '.mobile-menu' is whatever class or ID you have given to the containing element of your menu.
e.g
<div class="mobile-menu">
<ul>
<li>about</li>
<li>Food</li>
</ul>
</div>
Related
I have created a jfiddle for this problem at: JSFiddle showing menu problems
I am trying to create a cool menu using jquery and css3 mainly because of familiarity. I would be willing to switch to full CSS3, but I am less sure of how to do that. I have several problems that I cannot seem to fix. The code is as follows:
javascript:
(function ($) {
$.fn.hoverIntent = function (f, g) {
// default configuration options
var cfg = {
sensitivity: 7,
interval: 100,
timeout: 0
};
// override configuration options with user supplied object
cfg = $.extend(cfg, g ? {
over: f,
out: g
} : f);
// instantiate variables
// cX, cY = current X and Y position of mouse, updated by mousemove event
// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
var cX, cY, pX, pY;
// A private function for getting mouse position
var track = function (ev) {
cX = ev.pageX;
cY = ev.pageY;
};
// A private function for comparing current and previous mouse position
var compare = function (ev, ob) {
ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
// compare mouse positions to see if they've crossed the threshold
if ((Math.abs(pX - cX) + Math.abs(pY - cY)) < cfg.sensitivity) {
$(ob).unbind("mousemove", track);
// set hoverIntent state to true (so mouseOut can be called)
ob.hoverIntent_s = 1;
return cfg.over.apply(ob, [ev]);
} else {
// set previous coordinates for next time
pX = cX;
pY = cY;
// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
ob.hoverIntent_t = setTimeout(function () {
compare(ev, ob);
}, cfg.interval);
}
};
// A private function for delaying the mouseOut function
var delay = function (ev, ob) {
ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
ob.hoverIntent_s = 0;
return cfg.out.apply(ob, [ev]);
};
// A private function for handling mouse 'hovering'
var handleHover = function (e) {
// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
while (p && p != this) {
try {
p = p.parentNode;
} catch (e) {
p = this;
}
}
if (p == this) {
return false;
}
// copy objects to be passed into t (required for event object to be passed in IE)
var ev = jQuery.extend({}, e);
var ob = this;
// cancel hoverIntent timer if it exists
if (ob.hoverIntent_t) {
ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
}
// else e.type == "onmouseover"
if (e.type == "mouseover") {
// set "previous" X and Y position based on initial entry point
pX = ev.pageX;
pY = ev.pageY;
// update "current" X and Y position based on mousemove
$(ob).bind("mousemove", track);
// start polling interval (self-calling timeout) to compare mouse coordinates over time
if (ob.hoverIntent_s != 1) {
ob.hoverIntent_t = setTimeout(function () {
compare(ev, ob);
}, cfg.interval);
}
// else e.type == "onmouseout"
} else {
// unbind expensive mousemove event
$(ob).unbind("mousemove", track);
// if hoverIntent state is true, then call the mouseOut function after the specified delay
if (ob.hoverIntent_s == 1) {
ob.hoverIntent_t = setTimeout(function () {
delay(ev, ob);
}, cfg.timeout);
}
}
};
// bind the function to the two event listeners
return this.mouseover(handleHover).mouseout(handleHover);
};
})(jQuery);
$(function () {
var config = {
sensitivity: 3, // number = sensitivity threshold (must be 1 or higher)
interval: 200, // number = milliseconds for onMouseOver polling interval
over: doOpen, // function = onMouseOver callback (REQUIRED)
timeout: 200, // number = milliseconds delay before onMouseOut
out: doClose // function = onMouseOut callback (REQUIRED)
};
function doOpen() {
$(this).addClass("hover");
$('ul:first', this).css('visibility', 'visible');
}
function doClose() {
$(this).removeClass("hover");
$('ul:first', this).css('visibility', 'hidden');
}
$("ul.dropdown li").hoverIntent(config);
$("ul.dropdown li ul li:has(ul)").find("a:first").append(" » ");
$("ul.dropdown li ul li:has(ul)").find("span:first").append(" » ");
});
CSS3:
.main_nav {
background-color:#ffffff;
text-align:center;
float:left;
height:50px;
}
.main_nav ul{
list-style:outside none none !important;
text-align: center;
display: inline;
width: 80%;
}
/*
LEVEL ONE
*/
ul.dropdown { position: relative; white-space: nowrap;text-wrap: none;}
ul.dropdown li { font-weight: bold; float: left; background: #ffffff; color: #4b2c17; }
ul.dropdown a:hover { color: #ffffff; }
ul.dropdown a:active { color: #ffa500; }
ul.dropdown li a { display: block; padding: 4px 8px; border-right: 1px solid #333;
color: #222; }
ul.dropdown li:last-child a { border-right: none; } /* Doesn't work in IE */
ul.dropdown li.hover,
ul.dropdown li:hover { background: rgb(214, 210, 0); color: #ffffff; position: relative; }
ul.dropdown li.hover a { color: black; }
ul.dropdown li:hover h4 {background: #ffffff;color: #4b2c17;}
/*
LEVEL TWO
*/
ul.dropdown ul { visibility: hidden; position: absolute; top: 100%; left: 0; padding-left: 0px !important;}
ul.dropdown ul li { font-weight: normal; background: #ffffff; color: #4b2c17;
border-bottom: 1px solid #222; float: none; }
/* IE 6 & 7 Needs Inline Block */
ul.dropdown ul li a { border-right: none; width: 100%; display: inline-block; }
/*
LEVEL THREE
*/
ul.dropdown ul ul { left: 100%; top: 0; }
ul.dropdown li:hover > ul { visibility: visible; }
/*
LEVEL Four
*/
ul.dropdown ul ul ul { left: 100%; top: 0; }
ul.dropdown ul ul li:hover > ul { visibility: visible; }
and the HTML:
<div class="main_nav">
<ul class="dropdown">
<li>Home</li>
<li>User
<ul class="sub_menu">
<li class="subnavhead"><h3>New Users</h3></li>
<li>Add New User</li>
<li>Validate Users</li>
<li class="subnavhead"><h3>Current Users</h3></li>
<li>Edit User Information</li>
</ul>
</li>
<li class="topnav">Head 2
<ul class="sub_menu">
<li><a target="new" href="#">Subhead 1</a></li>
<li class="subnavhead"><h4><span>Section Group</span></h4>
<ul class="thirdnav">
<li>Subgroup head 1
<ul class="thirdnav">
<li>Subgroup item 1</li>
<li>Subgroup item 2</li>
</ul>
</li>
<li>Subgroup head 2
<ul class="thirdnav">
<li><span>Subgroup item head 1</span>
<ul class="thirdnav">
<li>third level 1</li>
<li>third level 2</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
These codes are supposed to generate a multi-level menu with the ability to track what is highlighted; however, there are several abberrant behaviors within this that I have been currently unable to fix.
The first is the width for the main navigation bar. I have been unable to get the menu to spread out to fill the menu bar even 80% regardless of the width parameter I have tried to define.
The second is the width of the LI on the drop-down menu components. As you can see I am able to prevent the line from wrapping, however as shown, the <li> does not stretch the width of the longest piece of text. Along with this, you see the highlight isn't consistent and I do not know why. I have tried multiple variations and no success.
The last problem is why that stupid >> is showing up on the last html link under sugroup head 2. The logic doesn't fit that, but it seems to show up.
Any help would be greatly appreciated!
Thanks!
Jon
If I understood correctly the issues I think I've resolved 2 and 3. About issue number 1 I simply don't understand what you mean... You want the whole menu to take up the whole page's width? If you could clarify it would be really helpful.
Anyway, for issue number 2 (again, if I understood it correctly) you can make the menu take up the width of the longest item by disabling the wrapping and setting the width to 100%:
ul.dropdown ul li {
font-weight: normal;
background: #ffffff;
color: #4b2c17;
border-bottom: 1px solid #222;
width: 100%;
white-space:nowrap;
}
For issue number 3, Prachit had it right. It's the :has jQuery selector combined with the .find that's giving you trouble, since the a tag for "third level 1" is the first descendent a tag of a li that matches your selector $("ul.dropdown li ul li:has(ul)").find(" a:first"). In this case you should be looking only for direct childs of the li that matches your selector, hence your line would turn into:
$("ul.dropdown li ul li:has(ul)").find("> a:first").append(" » ");
Anyway, I've updated your fiddle here: http://jsfiddle.net/tzn1x7uq/5/
Hope I could help.
The other answers appear to have the good solutions for issues 2 & 3. When using position:absolute the children's height and width do not adhere like they normally do. Using white-space: nowrap will correct that (although using width:100% won't make a difference).
This line:
$("ul.dropdown li ul li:has(ul)").find("> a:first").append(" » ");
Works fine, there's other ways to target this besides :has() but it works. You can correct the hover issue of "head 2" > "section group" by removing the background from the following rule:
ul.dropdown li:hover h4 {background: #ffffff;color: #4b2c17;}
Lastly is the issue of not being able to set the width. There's a few things that need to happen. For one be sure to set the width on the document:
html, body{
width: 100%;
}
Next you need to add the same to all parents (percentage width only works if the parent has a defined width as well). So start with .main_nav:
.main_nav {
width: 100%; //add
background-color:#ffffff;
text-align:center;
height:50px;
}
On of the biggest reasons you're having issues is because of .main_nav ul being set to display: inline. inline doesn't not respect it's children's width/height therefore calling width: 100% will have no effect on it. Change to inline-block or just block and now add your width:
.main_nav ul{
width: 100%; //add
list-style:outside none none !important;
text-align: center;
display: inline-block; //add
padding: 0; //clear the default padding set on ul elements
}
Next, Your list items are floating, you'll need to clear those. Typically overflow:hidden is a good approach for clearing floats but in this case you have subnavs that will "overflow" your content so you're better off using a clearfix:
.main_nav ul:after{
content: "";
display: block;
clear: both;
}
Now you can set the size on your li's:
ul.dropdown li { width:33%; font-weight: bold; float: left; background: #ffffff; color: #4b2c17; }
Since your styles are being inherited through shared targeting, you need to overwrite the previous width of 33% with width: 100% for your subnav lis:
ul.dropdown ul li { font-weight: normal; background: #ffffff; color: #4b2c17; border-bottom: 1px solid #222; float: none; width: 100%; //add }
Now your list will take the full width. You have other issues, for one, using visibility: hidden is not a great idea. While the element is "hidden" from sight, it still takes up room on the page (as you will see if you scroll right and there is a lot of excess space). There's also the fact that your "head 2" menu has so many subnavs and stretches so far to the right that it's not ideal to be tucked into the corner. You may want to revisit the way it displays. Perhaps have it just drop downwards instead of two the right. Also just a UI/UX tip, having so many levels of dropdowns is not well liked for a user. But that's going to be up to you. Structurally this could use a lot of work, you should take advantage of class names so you don't have children inheriting unwarranted styles but I hope this sets you on the right path:
FIDDLE
you can use it.
<style>
body {
padding: 20px 50px 150px;
font-size: 13px;
text-align: center;
/* background: #E3CAA1;*/
}
ul.dr_menu {
text-align: left;
display: inline;
margin: 0;
padding: 15px 4px 17px 0;
list-style: none;
/*-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.15);
-moz-box-shadow: 0 0 5px rgba(0, 0, 0, 0.15);
box-shadow: 0 0 5px rgba(0, 0, 0, 0.15);*/
}
ul.dr_menu li {
font: bold 12px/18px;
display: inline-block;
margin-right: -4px;
position: relative;
padding: 15px 20px;
/* background: #fff;*/
cursor: pointer;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-ms-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
}
ul.dr_menu li:hover {
background: #0b86c8;
color: #fff;
}
ul.dr_menu li ul {
padding: 0;
position: absolute;
top: 48px;
left: 0;
width: 150px;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
display: none;
opacity: 0;
visibility: hidden;
-webkit-transiton: opacity 0.2s;
-moz-transition: opacity 0.2s;
-ms-transition: opacity 0.2s;
-o-transition: opacity 0.2s;
-transition: opacity 0.2s;
}
ul.dr_menu li ul li {
background: #0b86c8;
display: block;
color: #fff;
text-shadow: 0 -1px 0 #000;
}
ul.dr_menu li ul li:hover { background: #666; }
ul.dr_menu li:hover ul {
display: block;
opacity: 1;
visibility: visible;
}
</style>
<body>
<ul class="dr_menu">
<li>
Add Management
<ul>
<li>My Add</li>
</ul>
</li>
<li>
API Management
<ul>
<li>Create API</li>
<li>Manage API</li>
<li>Test API</li>
<li>Document API</li>
</ul>
</li>
</ul>
</body>
The width of main navigation bar does not spread because .main_nav have float: left;, so if you added width to li in percentage it won't spread. You can add width to .main_nav and then to li in percentage, it will spread along the width of .main_nav.
Set width of li on drop-down to get desired width drop-down. Not sure what you mean about highlight inconsistent, if you mean about extra white-spaces, it is because heading tags h3 and h4 have some default padding and margin. Set margin and padding to 0 for h3 and h4.
The >> shows up because you have used has selector in $("ul.dropdown li ul li:has(ul)").find("a:first").append(" » ");. has matches if tag exists anywhere among its descendants, not just as a direct child.
is this what youre looking for? http://jsfiddle.net/tzn1x7uq/7/
1a. Main Menu is 100% width: width: 100%; /*ADDED LINE*/
1b. Menu links take up more space:
ul.dropdown li a {
display: block; padding: 4px 30px; border-right: 1px solid #333; color: #222;
} /*ADDED padding 30px*/
prevent line wrapping:
ul li {white-space: nowrap;} /*ADDED LINE*/
2b. weird highlighting stuff:
h3{ margin: 0px;}
also you have a <h4><span>text here</span></h4>, i changed it to <h3>Text here</h3>
random >> caused by »
/* COMMENTED OUT: GAVE YOU THE >> things
$("ul.dropdown li ul li:has(ul)").find("a:first").append(" » ");
$("ul.dropdown li ul li:has(ul)").find("span:first").append(" » ");
*/
hope this helps!
You can have the hover effects using CSS only buddy.
<div id="navigation">
<ul class="menu">
<li>Home</li>
<li>User
<ul class="sub-menu">
<li>
<h3>New Users</h3>
Add New User
</li>
<li>Validate Users</li>
<li>
<h3>Current Users</h3>
Edit User Information
</li>
</ul>
</li>
<li>User 2
<ul class="sub-menu">
<li>
<h3>New Users</h3>
Add New User
<ul class="sub-menu">
<li>
<h3>New Users 2</h3>
Add New User
<ul class="sub-menu">
<li>
<h3>New Users 3</h3>
Add New User
</li>
<li>Validate Users</li>
<li>
<h3>Current Users</h3>
Edit User Information
</li>
</ul>
</li>
<li>Validate Users</li>
<li>
<h3>Current Users</h3>
Edit User Information
</li>
</ul>
</li>
<li>Validate Users</li>
<li>
<h3>Current Users</h3>
Edit User Information
</li>
</ul>
</li>
<li>User 3
<ul class="sub-menu">
<li>
<h3>New Users</h3>
Add New User
</li>
<li>Validate Users</li>
<li>
<h3>Current Users</h3>
Edit User Information
</li>
</ul>
</li>
</ul>
For CSS
#navigation:before,
#navigation:after { clear: both; content: ' '; display: block; }
#navigation ul { padding: 0; }
#navigation li { float: left; list-style: none; position: relative; }
#navigation li a { display: block; padding: 5px 15px; text-decoration: none; white-space: nowrap; }
#navigation li a:hover { background-color: #222; color: #fff; }
#navigation li ul,
#navigation li:hover ul ul,
#navigation li li:hover ul ul { display: none; position: absolute; }
#navigation li:hover ul,
#navigation li li:hover ul,
#navigation li li li:hover ul { display: block; }
#navigation li li { float: none; }
#navigation ul ul ul { left: 100%; top: 0;}
h3 { margin: 0; }
js fiddle DEMO
On my page, I have a menu with currently six links. Two of them open a sub-menu (an ul-tag within the li-tag). Using jQuery, I'm trying to calculate the number of links (6) and then give each link a width of 1/6 of the page. Using this code, I can accomplish my goal, but only with normal links (with no submenu):
$( document ).ready(function()
{
// Gets the number of elements with class yourClass
var amount = $('.menulink').length;
alert(amount) //EDIT: This outputs "6"
// Calculates the width each element should get
var width = 100/amount;
width += "%";
// Set the width on each element
$( "nav ul li " ).css('width', width);
});
And my HTML looks like this:
<nav>
<ul>
<li class="menulink">Link1 (with submenu)
<ul>
<li>Submenuitem1</li>
<li>Submenuitem2</li>
<li>Submenuitem3</li>
<li>Submenuitem4</li>
</ul>
</li>
<li class="menulink">Link2</li>
<li class="menulink">Link3</li>
<li class="menulink">Link4</li>
<li class="menulink">Libk5</li>
<li class="menulink">Link6 (with submenu)
<ul>
<li>Submenuitem1</li>
<li>Submenuitem2</li>
<li>Submenuitem3</li>
</ul>
</li>
</ul>
</nav>
I am aware that this is not necessary and that I could just set the width to 16.7% with 6 menulinks, but I want to understand why my code doesn't work. Can anyone please explain why it doesn't?
EDIT: This is how my CSS looks:
body
{
padding: 0;
margin: 0;
overflow-y: scroll;
font-family: Arial, Helvetica, sans-serif;
font-size: 18px;
}
nav
{
background-color:#222;
}
nav ul
{
list-style-type: none;
padding: 0;
margin: 0;
position: relative;
}
nav ul li
{
display:inline-block;
}
nav ul li:hover
{
background-color: #333;
}
nav ul li a
{
color: #CCC;
display: block;
padding: 15px;
text-decoration:none;
}
nav ul li a:hover
{
color: #CCC;
text-decoration:none;
}
nav ul ul
{
display:none;
position:absolute;
background-color: #333;
border: 5px solid #222;
border-top: 0;
margin-left: -5px;
width: 300px;
}
nav ul ul li
{
display:block;
width: 300px;
}
According to what you've said in the comments, it's not applying the width to the items with sub-menus.
Try this:
$( document ).ready(function() {
// Gets the number of elements with class yourClass
var amount = $('.menulink').length;
// Calculates the width each element should get
var width = 100/amount;
width += "%";
// Set the width on each element
$("nav > ul > li").css('width', width);
});
I'm trying to use user Wind Shear's permanent hover solution on a group of thumbnails. However, I'd like the "permanent hover" state to only be applied to one thumbnail at a time. So if I hover off a thumbnail and onto the page the permanent hover stays applied to that thumbnail, but when I hover onto a different thumbnail it should take the permeant hover off the first thumbnail and apply it to the new one.
html:
<ul class="test">
<li id="onabout">
Alpha
<ul>
<li>Hiya! And it persists</li>
</ul>
</li>
</ul>
js:
$("#onabout").one("mouseover", function() {
$("#onabout ul").addClass('permahover');
});
css:
ul {
display: block;
width: 200px;
}
ul li {
display: block;
}
ul li a {
display: block;
border: 1px solid #000;
background: #fff;
}
ul li a {
display: block;
border: 1px solid #000;
background: #fff;
}
ul li ul {
display: none;
}
ul li ul.permahover {
display: block;
}
Here's the jsfiddle from Wind Shear's question: http://jsfiddle.net/jlratwil/w83BW/
The permanent hover function works great, but I can't figure out how to modify it to only apply to one thumbnail at a time. Thanks!
Use .on() instead of .one()
$("#onabout").on("mouseover", function() {
$("#onabout ul").removeClass('permahover');
$(this).find("ul").addClass('permahover');
});
Use .on instead of .one and remove the class then add it to the hovered element
$(".onabout").on("mouseover", function() {
$('.permahover').removeClass('permahover');
$(this).find("ul").addClass('permahover');
});
Demo
I am a student worker, I'm working off an idea, I have found an open source drop down menu that I would like to alter.
I would like to alter it so that instead of showing its children when it is hovered over, it shows them when clicked. Is this possible? Or does anyone know of a similar solution that is open source?
Here is the code:
Too many lines to post the HTML so here is the URL
http://notimefortime.com/index.txt
#menuh-container
{
position: absolute;
top: 1em;
left: 1em;
}
#menuh
{
font-size: 10px;
font-family: arial, helvetica, sans-serif;
width:100%;
float:left;
margin:2em;
margin-top: 1em;
}
#menuh a
{
text-align: center;
display:block;
border: 1px solid #0040FF;
white-space:nowrap;
margin:0;
padding: 0.3em;
}
#menuh a:link, #menuh a:visited, #menuh a:active
{
color: white;
background-color: #0040FF;
text-decoration:none;
}
#menuh a:hover
{
color: white;
background-color: #668CFF;
text-decoration:none;
}
#menuh a.top_parent, #menuh a.top_parent:hover /* attaches down-arrow to all top-parents */
{
background-image: url(navdown_white.gif);
background-position: right center;
background-repeat: no-repeat;
}
#menuh a.parent, #menuh a.parent:hover /* attaches side-arrow to all parents */
{
background-image: url(nav_white.gif);
background-position: right center;
background-repeat: no-repeat;
}
#menuh ul
{
list-style:none;
margin:0;
padding:0;
float:left;
width:20em;
}
#menuh li
{
position:relative;
min-height: 1px;
vertical-align: bottom;
}
#menuh ul ul
{
position:absolute;
z-index:500;
top:auto;
display:none;
padding: 1em;
margin:-1em 0 0 -1em;
}
#menuh ul ul ul
{
top:0;
left:100%;
}
div#menuh li:hover
{
cursor:pointer;
z-index:100;
}
div#menuh li:hover ul ul,
div#menuh li li:hover ul ul,
div#menuh li li li:hover ul ul,
div#menuh li li li li:hover ul ul
{
display:none;
}
div#menuh li:hover ul,
div#menuh li li:hover ul,
div#menuh li li li:hover ul,
div#menuh li li li li:hover ul
{
display:block;
}
No.
You're currently using the CSS :hover pseudo selector which displays the child when the parent is hovered over. There's a pseudo selector :active which is only triggered if you're holding down the mouse button on an element, but that's obviously not what you want.
For the menu to appear on click, you'll need JavaScript. However, in case a user is browsing with Javascript off, you'll want to revert to the CSS hover technique. So, start with some basic HTML/CSS, similar to what you have:
HTML:
<ul id="menu">
<li>
Some Link
<ul>
<li>A</li>
<li>B</li>
</ul>
</li>
<li>
Some Link 2
<ul>
<li>1</li>
<li>2</li>
</ul>
</li>
</ul>
CSS:
#menu li ul {
display:none;
}
#menu li:hover ul {
display:block;
}
Then, in JavaScript, override the hover event and keep the children hidden. Also, attach a click event and show the child on that:
Javascript:
window.onload = function() {
var menu = document.getElementById("menu"), //get the menu
i = 0;
//get the <li>s
var parents = menu.children;
for(i=0;i<parents.length;i++) {
//override the hover event
parents[i].onmouseover = function() {
//hide the first child (which, in this specific case,
//is the <ul> that we're looking for)
//if you want to hide more children, you could
//loop through and hide them all, etc.
this.children[0].style.display = "none";
};
//on click,
parents[i].onclick = function() {
//show the first child if it's hidden
//hide if it's visible
var c = this.children[0];
c.style.display = c.style.display === "none" ? "block" : "none";
};
}
};
You can see an example here: http://jsbin.com/ifuvuw/2/edit
Please note:
This does not handle the nested menus you have. It's a simple example. You can take the basic principle and apply it to your case. If you have any questions on how it works, please ask, but if you're having trouble applying it, consider asking a new question.
TL;DR: You can't do it with CSS, but you can with Javascript
Pros: please tweak my (probably crappy) JS and improve it
Noobs: please ask if you don't understand how it works
The best way to accomplish this would be to use JavaScript. I'd recommend using the jQuery framework, it makes it a lot easier. Here is a good starting point:
http://api.jquery.com/click/
I am very new to javascript and ajax/jquery and have been working on trying to get a script to open and close the drop menu on click rather that hover.
The menu in question is found on http://www.gamefriction.com/Coded/ and is the dark menu on the right side under the header. I would like it to open and close like the other menu that is further below it (it is light gray and is in the "Select Division" module).
The gray menu is part of a menu and the language menu is not.
I have a jquery import as well which can be found in the view source of the above link.
My Javascript Code:
<script type="text/javascript">
/* Language Selector */
$(function() {
$("#lang-selector li").hover(function() {
$('ul:first',this).css('display', 'block');
}, function() {
$('ul:first',this).css('display', 'none');
});
});
$(document).ready(function(){
/* Navigation */
$('.subnav-game').hide();
$('.subnav-game:eq(0)').show();
$('.preorder-type').hide();
$('.preorder-type:eq(3)').show();
});
</script>
My CSS:
#lang-selector
{
font-size: 11px;
height: 21px;
margin: 7px auto 17px auto;
width: 186px;
}
#lang-selector span
{
color: #999;
float: left;
margin: 4px 0 0 87px;
padding-right: 4px;
text-align: right;
}
#lang-selector ul
{
float: left;
list-style: none;
margin: 0;
padding: 0;
}
#lang-selector ul li a
{
padding: 3px 10px 1px 10px;
}
#lang-selector ul, #lang-selector a
{
width: 186px;
}
#lang-selector ul ul
{
display: none;
position: absolute;
}
#lang-selector ul ul li
{
border-top: 1px solid #666;
float: left;
position: relative;
}
#lang-selector a
{
background: url("http://www.gamefriction.com/Coded/images/language_bg.png") no-repeat;
color: #666;
display: block;
font-size: 10px;
height: 17px;
padding: 4px 10px 0 10px;
text-align: left;
text-decoration: none;
width: 166px;
}
#lang-selector ul ul li a
{
background: #333;
color: #999;
}
#lang-selector ul ul li a:hover
{
background: #c4262c;
color: #fff;
}
My HTML:
<div id="lang-selector">
<ul>
<li>
Choose a Language
<ul>
<li>English</li>
<li>Deutsch</li>
<li>Español</li>
<li>Français</li>
<li>Italiano</li>
</ul>
</li>
</ul>
</div>
Thanks!
$(function() {
$("#lang-selector li:first").click(function(){
$('ul:first',this).toggle();
})
});
Using toggle will require you to click to open then reclick to close
I would do something like this...
$(function() {
$("#lang-selector > li").click(function() {
$('ul:first',this).toggleClass('active');
});
});
And, then, in the CSS add this:
.active { display: block; }
<< EDIT: Removed "ul" from ".active" class for CSS rendering efficiency >>
Also make sure that the sub-nav <ul> has "display: none;" on it by default in your CSS.
This will make it so that clicking an <li> tag in #lang-selector, but not in any sub-nav <ul> tags will either open or close the sub-nav, depending on it's current state.
If you're worried about the accessibility of having "display: none" on the sub-nav by default, you can do something like this...
$(function() {
$("#lang-selector li ul").addClass("hidden");
$("#lang-selector li").click(function(e) {
e.preventDefault();
$('ul:first',$(this)).toggleClass('hidden active');
});
});
<< EDIT: Altered selectors to match example provided, turned "this" into jQuery object. >>
And then also add this to the CSS
.hidden { display: none; }
In this scenario, you have the <ul> showing by default, then when the document loads, jQuery adds the "hidden" class to all of them to hide them, then on the click of the <li> it will toggle the hidden and active classes, displaying them or hiding them.
You'll also need to remove your current "display: none" from your #lang-selector ul ul in CSS, otherwise it takes priority over the hidden / active classes.
search this $("#lang-selector li").hover and replace with
$("#lang-selector li").click
.hover, .click, .something, are all triggers, view this link:
Jquery Events
to learn more about events in Jquery!
Ps: sushil bharwani (vote it), is right, just change your .hover by the .click
if you need two functions for a click event, try .toggle
i'm using this:
$('.triggerlist').toggle(function(e) {
e.preventDefault();
$(this).find('ul').fadeIn();
},function() {
$(this).find('ul').fadeOut();
});
Which allows me to do more stuff on the 2 functions than just the .click with its 1 function.