I have been trying to fix this problem for a while. Basically I am creating a drop down menu that has divs that contain the ul's so that I can have a box with a fixed width which will allow me to have images within the box.
An example of this would be BestBuy.com's navigation menu. I really like the design, but I'm having a difficult time replicating it.
My CSS works without trouble ONLY when the li's are not links. Example: It works when it is <li>Link</li> and not <li>Link</li>.
Of course inside that <li> is another list.
Anyway, I decided to use JQuery to fix the issue and I am about halfway there.
Here is my JQuery:
$(document).ready(function () {
$(".navbar ul li").hover(function() {
$(".navlink > div:first").addClass("active");
}, function() {
$(".navlink > div:first").removeClass("active");
});
$(".secondarylink").hover(function() {
$(".secondarylink > div").addClass("active");
}, function() {
$(".secondarylink > div").removeClass("active");
});
});
Here is my markup:
<div class="navbar">
<ul>
<li class="navlink"> Products
<div class="secondlevel">
<ul>
<li class="secondarylink">Testing 1
<div class="thirdlevel two-columns">
<div class="column">
<ul>
<li>Testing 1 </li>
<li>Testing 2 </li>
<li>Testing 3 </li>
<li>Testing 4 </li>
</ul>
</div>
<div class="column">
<ul>
<li>Testing 1 </li>
<li>Testing 2 </li>
<li>Testing 3 </li>
<li>Testing 4 </li>
</ul>
</div>
</div>
</li>
<li class="secondarylink">Testing 2
<div class="thirdlevel">
<ul>
<li>Testing 1</li>
<li>Testing 2</li>
<li>Testing 3</li>
<li>Testing 4</li>
</ul>
</div>
</li>
<li>Testing 3</li>
<li>Testing 4</li>
</ul>
</div>
</li>
<li class="navlink">Test Link</li>
</ul>
</div>
And my styling:
body {
font-family:sans-serif;
background: #eee;
}
.navlink {
display:block;
}
.navbar {
background:lightblue;
width: 100%;
padding:0;
}
.navbar ul {
list-style:none;
padding:0;
margin:0;
}
.navbar ul>li {
display:inline-block;
}
.navbar ul li ul>li {
display:block;
}
.secondlevel {
position:absolute;
width:350px;
height:477px;
background:#fff;
padding:0;
border: 1px solid #c3c4c4;
}
.thirdlevel {
position:absolute;
width:350px;
height:477px;
background:lightgreen;
left:350px;
border: 1px solid #c3c4c4;
top:-1px;
}
.thirdlevel.two-columns {
width:700px;
}
.thirdlevel div:first-child {
position:absolute;
left:0;
}
.thirdlevel div {
position:absolute;
right:0;
}
.column {
width:350px;
}
.thirdlevel {
display:none;
}
.secondlevel {
display:none;
}
/*
.navbar ul li:hover > div:first-child {
display:block;
}
*/
.active {
display:block;
}
.hidden {
display:none;
}
.navbar ul li a {
display:block;
}
Demo
As you can see, in my CSS I had .navbar ul li:hover > div:first-child { display:block;}. This works, but without the links... Someone told me to try making the <a> display:block; but that didn't work either.
All I need to do(I think) is be able to select div:first-child for this to work, but so far I haven't found anything that works. What am I doing wrong?
Any help is greatly appreciated. Thank you people!
I'm not entirely sure what you're after, but maybe this helps.
With CSS:
.navbar > ul > li:hover > .secondlevel {
display: block;
}
.navbar .secondarylink:hover > .thirdlevel {
display: block;
}
Demo
With jQuery:
$(".navbar ul li").hover(function () {
$(this).find('.secondlevel').show();
}, function () {
$(this).find('.secondlevel').hide();
});
$(".secondarylink").hover(function () {
$(this).find('.thirdlevel').show();
}, function () {
$(this).find('.thirdlevel').hide();
});
Demo
It's doesn't matter with the <li>item</li> or <li>item</li> as long as you have the correct script.
As I looked into your script, the action you trigger is to add 'active' class to all the second/third level.
I've updated the script and now it only add class to the second level / third level accordingly.
$(this).find().addClass();
DEMO
Related
I'm working on a mock site for my web developer portfolio. I don't have much experience with Javascript and JQuery, but I'm trying to figure out the most efficient way to show and hide dropdowns for a nav menu. My JQuery isn't working and I wanted to know if anyone had any tips. Also, I do plan on making dropdowns for all the instruments in the first Ul.
HTML:
<body>
<div class="container-fluid">
<div id="main-page">
<ul id="main-menu">
<li class="main-menu-list-items" style="border: 1px solid black;">
<div class="dropdown">
<ul>
<li>Products</li>
<div id="myDropdown" class="dropdown-content">
<ul>
<li class="dropdown-submenu"><a onclick="myClarinetDrop()" class="clarinet-drop" href="#">Clarinet</a>
<div id="my-clarinet-dropdown" class="dropdown-content">
<ul>
<li>Bb Clarinet</li>
<li>Bb Bass Clarinet</li>
<li>Eb Clarinet</li>
<li>Alto Clarinet</li>
<li>Bb German Clarinet</li>
<li>Bb Contrabass Clarinet</li>
</ul>
</li>
<li>Saxophone</li>
<li>Flute</li>
<li>Bassoon</li>
<li>Recorder</li>
<li>Brass</li>
<li>Guitar</li>
<li>Piano</li>
<li>Orchestral</li>
<li>Percussion</li>
</div><!--closes "myDropdown"-->
</ul>
</div><!--closes dropdown-->
</li>
<li class="main-menu-list-items"style="border: 1px solid black;">
<span>Shop By Brands</span>
</li>
<li class="main-menu-list-items" style="border: 1px solid black;">
<span>How To Order</span>
</li>
<li class="main-menu-list-items" style="border: 1px solid black;">
<span>Quick Order</span>
</li>
<li class="main-menu-list-items" style="border: 1px solid black;">
<span>About Us</span>
</li>
</ul><!--closes "main-menu"-->
</div><!--closes "main-page"-->
</div><!--closes "container-fluid"-->
</body>
CSS:
body {
margin:0;
padding:0;
}
.main-menu-list-items {
list-style-type:none;/*removes bullet point*/
float:left;/*puts list items side by side -- with no spaces*/
padding:15px 75px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown >ul {
margin-left:-40px;
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display:none;
position: absolute;
min-width: 1154px;
border:1px solid black;
margin-left:-76px;
margin-top:15px;
height:50px;
list-style-type:none;
}
.dropdown-content > ul {
list-style-type:none;
}
.dropdown-content >ul >li {
position:relative;
float:left;
padding:15px 29px;
}
.dropdown-submenu > div > ul > li {
position:relative;
float:left;
padding:15px 52px 0 30px;
}
.dropdown-submenu > div > ul {
border:1px solid black;
height:50px;
margin-left:-70px;
bottom:-54px;
min-width: 1114px;
position:absolute;
list-style-type:none;
display:none;
}
/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
.show {display:block;}
JQuery:
$(' .main-menu-list-items > .dropdown').click(function() {
var submenu = $(this).children('.dropdown > ul');
if($('.dropdown-content').css('display') == 'none') {
$(submenu).show();
}
else {
$(submenu).hide();
}
});
If you want to open a single sub-menu, it should be sufficient to add a class. You can then show the child element (.dropdown-content) by adding another CSS rule. If you remove that class, the child node will be hidden again. I have rewritten your code a bit and improved it that purpose:
$('.main-menu-list-items > .dropdown').click(function() {
var $this = $(this); // performance, so we do not have to call $(this) multiple times
if(!$this.hasClass('show')) {
$this.addClass('show');
} else {
$this.removeClass('show');
}
});
Then add this to your CSS. This works because you previously have hidden this element within your CSS:
.show .dropdown-content {
display: block;
}
As a side note: remove onclick="myFunction()". You do not have this function defined, so it will only give you errors in the console.
The first thing you might want to fix is your HTML. The only allowed direct descendants of a ul are li, do remove the divs. Also, you have a few instances in your HTML where your closing brackets are in the wrong place, thus creating invalid HTML.
Here's a simple format for a menu, but you'd have to redo your CSS to use it:
<nav>
<ul>
<li class="dropdown">
<a href="#" >Products</a>
<ul class="sub-menu">
<li class="dropdown">
Clarinet
<ul class="sub-menu">
<li>Bb Clarinet</li>
<li>Bb Bass Clarinet</li>
<li>Eb Clarinet</li>
<li>Alto Clarinet</li>
<li>Bb German Clarinet</li>
<li>Bb Contrabass Clarinet</li>
</ul>
</li>
<li>
Saxophone
</li>
<li>
Flute
</li>
<li>
Bassoon
</li>
<li>
Recorder
</li>
<li>
Brass
</li>
<li>
Guitar
</li>
<li>
Paino
</li>
<li>
Orchestral
</li>
<li>
Percussion
</li>
</ul>
</li>
<li>
Shop By Brands
</li>
<li>
How to Order
</li>
<li>
Quick Order
</li>
<li>
About Us
</li>
</ul>
</nav>
Then, to show the sub-menu, regardless of how many times it's nested, you could do something like:
$('.dropdown').on('click', function() {
$(this).children('.sub-menu').toggleClass('hideSubMenu');
});
Thank you for all that helped me with this question!!
I completely re-did my HTML because I realized there were tons of errors.
HTML:
<nav>
<ul id="main-bar">
<li class="dropdown">
Product
<!--sub-menu will hold all contents in dropdown --list items-->
<ul id="product-bar" class="sub-menu">
<li>Clarinet</li>
<li>Saxophone</li>
<li>Flute</li>
<li>Bassoon</li>
<li>Recorder</li>
<li>Brass</li>
<li>Guitar</li>
<li>Piano</li>
<li>Orchestral</li>
<li>Percussion</li>
</ul><!--closes product-bar-->
</li><!--closes product list item that is holding all the products-->
<li>Shop By Brands</li>
<li>How to Order</li>
<li>Quick Order</li>
<li>About Us</li>
</ul><!--closes main-bar-->
</nav>
I re-did my CSS as well:
body {
margin:0;
padding:0;
}
#main-bar {
list-style-type:none;/*removes bullets*/
height:50px;/*sets height of main-bar to same height as li's in #main-bar*/
}
#main-bar > li {
float:left;/*puts list items next to each other*/
border:1px solid black;
padding:15px 80px;
}
#main-bar > li > a {
text-decoration:none;/*removes underline from link*/
}
#product-bar {
position: absolute;
min-width: 1154px
border:1px solid black;
margin-left:-81px;
margin-top:15px;
height:50px;
list-style-type:none;
display:none
}
#product-bar > li {
float:left;
padding:15px 30px;
}
#product-bar > li > a {
text-decoration:none;
}
.show #product-bar {
display:block;
}
And finally, I went with this approach for the JQuery
JQuery:
$('.dropdown').on('click', function() {
var $this = $(this);times
if(!$this.hasClass('show')) {
$this.addClass('show');
} else {
$this.removeClass('show');
}
});
I am using stopPropegation to aid me in the way my dropdowns work.
I am using it for multiple dropdowns to help me keep the dropdown open but if the user clicks anywhere else on the page then it will slide up the menu.
HTML
<nav id="moo">
<ul>
<li>Item 1 <i>o</i>
<div class="dropdown">
<ul>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
</li>
<li>Item 1 <i>o</i>
<div class="dropdown">
<ul>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
</ul>
</div>
</li>
</ul>
</nav>
<div class="clear"></div>
<div id="login-top">Login</div>
<div id="user">roooar</div>
CSS
ul { padding: 0px; margin: 0px; }
li { display: inline; }
nav li { position: relative; }
nav i { cursor: pointer; font-weight: bold; background-color: red;padding: 5px; }
.dropdown { display: none; position: absolute; border:1px solid #ccc; padding: 10px; }
.dropdown li {
display: block;
}
.clear {
clear:both;
}
#login-top {
background:blue;
padding:10px;
color:white;
margin-top:30px
}
#user {
background:pink;
margin-top:10px;
padding:50px;
}
SCRIPT
$('#login-top').click(function () {
var $user = $('#user');
if ($('#user').is(':visible')) {
$user.slideUp(300);
} else {
$user.slideUp(300);
$user.slideDown(300);
}
});
$('nav > ul > li').click(function (e) {
var $childDropdown = $(this).find('.dropdown');
if ($childDropdown.is(':visible')) {
var target = $(e.target);
if (!$(target).parents(".dropdown").length) {
$('.dropdown').slideUp(300);
}
} else {
$('.dropdown').slideUp(300);
$childDropdown.slideDown(300);
}
});
/* Anything that gets to the document
will hide the dropdown */
$(document).click(function () {
$(".dropdown").hide();
$("#user").slideUp();
});
/* Clicks within the dropdown won't make
it past the dropdown itself */
$("nav, #login-top, #user").click(function (e) {
e.stopPropagation();
});
I have 2 questions really about this.
Say if I click open the dropdown menu because I have included certain elements to be exempt from clicking elsewhere on the page - If I click anywhere else it will slide back up exactly how I want.
However, if I happen to click on the #login-top this will not make it slide up as I have added it to the code for the stopPropagation
Is there a may of making it work so that when ".dropdown" is active then you can click absolutely everywhere (including on the <div id='login'> And then when "#login" and "#user" is active you can click anywhere on "nav" and it will still slide up the div?
Is it the right thing to be doing by grouping all the classes and id's into the code:
$("nav, #login-top, #user").click(function (e) {
e.stopPropagation();
});
(I am struggling to explain this but hopefully you can see what I mean if you look at the fiddle version)
http://jsfiddle.net/susannalarsen/Nt2ZM/1/
I want to create a tab and when someone hover on that tab someway below a new ul items should display with fade in and fade out effect. Till now I have used mouseenter and the new diplay items should stay there to choose other options.
HTML
<ul class="sector-nav">
<li>Residential</li>
<li>Commerical</li>
<li>Private</li>
</ul>
<ul class="res-pro residential-pro">
<li>rProject 1</li>
<li>rProject 2</li>
<li>rProject 3</li>
</ul>
<ul class="com-pro commercial-pro">
<li>cProject 1</li>
<li>cProject 2</li>
<li>cProject 3</li>
</ul>
JS
$(document).ready(function() { $('.residential-main').mouseenter(function() { $('.residential-pro').show(); }); $('.residential-main').mouseleave(function () { $('.residential-pro').hide(); }); });
$(document).ready(function() { $('.commercial-main').mouseenter(function() { $('.commercial-pro').show(); }); $('.commercial-main').mouseleave(function () { $('.commercial-pro').hide(); }); });
See jsFiddle
You don't need javascript for this as you can do it using CSS only with the :hover psuedo selector.
First you need to make the related ul elements children of their parent li:
<ul class="sector-nav">
<li>
Residential
<ul class="res-pro residential-pro">
<li>rProject 1</li>
<li>rProject 2</li>
<li>rProject 3</li>
</ul>
</li>
<li>
Commerical
<ul class="com-pro commercial-pro">
<li>cProject 1</li>
<li>cProject 2</li>
<li>cProject 3</li>
</ul>
</li>
<li>Private</li>
</ul>
Then amend the following selectors to hide/show the relevant ul elements on hover:
.sector-nav > li {
display: inline;
padding-right: 20px;
border-right-width: 1px;
border-right-style: solid;
border-right-color: #999;
padding-left: 20px;
position: relative;
}
.sector-nav li > ul {
display: none;
position: absolute;
}
.sector-nav > li:hover > ul {
display: block;
}
Example fiddle
The better way would be to use CSS. Here is fiddle a with fadeIn animation example.
.fadeIn {
border: 1px solid #48484A;
font-size: 18px;
opacity:0;
-webkit-transition : all 2s ease-out;
-moz-transition : all 2s ease-out;
-o-transition : all 2s ease-out;
transition : all 2s ease-out;
}
.thisText:hover .fadeIn {
opacity: 1;
}
But since your are using JQuery, you can also use his fadein function which provide animation.
Here is an example from the JQuery documentation:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>fadeIn demo</title>
<style>
p {
position: relative;
width: 400px;
height: 90px;
}
div {
position: absolute;
width: 400px;
height: 65px;
font-size: 36px;
text-align: center;
color: yellow;
background: red;
padding-top: 25px;
top: 0;
left: 0;
display: none;
}
span {
display: none;
}
</style>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>
<p>
Let it be known that the party of the first part
and the party of the second part are henceforth
and hereto directed to assess the allegations
for factual correctness... (click!)
<div><span>CENSORED!</span></div>
</p>
<script>
$( "a" ).click(function() {
$( "div" ).fadeIn( 3000, function() {
$( "span" ).fadeIn( 100 );
});
return false;
});
</script>
</body>
</html>
See the doc for more examples (JQuery doc)
If you want to use js, your solution is very close.
Just replace jquery show,hide with fadeIn and fadeOut respectively and initially hide the elements from css. However you also need to modify your html, so that children are presented under their parents.
HTML
<ul class="sector-nav">
<li class="residential-main">Residential<ul class="res-pro residential-pro">
<li>rProject 1
</li>
<li>rProject 2
</li>
<li>rProject 3
</li>
</ul>
</li>
<li class="commercial-main"><a href="#" >Commerical</a>
<ul class="com-pro commercial-pro">
<li>cProject 1
</li>
<li>cProject 2
</li>
<li>cProject 3
</li>
</ul>
</li>
<li>Private
</li>
</ul>
CSS
.sector-nav li {
display: inline;
}
.residential-pro , .commercial-pro{
display:none;
position:absolute;
padding:0;
}
.residential-pro li, .commercial-pro li{
display:block;
}
JS
$(document).ready(function () {
$('.residential-main,.residential-pro').mouseenter(function () {
$('.residential-pro').stop(false,true).offset({left:$('.residential-main').offset().left}).fadeIn();
});
$('.residential-main').mouseleave(function () {
$('.residential-pro').stop(false,true).fadeOut();
});
});
$(document).ready(function () {
$('.commercial-main,.commercial-pro').mouseenter(function () {
$('.commercial-pro').stop(false,true).offset({left:$('.commercial-main').offset().left}).fadeIn();
});
$('.commercial-main').mouseleave(function () {
$('.commercial-pro').stop(false,true).fadeOut();
});
});
http://jsfiddle.net/tEMQj/7/
When I created a drop down menu using css, it generates a line break before and after drop down menu
Here is html code
<body>
<!--nav class="navi"-->
<div class="navi" id="navi">
<ul>
<li>Home</li>
<li>About us
<ul>
<li>History</li>
<li>Company Profile</li>
<li>Core Values And Mission</li>
<li>Strategy</li>
</ul>
</li>
<li>Our Brands
<ul>
<li>HAMARA GLUCOSE D</li>
<li>HAMARA HEALTH CARE PATENT PRODUCTS</li>
<li>WAHT'S NEW</li>
</ul>
</li>
<li>Nutrition Space
<ul>
<li>Product FAQ</li>
<li>Health & Wellness</li>
</ul>
</li>
<li>Media
<ul>
<li>News Paper Clippings</li>
<li>Product Photos</li>
<li>Founder which...</li>
</ul>
</li>
<li>HSS</li>
<li>Copackers & Investors</li>
<li>Career</li>
<li>Communities</li>
<li>Contact Us</li>
</ul>
</div>
<!--/nav-->
</body>
and here is css code
<style>
.navi ul li
{
float:left;
}
.navi ul li a
{
display:block;
padding: 10px;
text-decoration:none;
}
.navi ul li:hover > a
{
color:white;
}
.navi ul
{
display:inline-table;
list-style:none;
padding: 0 0px;
position:relative;
background:#C93;
}
.navi ul ul
{
display: none;
position:absolute;
}
.navi ul ul li
{
/*display:block;*/
float:none;
}
.navi ul li:hover > ul
{
display:block;
background:#FC0707;
}
</style>
So I don't want to generate a line break
*{
padding:0;
margin:0;
}
Add this to styles
try using the white-space property
assign this to the div:
.navi
{
white-space: nowrap;
}
some more examples
If you meant the first layer of a remove display:block; from below code else if it is the second layer of a i.e. menu options
Try chaning
.navi ul li a {
display:block;
padding: 10px;
text-decoration:none; }
to
.navi ul li > a {
display:block;
padding: 10px;
text-decoration:none; }
I believe that block style has been applied to ALL the a creating a break inside the menu options too
Where it generates line break? By default div display type is block which takes 100% width of its parent and obviously pushed content down which is next to it in the flow.
Do you want to add content before and after the menu?
#navi{
display: inline;
}
Also make before and after content's display property to inline ( if no width is specified ) or inline-block ( if you want to specify width ).
I have the following html
<ul id="header">
<li class="dropdown"><span>Our Locations</span>
<ul>
<li>London</li>
<li>New York</li>
</ul>
</li>
<li class="dropdown"><span>Language Selector</span>
<ul>
<li>English</li>
<li>German</li>
<li>French</li>
<li>Chinese</li>
<li>Mandarin</li>
</ul>
</li>
</ul>
And am trying to get a menu which looks the following way
The difficulty the odd shape of the background and the fact that the text will change with translations of the site.
At present I have the following javascript
(function ($) {
$.fn.dropDownMenu = function () {
$.each(this, function () {
var li = $(this);
li.hover(function () {
$(this).addClass("hover");
$('ul:first', this).css('visibility', 'visible');
}, function () {
$(this).removeClass("hover");
$('ul:first', this).css('visibility', 'hidden');
});
});
}
$(function () {
$(".dropdown").dropDownMenu();
});
})(jQuery);
The only way I can see possibly working is absolutely positioning the inner ul (contained by the li.dropdown) which will give me a box, z-indexing the parent li on top using left/right/top borders to get the join of the two boxes and then maybe adding an extra div to cover any overlap parent li. Am wondering if there is a better way?
Try this... it took a little while to figure out, and I haven't tested it for cross browser, but it works on IE 9. will probably need tweaking.
I added a div with a high z-index to mask part of the top border for the nested <ul>
CSS:
#header {
margin:0;
padding:6px 0 5px 0;
background-color:#FFFFFF;
list-style-type:none;
}
li.dropdown {
position:relative;
display:inline;
margin:0;
padding:0;
}
div.borderMask {
position:absolute;
display:none;
background-color:#FFFFFF;
padding:1px;
height:1px;
line-height:1px;
right:0px;
left:0px;
top:13px;
z-index:1000;
}
li.dropdown ul {
position:absolute;
display:none;
background-color:#FFFFFF;
border:solid 1px #CCCCCC;
width:150px;
right:-1px;
top:13px;
}
li.dropdown:hover {
background-color:#FFFFFF;
border-top:solid 1px #CCCCCC;
border-left:solid 1px #CCCCCC;
border-right:solid 1px #CCCCCC;
}
li.dropdown:hover ul {
display:inline;
}
li.dropdown:hover div.borderMask {
display:block;
}
HTML:
<ul id="header">
<li class="dropdown"><span>Our Locations</span>
<div class="borderMask"></div>
<ul>
<li>London</li>
<li>New York</li>
</ul>
</li>
<li class="dropdown"><span>Language Selector</span>
<div class="borderMask"></div>
<ul>
<li>English</li>
<li>German</li>
<li>French</li>
<li>Chinese</li>
<li>Mandarin</li>
</ul>
</li>
</ul>