CSS and jQuery issues with height of drop down menus - javascript

So I've made some drop down menus. The drop downs are ul nested in li. For style reasons I need have the drop down height set to 0px with some padding when the page first loads. All my drop downs have different heights. When I put 100% in as the height to animate too, it does not work.
Here is a link: http://www.jasonfoumberg.com/test/writing.html
How do I get the drop downs to animate to the proper height. Each drop down has a different number of items.
jQuery
$(document).ready(function () {
var defHeight = $('ul:first', this).height();
console.log(defHeight);
$("ul li").hover(
function () {
$('ul:first', this).animate({
height: "100%"
});
}, function () {
$('ul:first', this).animate({
height: "0px"
});
});
});​
HTML
<div id="mainWrapperContent">
<div id="writingMenu">
<ul>
<li>critical reviews
<ul>
<li>frieze</li>
<li>Modern Painters</li>
<li>photograph</li>
<li>sculpture</li>
<li>NewCity</li>
</ul>
</li>
<li>Exhibition Catalogs
<ul>
<li>Catalog One</li>
<li>Catalog Two</li>
<li>Catalog Three</li>
<li>Catalog Four</li>
<li>Catalog Five</li>
</ul>
</li>
<li>BreakOut Artists
<ul>
<li>2012</li>
<li>2011</li>
<li>2010</li>
<li>2009</li>
<li>2008</li>
</ul>
</li>
<li>Cover Stories
<ul>
<li>Catalog One</li>
<li>Catalog Two</li>
<li>Catalog Three</li>
<li>Catalog Four</li>
<li>Catalog Five</li>
<li>Catalog One</li>
<li>Catalog Two</li>
<li>Catalog Three</li>
<li>Catalog Four</li>
<li>Catalog Five</li>
</ul>
</li>
</ul>
</div><!-- writing Menu -->
</div><!-- mainWrapper Content -->​
CSS
#writingMenu a {
margin: 0px 0px 0px 0px;
padding: 12px 5px 5px 5px;
text-align: right;
-webkit-transition: all .3s ease;
-moz-transition: all .3s ease;
-o-transition: all .3s ease;
-ms-transition: all .3s ease;
transition: all .3s ease;
background: #ffffff;
color: #B3B3B3;
min-width: 140px !important;
display: block;
}
#writingMenu a:hover {
color: #37342e;
}
#writingMenu ul li ul {
position: absolute;
width: 90%;
float: left;
overflow: hidden;
border-left: thin solid black;
border-bottom: thin solid black;
border-right: thin solid black;
margin-left: -5px;
padding-top: 5px;
background-image: url(images/speckled_backgrounddk.jpg);
display: block;
height: 0px;
}
#writingMenu ul li ul li {
background-image: none;
float: none;
}
#writingMenu ul li ul a {
margin: 0px;
padding: 0px;
text-align: left;
-webkit-transition: all .3s ease;
-moz-transition: all .3s ease;
-o-transition: all .3s ease;
-ms-transition: all .3s ease;
transition: all .3s ease;
color: #B3B3B3;
background-color: transparent;
background-image: none;
text-transform: lowercase;
color: #999999;
}​

$(document).ready(function() {
var defHeight = $('ul:first',this).height();
console.log(defHeight);
$("ul li").hover(
function () {
$('ul:first',this).stop().animate({height : "toggle"});
},
function () {
$('ul:first',this).stop().animate({height : "toggle"});
});
});
Havent tried but this should work

I'vde made a css-only based dd menu if you're interested...
HTML =>
<!-- by rocky -->
<div id="wrapper">
<div id='navMenu'>
<ul>
<li>Menu1
<ul>
<li>Dropdown1</li>
<li>Dropdown2</li>
<li id="submenu">Dropdown3
<ul>
<li>Submenu 1</li>
<li>Submenu2</li>
<li>Submenu3</li>
</ul>
</li>
</ul> <!-- End of Menu1-->
</li> <!-- Menu2 -->
<li>Menu2
<ul>
<li>Dropdown2 </li>
<li id="submenu">Dropdown2
<ul>
<li>Dropdown2</li>
</ul>
</li>
<li>Dropdown2</li>
</ul> <!-- End Inner UL -->
</li> <!-- ABOUT -->
<li>Menu3
<ul>
<li>Submenu3</li>
<li id="submenu">Submenu3
<ul>
<li>Submenu3</li>
</ul>
</li>
</ul> <!-- End Inner UL -->
</li> <!-- End main LI -->
</ul> <!-- End main UL -->
</div> <!-- End Nav -->
</div> <!-- End wrapper -->
And the CSS:
#navMenu {
margin: 0;
padding: 0;
}
#navMenu ul{
margin: 0;
padding: 0;
line-height: 30px;
}
#navMenu li{
margin: 0;
padding: 0;
list-style: none;
float: left;
position: relative;
}
#navMenu ul li a {
text-align: center;
text-decoration: none;
height: 30px;
width: 150px;
display: block;
color: #000;
}
#navMenu ul ul {
position: absolute;
visibility: hidden;
top: 30px;
}
#navMenu ul li:hover ul {
visibility: visible;
}
#navMenu ul li ul a:hover {
color: #999;
}
#navMenu ul ul li#submenu ul {
position: absolute;
visibility: hidden;
top: 30px;
}
#navMenu ul ul li#submenu:hover ul {
margin-top: -30px;
margin-left: 105px;
visibility: visible;
}
There is a demo here:
http://dbwebb.se/style/?id=152

Related

Back button like breadcrumbs in jquery

I am displaying the menu on the left side. As of now, there is no issue with the menu.
Now I am working on the back button. Once the user clicks on the Demo1 -> Demo 1.1 then it will show the Demo 1.1.1, Demo 1.1.2 etc. So I am planning to show back button at the top like
//back
Demo1->Demo 1.1
//dropdown
Demo 1.1.1
Demo 1.1.2
Demo 1.1.3
Demo 1.1.4
Note: My menu is completely dynamic, I don't want to add the static value.
$('.menu-item-has-children .sub-menu').css({
'left': '-320px'
});
$('.menu-item-has-children > a').click(function() {
//alert('hello');
var positionMenu = $(this).parent().attr('id');
//console.log(positionMenu);
$('.menu-item-has-children[id=' + positionMenu + '] > .sub-menu').css({
'left': '0px'
});
var pMenu1 = $(this).text();
console.log(pMenu1);
$('.secondary').prepend(pMenu1);
});
ul {
padding-left: 0;
}
.secondary {
z-index: 99;
background: #f8f8f8;
-webkit-box-shadow: 0 8px 24px rgba(229, 228, 230, 0.4);
box-shadow: 0 8px 24px rgba(229, 228, 230, 0.4);
-webkit-transition: left 0.2s ease, width 0.2s ease;
transition: left 0.2s ease, width 0.2s ease;
border-right: 1px solid #eaedf1;
position: fixed;
top: 0;
height: 100%;
padding: 12px;
width: 320px;
}
.menu li {
padding-bottom: 10px;
padding-left: 23px;
list-style: none;
}
.menu-item-has-children>a {
position: relative;
display: block;
}
.menu-item-has-children .sub-menu {
width: 100%;
height: 100%;
padding-top: 40px;
background: #f8f8f8;
list-style: none;
position: absolute;
top: 0;
left: 0;
transition: left .3s;
z-index: 10;
}
.menu-item-has-children>a::after {
display: inline-block;
vertical-align: middle;
font-family: "Font Awesome 5 Free";
font-weight: 900;
content: "\f054";
position: absolute;
right: 05px;
top: 0px;
font-size: 12px;
}
<script src="https://kit.fontawesome.com/97446b8f60.js" crossorigin="anonymous"></script>
<div class="secondary">
<ul id="menu-inner-page-menu" class="menu">
<li>Home</li>
<li id="menu-item-204" class="menu-item-has-children">Demo1
<ul class="sub-menu">
<li id="menu-item-304" class="menu-item-has-children">Demo 1.1
<ul class="sub-menu">
<li>Demo 1.1.1</li>
<li>Demo 1.1.2</li>
<li>Demo 1.1.2</li>
</ul>
</li>
<li id="menu-item-305">Demo 1.2</li>
<li id="menu-item-306">Demo 1.3</li>
<li id="menu-item-307">Demo 1.4</li>
</ul>
</li>
<li id="menu-item-205" class="menu-item-has-children">Demo2
<ul class="sub-menu">
<li id="menu-item-315">Demo 2.1</li>
<li id="menu-item-316">Demo 2.2</li>
</ul>
</li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
Now I am getting the output in the console.
Also getting the in the HTML view source
Now, How to make the clickable?
Your HTML.
<div class="secondary">
<div id="menu-breadcrumb"></div>
<ul id="menu-inner-page-menu" class="menu">
<li>Home</li>
<li id="menu-item-204" class="menu-item-has-children">Demo1
<ul class="sub-menu">
<li id="menu-item-304" class="menu-item-has-children">Demo 1.1
<ul class="sub-menu">
<li>Demo 1.1.1</li>
<li>Demo 1.1.2</li>
<li>Demo 1.1.2</li>
</ul>
</li>
<li id="menu-item-305">Demo 1.2</li>
<li id="menu-item-306">Demo 1.3</li>
<li id="menu-item-307">Demo 1.4</li>
</ul>
</li>
<li id="menu-item-205" class="menu-item-has-children">Demo2
<ul class="sub-menu">
<li id="menu-item-315">Demo 2.1</li>
<li id="menu-item-316">Demo 2.2</li>
</ul>
</li>
</ul>
</div>
<script src="https://kit.fontawesome.com/97446b8f60.js" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
CSS
ul {
padding-left: 0;
}
.secondary {
z-index: 99;
background: #f8f8f8;
-webkit-box-shadow: 0 8px 24px rgba(229, 228, 230, 0.4);
box-shadow: 0 8px 24px rgba(229, 228, 230, 0.4);
-webkit-transition: left 0.2s ease, width 0.2s ease;
transition: left 0.2s ease, width 0.2s ease;
border-right: 1px solid #eaedf1;
position: fixed;
top: 0;
height: 100%;
padding: 12px;
width: 320px;
}
.menu li {
padding-bottom: 10px;
padding-left: 23px;
list-style: none;
}
.menu-item-has-children>a {
position: relative;
display: block;
}
.menu-item-has-children .sub-menu {
width: 100%;
height: 100%;
padding-top: 40px;
background: #f8f8f8;
list-style: none;
position: absolute;
top: 0;
left: 0;
transition: left .3s;
z-index: 10;
}
/* select only first child li that has sub menu to top 40 */
.menu > li.menu-item-has-children > .sub-menu {
top: 40px;
}
.menu-item-has-children>a::after {
display: inline-block;
vertical-align: middle;
font-family: "Font Awesome 5 Free";
font-weight: 900;
content: "\f054";
position: absolute;
right: 05px;
top: 0px;
font-size: 12px;
}
/* below is style for menu breadcrumb */
.mbc-link-back {
color: #0066cc;
text-decoration: none;
}
#menu-breadcrumb a + a::before {
color: #222;
content: '>';
cursor: default;
padding: 0 3px;
}
JavaScript (jQuery)
$('.menu-item-has-children .sub-menu').css({
'left': '-320px'
});
var menuBreadcrumb = document.getElementById('menu-breadcrumb');
$('.menu-item-has-children > a').click(function() {
//alert('hello');
var thismenuLi = $(this).parent().attr('id');
let thismenuText = $(this).text();
let mbcElement = '<a class="mbc-link-back" href="#" data-menu-item-id="' + thismenuLi + '">' + thismenuText + '</a>'
menuBreadcrumb.insertAdjacentHTML('beforeend', mbcElement);
//console.log(thismenuLi);
$('.menu-item-has-children[id=' + thismenuLi + '] > .sub-menu').css({
'left': '0px'
});
});
// use event delegation to listen click on menu breadcrumb and go back.
$('body').on('click', '.mbc-link-back', function(e) {
e.preventDefault();
// in case user click on the item before last, go back all until the end.
$(this).nextAll().each(function(index) {
mbcGoBack($(this));
});
mbcGoBack($(this));
});
function mbcGoBack(jQThis) {
let menuLiId = jQThis.data('menuItemId');
$('.menu-item-has-children[id=' + menuLiId + '] > .sub-menu').css({
'left': '-320px'// must match from the beginning.
});
jQThis.remove();
}
I was renamed one of your JS variable to make it more understandable, add JS functional, modify CSS a little for top value for only first sub item, add CSS for menu breadcrumb.
See it in action

jQuery slideDown snap after page reload

I have already asked this question but didn't get any answers so I'll try once again.
I have built a navigation menu on WordPress using jQuery to have a slide down/up animation on the submenus. I am using flexbox on the submenus which is what seems to cause the problems. When I change it to block it works fine but the design is not what I am looking for.
The problem and how to recreate it: The first time you refresh the page (or run the code on jsfiddle) and hover over the menu, the submenu will slide down over the height it should stop at and snap back after that. After that all the other submenus work fine. It's just I would like to fix that snap back since it does not look that good.
Does anyone have an idea why this is happening and/or how to fix it?
Link for the jsfiddle where you can test the problem yourself: https://jsfiddle.net/u2zs38oL/
And the code for the jsfiddle below:
HTML:
<header>
<nav class="main-navigation" id="desktop-navigation">
<div class="container-fluid">
<div class="menu-menu-1-container">
<ul id="menu-menu-2" class="d-flex justify-content-center">
<li
class="has-mega-menu menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-has-children menu-item-92">
Test
<ul class="sub-menu">
<li
class="mega-menu-column menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-has-children menu-item-93">
Test
<ul class="sub-menu">
<li
class="menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-94">
Test</li>
</ul>
</li>
<li
class="mega-menu-column menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-149">
Test
<ul class="sub-menu">
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-150">
Test</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
</header>
CSS:
header .main-navigation {
display: block;
margin-left: 1rem!important;
margin-right: 1rem!important;
text-transform: uppercase;
}
header .main-navigation > div {
background: #000;
position: relative;
}
header .menu-menu-1-container {
height: 50px;
white-space: initial;
}
header #menu-menu-2 {
list-style: none;
margin: 0;
flex-direction: row;
}
header #menu-menu-2 > .menu-item {
padding: 0 20px;
height: 50px;
border-bottom: 3px solid;
border-color: #000;
display: flex;
align-items: center;
justify-content: center;
}
header #menu-menu-2 .menu-item:hover {
border-color: red;
transition: 0.1s ease-in-out;
}
header #menu-menu-2 > li:hover > a {
color: red;
}
header .has-mega-menu > .sub-menu {
position: absolute;
background: #fff;
top: 50px;
left: 0;
width: 100%;
display: none;
box-shadow: 0 5px 10px rgb(0 0 0 / 10%);
}
header #menu-menu-2 li, header #menu-menu-2 ul {
list-style: none;
padding: 0;
}
header #menu-menu-2 li a {
text-decoration: none;
}
header #menu-menu-2 > li > a {
color: #fff;
}
header .has-mega-menu a {
color: #000;
}
header .mega-menu-column {
margin-left: 10px;
margin-top: 25px;
margin-bottom: 25px;
padding: 0 15px!important;
}
header .mega-menu-column > a {
position: relative;
font-weight: 600;
letter-spacing: 1px;
padding-bottom: 10px;
pointer-events: none;
}
header .mega-menu-column > a::before {
content: "";
position: absolute;
height: 1px;
width: 14px;
bottom: 0;
background-color: #000;
opacity: 0.2;
}
header .mega-menu-column ul {
margin-top: 20px;
}
header .mega-menu-column ul li {
padding: 5px 0!important;
}
header .mega-menu-column ul a {
color: grey;
font-weight: 400;
line-height: 25px;
transition: all 0.3s ease-in-out;
text-transform: capitalize;
display: block;
}
header .mega-menu-column ul li a:hover {
-webkit-transition: -webkit-transform 0.3s ease-in-out;
-moz-transition: -moz-transform 0.3s ease-in-out;
-ms-transition: -ms-transform 0.3s ease-in-out;
-o-transition: -o-transform 0.3s ease-in-out;
transition: transform 0.3s ease-in-out;
-webkit-transform: translateX(5px);
-moz-transform: translateX(5px);
-ms-transform: translateX(5px);
-o-transform: translateX(5px);
transform: translateX(5px);
color: #000;
border-bottom: 1px solid red;
}
.d-flex {
display: flex;
}
.justify-content-center {
justify-content: center;
}
jQuery:
jQuery(document).ready(function() {
jQuery('.main-navigation .has-mega-menu').hover(function() {
jQuery(this).has('.sub-menu').children('.sub-menu').stop().slideDown({start: function() {
jQuery(this).css('display', 'flex');
}, duration: 250
});
jQuery(this).children('.sub-menu').css('z-index', '3')
}, function() {
jQuery(this).has('.sub-menu').children('.sub-menu').stop().slideUp(250);
jQuery(this).children('.sub-menu').css('z-index', '2')
});
});
I found a way around this problem (at least for my case). So I found if on page reload, the submenu that is hidden and shown, has display flex instead of none then there seems to be no problems with the snapping. But obviously I do not want to start with the menu opened.
So what I did was set the submenu to flex and hid the menu with z-index until the jQuery has loaded and then hid (set display none) the submenu with jQuery. Then when hovering over the menu item toggled the slideDown and added higher z-index to that object.
Fiddle can be found here: https://jsfiddle.net/e319ydkm/
Changes I made to the original code:
header .has-mega-menu > .sub-menu {
display: none -> flex;
z-index: -1;
}
.hide-under {
background: #fff;
z-index: 1;
height: 1000px;
}
jQuery('.main-navigation .has-mega-menu > .sub-menu').hide();
This of course is not a perfect solution and I couldn't really figure out what is causing it other than that it is caused by flexbox (probably). I will not mark this reply as an answer since this isn't really the solution.

How do I make a multi-level dropdown menu work on a touchscreen device using css or javascript?

How do I make a multi-level dropdown menu work on a touchscreen device using css or javascript? Because when I tested out my website on a touchscreen device I clicked on the dropdown menu (which worked fine), but when I tried to get rid of the dropdown menu I couldn't (unless I reloaded the page). I would like it to have it hover on desktop and not hover on touchscreens. Is that even possible? Here's my html and css text:
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/
normalize.min.css">
<style>
#media (max-width: 640px) {
.main-navigation{
position: absolute;
top: 166px;
left: 173px;
}
ul {
list-style: none;
padding: 0;
margin: 0;
background: #6e151e;
border-radius: 5px;
}
ul li {
display: block;
position: relative;
float: left;
background: #6e151e;
border-radius: 5px;
width: 130px;
}
li ul {
display: none;
position: absolute;
top: 37px;
left: 0px; }
ul li a {
display: block;
padding: 1em;
text-decoration: none;
white-space: nowrap;
color: #fff;
font-family: Helvetica;
font-size: 11px;
padding-top: 12px;
padding-bottom: 12px;
font-weight: 70000px;
border-radius: 5px;
text-align: center;
border-right: none;
}
ul li a:hover {
background: #054075;
transition: .4s ease;
}
li:hover > ul {
display: block;
position: absolute;
transition: .4s ease;
}
li:hover li {
float: none;
transition: .4s ease; }
li:hover a {
background: #6e151e;
transition: .4s ease;
}
li:hover li a:hover {
background: #054075;
transition: .4s ease;
}
#media (max-width: 640px) {
ul ul ul {
border-left: 1px solid #fff;
left: 130px;
top: 0px;
}
}
</style>
</head>
<body>
<ul class="main-navigation">
<li class="Menu">Menu
<ul>
<li>Section 1
<ul>
<li>Subsection 1</li>
<li>Subsection 2</li>
<li>Subsection 3</li>
<li>Subsection 4</li>
</ul>
</li>
<li>Section 1
<ul>
<li>Subsection 1
</li>
<li>Subsection 2</li>
<li>Subsection 3</li>
<li>Subsection 4</li>
</ul>
</li>
<li>Section 3
<ul>
<li>Subsection 1
</li>
<li>Subsection 2</li>
<li>Subsection 3</li>
<li>Subsection 4
</li>
</ul>
</li>
</ul>
</li>
</body>
</html>
like this? ... bootstrap...
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="index.html">Villa borghese</a>
</div>
<ul class="nav navbar-nav">
<li class="active">a</li>
<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">b<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>bo</li>
<li>ba</li>
<li>bb</li>
<li>bc</li>
<li>bd</li>
<li>be</li>
<li>bf</li>
</ul>
</li>
<li>c</li>
<li>d</li>
<li>e</li>
</ul>
</ul>
</div>
</nav>

Submenu disconnect on mouseover and cant navigate to submenu as well

I am trying to create a submenu, but had to keep the submenu HTML out of the main menu, and on mouseover it will show hide, but its not working as expected, I think I am not trying with a good approach, can someone look in to this and suggest.
Here is the JSfiddle demo
Notes
1. Problem is, when you mouseover on "Shop" and try to enter submenu, its hiding.
2. I had to keep the submenu html out of the main navigation as submenu has to be in full width.
3. I am also looking to add some transition effects, I know using display none/block, transition will not work but can somebody please suggest?
$('.shop').mouseenter(function(){
$('.primary-subnav').show()
}).mouseleave(function(){
$('.primary-subnav').hide()
});
.nav{float:left; width:100%;}
.primarynav {
list-style: none;
margin: 0;
padding: 0;
font-size: 15px;
text-align: right;
}
.primarynav > li {
list-style: none;
display: inline;
}
.primarynav > li > a {
display: inline-block;
text-decoration: none;
color: #333;
padding: 0 15px;
height: 67px;
line-height: 67px;
-webkit-transition: all 0.35s ease-in-out;
-moz-transition: all 0.35s ease-in-out;
-o-transition: all 0.35s ease-in-out;
-ms-transition: all 0.35s ease-in-out;
}
.primarynav > li > a:hover {
background-color: #c0e5da;
}
.primary-subnav {
position: absolute;
left: 0;
top: 64px;
width: 100%;
border-top: 2px solid #c0e5da;
background-color: rgba(255,0,0,0.9);
min-height: 350px;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="nav">
<ul class="primarynav">
<li>Shop </li>
<li>Nav Item </li>
<li>Nav Item </li>
<li>Nav Item</li>
<li>Nav Item</li>
</ul>
</div>
<div class="primary-subnav">
<div class="container"> Submenu Wrapper </div>
</div>
you can attach the same event handlers as you have attached to mouseover and mouseleave events of .shop to .primary-subnav.
$('.shop').mouseover(function(){
$('.primary-subnav').fadeIn(1000);
}).mouseleave(function(){
$('.primary-subnav').hide();
});
$('.primary-subnav').mouseover(function(){
$('.primary-subnav').show();
}).mouseleave(function(){
$('.primary-subnav').hide();
});
.nav{float:left; width:100%;}
.primarynav {
list-style: none;
margin: 0;
padding: 0;
font-size: 15px;
text-align: right;
}
.primarynav > li {
list-style: none;
display: inline;
}
.primarynav > li > a {
display: inline-block;
text-decoration: none;
color: #333;
padding: 0 15px;
height: 67px;
line-height: 67px;
-webkit-transition: all 0.35s ease-in-out;
-moz-transition: all 0.35s ease-in-out;
-o-transition: all 0.35s ease-in-out;
-ms-transition: all 0.35s ease-in-out;
}
.primarynav > li > a:hover {
background-color: #c0e5da;
}
.primary-subnav {
position: absolute;
left: 0;
top: 64px;
width: 100%;
border-top: 2px solid #c0e5da;
background-color: rgba(255,0,0,0.9);
min-height: 350px;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="nav">
<ul class="primarynav">
<li>Shop </li>
<li>Nav Item </li>
<li>Nav Item </li>
<li>Nav Item</li>
<li>Nav Item</li>
</ul>
</div>
<div class="primary-subnav">
<div class="container"> Submenu Wrapper </div>
</div>

Most efficient way to create a slide-down submenu in jQuery

I am trying to make a submenu which slides down from the main menu bar when hovering over a certain element. I am currently doing this using the following code:
$(document).ready( function() {
$('.navlist li a').hover( function() {
if( $(this).attr( 'data-param' ) == "parent" )
{
$('#subnavbar-' + $(this).attr( 'data-slug' )).slideDown( 200 );
}
}, function() {
if( $(this).attr( 'data-param' ) == "parent" )
{
var name = '#subnavbar-' + $(this).attr( 'data-slug' );
setTimeout( function() {
if( !$(name).is(':hover') )
{
$(name).slideUp( 200 );
}
}, 200 );
}
});
});
a {
color: white;
}
.navbar {
background-color: green;
margin-bottom: 0;
height: 30px;
}
ul.navlist {
list-style: none;
text-indent: 0;
margin: 0;
padding: 0;
float: left;
}
ul.navlist li {
display: block;
width: 100px;
float: left;
}
.subnavbar {
background-color: blue;
margin-top: 0;
height: 20px;
display: none;
}
ul.subnavlist {
list-style: none;
text-indent: 0;
margin: 0;
padding: 0;
float: left;
}
ul.subnavlist li {
display: block;
width: 80px;
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navbar">
<ul class="navlist">
<li>Item 1</li>
<li>Hover Here</li>
<li>Item 3</li>
</ul>
</div>
<div class="subnavbar" id="subnavbar-test">
<ul class="subnavlist">
<li>Subitem 1</li>
<li>Subitem 2</li>
<li>Subitem 3</li>
</ul>
</div>
As you can see by running the snippet; it works, but there are lots of bugs that I'm not sure what the best way to iron out are. Firstly, if the user hovers back and forth over the main menu item I don't want the event to be spammed, I could solve this problem using a setTimeout() and clearTimeout() but I'd like a better way if at all possible. Secondly, I'm not sure how best to get the subnavbar not to retract if the user has hovered over it instead of the parent menu item, how I'm doing it at the moment works, but then if the user hovers off, the navbar doesn't retract.
The efficient solution would be using just CSS. Absolutely no JQUERY required! Try this Fiddle.
HTML:
<nav>
<ul>
<li>Item 1</li>
<li>Item 2
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
<li>Sub Item 3
<ul>
<li>Sub Sub Item 1</li>
<li>Sub Sub Item 2</li>
</ul>
</li>
</ul>
</li>
<li>Item 3
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
</ul>
</li>
</ul>
</nav>
CSS Code:
nav {
margin: 100px auto;
text-align: center;
}
nav ul ul {
display: none;
}
nav ul li:hover > ul {
display: block;
}
nav ul {
background: -moz-linear-gradient(center top , #efefef 0%, #bbbbbb 100%) repeat scroll 0 0 rgba(0, 0, 0, 0);
border-radius: 10px;
box-shadow: 0 0 9px rgba(0, 0, 0, 0.15);
display: inline-table;
list-style: outside none none;
padding: 0 10px;
position: relative;
}
nav ul::after {
clear: both;
content: "";
display: block;
}
nav ul li {
float: left;
}
nav ul li:hover {
background: -moz-linear-gradient(center top , #4f5964 0%, #5f6975 40%) repeat scroll 0 0 rgba(0, 0, 0, 0);
}
nav ul li:hover a {
color: #fff;
}
nav ul li a {
color: #757575;
display: block;
padding: 15px 20px;
text-decoration: none;
}
nav ul ul {
background: none repeat scroll 0 0 #5f6975;
border-radius: 0;
padding: 0;
position: absolute;
top: 100%;
}
nav ul ul li {
border-bottom: 1px solid #575f6a;
border-top: 1px solid #6b727c;
float: none;
position: relative;
}
nav ul ul li a {
color: #fff;
padding: 5px 10px;
}
nav ul ul li a:hover {
background: none repeat scroll 0 0 #4b545f;
}
nav ul ul ul {
left: 100%;
position: absolute;
top: 0;
}
as you told me better css I've made a quick fiddle for you.
Of course you need to polish the style but the "working" is there.
css just:
.container {
height:30px;
background-color:green;
color:#fff;
}
.container > ul {position:relative;}
.container > ul li {
display:inline-block;
margin-right:30px;
}
.container > ul >li > ul {
position:absolute;
left:0;
background-color:blue;
top:0px;
z-index:-1;
}
.container > ul > li:hover > ul {
top:30px;
-webkit-transition: all 0.4s ease;
-moz-transition: all 0.4s ease;
-ms-transition: all 0.4s ease;
-o-transition: all 0.4s ease;
transition: all 0.4s ease;
}
edited: I change the aproach and insteed of makign the transition with height I've use just top. check it out
to solve your first issue I would recommend using the jQuery plugin Hover Intent. Like the name suggests, this provides an easy way to determine if the user intends to hover over the element and avoids the possibility of spamming the animation by quickly hovering in and out of the element multiple times.
To solve your second issue, if possible, you can add a containing element around both navbar and subnavbar and use that to close the subnavbar when you leave the containing element, if the subnavbar happens to be visible.
HTML:
<div id="containing_element">
<div class="navbar">
<ul class="navlist">
<li>Item 1</li>
<li>Hover Here</li>
<li>Item 3</li>
</ul>
</div>
<div class="subnavbar" id="subnavbar-test">
<ul class="subnavlist">
<li>Subitem 1</li>
<li>Subitem 2</li>
<li>Subitem 3</li>
</ul>
</div>
</div>
jQuery:
$(document).ready( function() {
function hoverEnter() {
$('#subnavbar-test').slideDown(200);
}
$('#hoverlink').hoverIntent( hoverEnter );
$('#containing_element').mouseleave(function () {
if($('#subnavbar-test').is(':visible')) {
$('#subnavbar-test').slideUp(200);
}
});
});
Remember to include the script for hover intent as well.

Categories