Displaying submenus on hover without javascript - javascript

I have a webpage that uses jquery to display a submenu div while a user is hovering over an a:link in the main parent menu.
$('.menu ul li').hover(function() {
$(this).find('.dropnav').stop(true, true).fadeTo('fast', 1);
}, function() {
$(this).find('.dropnav').stop(true, true).fadeOut(800, 0);
});
The problem is, I want this webpage's navigation feature to be independent of javascript. So when users do not have javascript enabled, the menu will still display - just without the effects of scrolls or fades.
Thanks.

Use the :hover CSS pseudo-class.
.menu ul li:hover .dropnav {
opacity: 1;
/* display: block; ? */
}

Here is a pretty solid example of a CSS based menu. There is JavaScript that goes with it, if you are looking for backwards compatibility to IE6.
http://qrayg.com/learn/code/cssmenus/

HTML
<ul class="main-nav">
<li>main nav-1
</li>
<li>main nav-2
<ul class="sub-nav">
<li>sub-nav-2.1</li>
<li>sub-nav-2.2</li>
<li>sub-nav-2.3</li>
</ul>
</div>
</li>
<li>main nav-3
<li>main nav-4
</ul>
css
ul.main-nav > li { position: relative; display: block; float: left; margin: 0 15px;}
ul.main-nav > li > a {display: block; line-height: 40px; }
ul.sub-nav { display:none; position: absolute; top: 40px; left: 0; min-width: 200px;}
ul.main-nav > li:hover ul.sub-nav { display: block; z-index: 999; }
check this one for live demo http://jsfiddle.net/q9YZf/

Related

Accordion on hamburger (Child links not displaying)

I'm trying to create an accordion which, on click, will display it's child links.
So in my demo below, on click of parent, I'm trying to display child.
$(function() {
// add icon on hamburger
$(".hs-item-has-children").append('<i></i>');
$(".hs-menu-children-wrapper").addClass('menu_hidden');
// on click, check if dropdown is down already
$(".hs-item-has-children").click(function() {
//$('.hs-menu-children-wrapper').toggleClass('menu_is_visibile');
if ($(".hs-menu-children-wrapper").hasClass('menu_hidden'))
$(".hs-menu-children-wrapper").removeClass('menu_hidden');
$(".hs-menu-children-wrapper").addClass('menu_is_visibile');
});
});
.menu li.hs-item-has-children i {
display: block;
position: absolute;
margin-top: 16px;
right: 50px;
margin-top: -28px;
}
.menu li.hs-item-has-children i {
display: block;
}
.menu li.hs-item-has-children i:before,
.menu li.hs-item-has-children i:after {
content: "";
position: absolute;
background-color: #ff6873;
width: 3px;
height: 9px;
}
.menu li.hs-item-has-children i:before {
transform: translate(-2px, 0) rotate(45deg);
}
.menu li.hs-item-has-children i:after {
transform: translate(2px, 0) rotate(-45deg);
}
.menu li.hs-item-has-children ul.hs-menu-children-wrapper.menu_hidden {
display: none !important;
}
.menu li.hs-item-has-children ul.hs-menu-children-wrapper.menu_is_visibile {
display: block !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="menu">
<ul>
<li class="hs-item-has-children" role="menu">Parent
<ul class="hs-menu-children-wrapper menu_hidden">
<li class="hs-menu-item">Child</li>
<li class="hs-menu-item">Child</li>
<li class="hs-menu-item">Child</li>
</ul>
</li>
<li class="hs-item-has-children" role="menu">Parent 2
<ul class="hs-menu-children-wrapper menu_hidden">
<li class="hs-menu-item">Child</li>
<li class="hs-menu-item">Child</li>
<li class="hs-menu-item">Child</li>
</ul>
</li>
</ul>
</div>
It's also a HubSpot menu, so cannot alter the markup too much (which is why I'm using .append())
Edit:
Trying to make only the selected parent links child link show. I.e. if I click Parent 2 in the demo above, only show the child links for that ul (currently both open).
Change your function to:
$(".hs-item-has-children").click(function() {
$(this).children('.hs-menu-children-wrapper').toggleClass('menu_is_visibile');
});
Jsfiddle: https://jsfiddle.net/ukowjqav/1/
Instead of using an if-else, you can toggle the class itself to view each parent's children. Also note that I'm using thisin the function. That way the code knows which particular item it is referencing. Hope this helps.

How to get mega menu with nested UL without JS?

We have the following html structure for our menu (see codepin). We would like to modify the menu without having to use JS on page load to move any elements around.
Here is what I tried, but cannot get the custom-dropdown to show like the screenshot below.
Here is my codepin that I have so far, but we are having hard time getting it to align in two columns like the screenshot. The goals below have been simplified, but should be applicable to other links like Category and Company as well since they follow similar structure.
Goal (see screenshot):
On hover of Testing 1, Collaboratively testing 1 and transition accurate should display
On hover of Collaboratively testing 1 then the Enthusiastically communicate cross-platform and Uniquely reconceptualize accurate should display
Screenshot:
Underline below Testing 1 is to simulate on hover effect
Grey background behind Collaboratively Testing is to indicate on hover effect, which results in goal #2 where they are display to the right.
Multi-Level Drop Down Menu with Pure CSS
ul {
list-style: none;
padding: 0;
margin: 0;
background: #1bc2a2;
}
ul li {
display: block;
position: relative;
float: left;
background: #1bc2a2;
}
/* This hides the dropdowns */
li ul { display: none; }
ul li a {
display: block;
padding: 1em;
text-decoration: none;
white-space: nowrap;
color: #fff;
border-bottom: 3px solid #1bc2a2
}
ul li a:hover {border-bottom: 3px solid #2c3e50}
/* Display the dropdown */
li:hover > ul {
display: block;
position: absolute;
}
li:hover li { float: none; }
li:hover a { background: #1bc2a2; }
li:hover li a:hover { background: #2c3e50; }
.main-navigation li ul li { border-top: 0; }
/* Displays second level dropdowns to the right of the first level dropdown */
ul ul ul {
left: 100%;
top: 0;
}
/* Simple clearfix */
ul:before,
ul:after {
content: " "; /* 1 */
display: table; /* 2 */
}
ul:after { clear: both; }
here comes your html code
<h1>Multi-Level Drop Down Menu with Pure CSS</h1>
<ul class="main-navigation">
<li>Home</li>
<li>Front End Design
<ul>
<li>HTML</li>
<li>CSS
<ul>
<li>Resets</li>
<li>Grids</li>
<li>Frameworks</li>
</ul>
</li>
<li>JavaScript
<ul>
<li>Ajax</li>
<li>jQuery</li>
</ul>
</li>
</ul>
</li>
</ul>

JS dropdown menu best practice

I want to implement the following tiny drop down menu into my project.
Is there anything inherently wrong with my code? I attempted the :hover pseudo via CSS but was unsuccessful. Is there a better way to JS this thing?
document.querySelector('.dropbtn').addEventListener('mouseenter', function(){
document.querySelector('.dropdown-content').style.visibility = 'visible'
})
document.querySelector('.dropbtn').addEventListener('mouseleave', function(){
document.querySelector('.dropdown-content').style.visibility = 'hidden'
})
.dropdown {
display: flex;
align-items: flex-start;
}
.dropbtn {
background-color: darkslategray;
color: white;
padding: 6px 10px 6px;
font-size: 18px;
border: none;
cursor: pointer;
}
.dropdown-content {
background-color: darkslategray;
display: inline-grid;
visibility: hidden;
padding: 6px 10px 6px;
}
img {
margin: 3px;
height: 40px;
width: 120px;
border: 1px solid gray;
}
<div class="dropdown">
<button class="dropbtn">Dropdown</button>
<div class="dropdown-content">
<img src="http://fullhdpictures.com/wp-content/uploads/2016/03/Blur-Backgrounds.jpg" alt="">
<img src="http://akveo.com/blur-admin/assets/img/blur-bg-blurred.jpg" alt="">
<img src="http://www.publicdomainpictures.net/pictures/50000/velka/blurred-background-green.jpg" alt="">
</div>
</div>
Codepen: https://codepen.io/HelleFl/pen/KyWYYX
Although there are several posts describing how to create a dropdown menu using just HTML and CSS, I'll try to answer your question.
tl;dr: Use CSS over JS for better performance
CSS or JS? Which one is better?
Basically whenever possible, use CSS over JS. There is a great SO answer about this here.
Going further, CSS animations should be preferred over JS animations unless the animation should have some advanced effects. There is a good google developers blog post on this as well.
How to create a dropdown menu
You can find the answer here. Basically you need to set the :hover onto the parent element, that holds both the link and submenu.
li img {
width: 120px;
height: auto;
}
ul > li {
display: inline;
position: relative;
min-width: 150px;
}
/* hide submenus by setting the max-height to 0 */
ul > li > ul {
max-height: 0;
overflow: hidden;
transition: max-height .75s ease;
}
/* set max-height to an approximate height it could have */
ul > li:hover > ul {
max-height: 300px;
}
ul.submenu {
background: #eee;
position: absolute;
left: 0;
top: 1em;
}
ul.submenu > li {
display: block;
}
<nav>
<ul>
<li>Hyperlink 1</li>
<li>
Hyperlink 2
<ul class="submenu">
<li><img src="http://fullhdpictures.com/wp-content/uploads/2016/03/Blur-Backgrounds.jpg" alt=""></li>
<li><img src="http://akveo.com/blur-admin/assets/img/blur-bg-blurred.jpg" alt=""></li>
<li><img src="http://www.publicdomainpictures.net/pictures/50000/velka/blurred-background-green.jpg" alt=""></li>
</ul>
</li>
</ul>
</nav>
I guess you was facing the same issue that I was facing when I checked your codepen, since the .dropbtn are in the same level as .dropdown-content, the selector .dropbtn:hover .dropdown-content wont work since its searching for a child inside .dropbtn, so you have to use the sibling selector:
.dropbtn:hover ~ .dropdown-content{
visibility: visible
}
(CSS animation its better than Javascript)
Also, a good practice in Javascript is to save the DOM element into an variable if you will use it multiple times, so you dont have to search for the DOM element again:
var dropBtnDOM = document.querySelector('.dropbtn');
var dropdownContentDom = document.querySelector('.dropdown-content');
dropBtnDOM.addEventListener('mouseenter', function(){
dropdownContentDom.style.visibility = 'visible'
})
dropBtnDOM.addEventListener('mouseleave', function(){
dropdownContentDom.style.visibility = 'hidden'
})
.dropdown:hover .dropbtn ~ .dropdown-content{
visibility: visible
}

hidden submenu in nav bar displaying on hover but not dropping down

I am very new to javascript, so I apologize in advance if I waste anyone's time with a problem that may have a "duh" answer :-)
I am creating a navigation bar for a webpage. It starts off as an unordered list, and I am styling it to float the list items horizontally across the page. That part works fine for me.
I started to work at incorporating an unordered list as a submenu of one of my original list items. When I hover the mouse over the main list item, the submenu items appear, and when I mouse out, the submenu items disappear. The problem is that when the submenu items appear, they display on top of the navigation link to the left, instead of breaking out and dropping down below the link that I am hovering over. I tried setting the position to relative, but then it just shoved the submenu to the right.
I think the problem may be with my css. If I do not apply the external style sheet, then things seem to work better.
Here is my html:
<ul class="nav">
<li>Home</li>
<li>Department Members</li>
<ul id="menu" style="display:none;position:absolute">
<li>Brian Kendricks</li>
<li>Tim Jones</li>
<li>David Kline</li>
</ul>
<li>Systems Used</li>
<li>System Status</li>
<li>Projects</li>
</ul>
My css is:
.nav li {
float: left;
width: 20%;
font-family: verdana,arial,sans-serif;
text-align: center;
padding-top: 5px;
padding-bottom: 5px;
background-image:none;
background-color: #004E98;
display: block;
}
.nav a {
color: white;
}
.nav a:hover {
color: white;
}
.nav li:a:hover {
background-color: #093F6D;
}
And here is my javascript:
function drop(menu) {
document.getElementById(menu).style.display = 'block';
document.getElementById(menu).style.position = 'relative';
}
function hide(menu) {
document.getElementById(menu).style.display = 'none';
}
I would like to stick to using javascript, as the course that I am taking does not wish for me to incorporate things like JQuery at this time.
Thanks in advance for any assistance that you may offer in pointing me in the right direction.
Make your submenu a child of the <li> they are under - instead of currently you have it a child of the overall <ul>. Then you can give the parent item relative positioning, and the child list absolute positioning with top 100% (putting it under the parent item).
function drop(menu) {
document.getElementById(menu).style.display = 'block';
}
function hide(menu) {
document.getElementById(menu).style.display = 'none';
}
.nav li {
float: left;
width: 20%;
font-family: verdana,arial,sans-serif;
text-align: center;
padding-top: 5px;
padding-bottom: 5px;
background-image:none;
background-color: #004E98;
display: block;
position: relative;
}
.nav a {
color: white;
}
.nav a:hover {
color: white;
}
.nav li:a:hover {
background-color: #093F6D;
}
.dropmenu {
position: absolute;
top:100%;
left: 0;
}
.dropmenu li {
display: block;
float: left;
width:100%;
}
<ul class="nav">
<li>Home</li>
<li>Department Members
<ul id="menu" class="dropmenu" style="display:none">
<li>Brian Kendricks</li>
<li>Tim Jones</li>
<li>David Kline</li>
</ul>
</li>
<li>Systems Used</li>
<li>System Status</li>
<li>Projects</li>
</ul>

Why doesn't this drop down menu work?

I've download the Refresh template by Styleshout.com since I really like it. But unfortunately, there was no drop down menu in it, only a normal menu.
So I tried to integrate a drop down menu which I found a nice tutorial for.
It does almost work - almost. Here's the result: the template on my webspace.
The menus are opened - but at the wrong location. Why? What's wrong with my implementation? All 3 drop down lists are opened under the first item.
I hope you can help me. Thanks in advance!
PS: Here's the code:
####################
####### HTML #######
####################
<ul id="nav">
<li>Nav #1
<ul>
<li>Nav #1.1</li>
<li>Nav #1.2</li>
</ul>
</li>
<li>Nav #2
<ul>
<li>Nav #2.1</li>
<li>Nav #2.2</li>
</ul>
</li>
<li>Nav #3
<ul>
<li>Nav #3.1</li>
<li>Nav #3.2</li>
</ul>
</li>
</ul>
####################
#### JAVASCRIPT ####
####################
sfHover = function() {
var sfEls = document.getElementById("nav").getElementsByTagName("LI");
for (var i=0; i<sfEls.length; i++) {
sfEls[i].onmouseover=function() {
this.className+=" sfhover";
}
sfEls[i].onmouseout=function() {
this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
}
}
}
if (window.attachEvent) window.attachEvent("onload", sfHover);
###################
####### CSS #######
###################
ul#nav li ul {
position: absolute;
left: -9999px;
top: 38px;
display: block;
width: 100px;
background-color: transparent;
}
ul#nav li {
position: relative;
}
ul#nav li ul li {
float: none;
}
/* Links in the drop down lists start */
ul#nav li ul li a {
clear: left;
display: block;
text-decoration: none;
width: 100px;
background-color: #333;
}
/* Links in the drop down lists end */
/* Making visible start */
ul#nav li:hover ul, #nav li.sfhover ul {
left: auto;
}
/* Making visible end */
You need to float the container LI's left and set the 'top' value on the pop-up boxes to 100%.
(Tested only in FF3.5)
ul#nav li {
position: relative;
float: left;
}
ul#nav li ul {
position: absolute;
left: -9999px;
top: 100%;
display: block;
width: 100px;
background-color: transparent;
}
I think the reason it's only working in Firefox, or I should say was only working in Firefox since this was posted so long ago, is that IE might need specific pixel locations for the top attribute instead of 100%. I would recommend trying 0px at least for IE, this worked for me recently at least.
Doesn't really explain it directly, but I would reccomend adding and subtracting a class attribute, not modifying (getAttribute, removeAttribute, etc.). Also, your class name has a space in it ( " sfhover" ) which probably isn't a good idea.
Here:
<li>
<a>Nav #1</a>
<ul>
<li>Nav #1.1</li>
<ul>
</li>
To move the entire menu and its submenu. You will have to set float:left at <li> not <a>
#menu ul li a {
float: none;
}
#menu ul li {
float: left;
}
One more thing, this doesn't relate to your problem. But, I think you should use display:none/block instead of left:-9999px/auto.
Hope it help.

Categories

Resources