How to make a CSS onhover menu vanish when clicking in mobile - javascript

So I'm using a hoverdown menu at the top of my good free photos site.
On desktop, it works just fine when you hover down on it, the menu appears.
When you hover off of it, it goes away.
However, mobile does not have the hover behaviour so when on mobile you click on the menu to make it appear, you can't get rid of it.
I need it to go away if you click on the menu (but not the sublinks) or anywhere else on the page.
Here is the HTML code I am using:
<div class="menu-wrap">
<nav class="menu">
<ul class="clearfix">
<li>
Good Free Photos Menu<span class="arrow">▼</span>
<ul class="sub-menu">
<li>Free Stock Photos</li>
<li>Public Domain Images</li>
<li>Featured</li>
<li>Last 100 images</li>
<li>News</li>
<li>Tutorials</li>
</ul>
</li>
</ul>
</nav>
</div>
and the css:
.clearfix:after {
display:block;
clear:both;
}
/*----- Menu Outline -----*/
.menu-wrap {
width:100%;
box-shadow:0px 1px 3px rgba(0,0,0,0.2);
background:#3e3436;
}
.menu {
width:1000px;
margin:0px auto;
}
.menu li {
margin:0px;
list-style:none;
font-family:'Ek Mukta';
}
.menu a {
transition:all linear 0.15s;
color:#919191;
}
.menu li:hover > a, .menu .current-item > a {
text-decoration:none;
color:#be5b70;
}
.menu .arrow {
font-size:11px;
line-height:0%;
}
/*----- Top Level -----*/
.menu > ul > li {
float:left;
display:inline-block;
position:relative;
font-size:19px;
}
.menu > ul > li > a {
padding:10px 40px;
display:inline-block;
text-shadow:0px 1px 0px rgba(0,0,0,0.4);
}
.menu > ul > li:hover > a, .menu > ul > .current-item > a {
background:#2e2728;
}
/*----- Bottom Level -----*/
.menu li:hover .sub-menu {
z-index:1;
opacity:1;
}
.sub-menu {
width:160%;
padding:5px 0px;
position:absolute;
top:100%;
left:0px;
z-index:-1;
opacity:0;
transition:opacity linear 0.15s;
box-shadow:0px 2px 3px rgba(0,0,0,0.2);
background:#2e2728;
}
.sub-menu li {
display:block;
font-size:16px;
}
.sub-menu li a {
padding:10px 30px;
display:block;
}
.sub-menu li a:hover, .sub-menu .current-item a {
background:#3e3436;
}
I know this may require some JavaScript, but I don't know what code.

You should read the following post :
CSS :hover behaviour on touchscreen devices
The problem with your current design is that it relies on the :hover state to work, which would not always work (for keyboard navigation, and causes problem with touchscreens).
A lot of accessible implementations for dropdown menus are well documented
Your current code may work within your current configuration, all you have to do is set the focus outside of your menu, for instance:
close menu
<div class="menu-wrap">
<nav class="menu">
But this won't make accessible your menu and won't make it work in the browsers where the :hover state is not recognized as :focus

Here's what I would do:
I would start by transferring the hover state from the css hover to a class name like .dropdown-open.
Using jquery:
if the website is viewed on a computer, control this class on mouseover and mousout.
else, toggle the class on mousedown of the element.
The jQuery would look something like this:
$(document).ready(function(){
function checkWidthForMenu(){
if($(window).width() > 760) {
$('.sub-menu').mouseover(function(){
$(this).addClass('dropdown-open');
});
$('.sub-menu').mouseout(function(){
$(this).removeClass('dropdown-open');
});
} else {
$(document).mousedown(function(){
$('.sub-menu.dropdown-open').removeClass('dropdown-open');
});
$('.sub-menu').mousedown(function(){
$(this).toggleClass('dropdown-open');
});
}
}
checkWidthForMenu();
$(window).resize(checkWidthForMenu());
});
Edit:
Adam has a good point for accessibility; so in your css, add the styles for the opened menu to .sub-menu.dropdown-open, .sub-menu:focus {...} This will make it open on hover and on focus (using the tab key as navigation)

Related

Responsive menu's sub-menus not forcing scrolling when flowing offscreen

Edit: Problem solved by a user on another site. I have summarised this as a separate answer.
=====
Edit: I have tried various overflow settings for the nav but still nothing. This must be something simple, but I can't find it. Anyone?
=====
I have a responsive menu that is sticky when reaching the top of the page in larger windows, but fixed to the top permanently when displaying the hamburger. The menu is using Todd Motto's flaunt.js menu: https://toddmotto.com/labs/flaunt-js/
In the original demo (above) the menu is not fixed. Changing the CSS to make the menu fixed has the unfortunate effect of preventing menu scrolling.
I would like to prevent the body scrolling behind, which I can do successfully with jQuery toggleClass, but need to make the menu scrollable as it will often be extending off-screen in hamburger mode on smaller devices.
I have tried adding overflow-y: scroll to various parts of the menu structure; this creates the scroll track, but still there is no bar inside and no scrolling even when the menu extends off-screen.
The problem occurs when changing the nav's position in the CSS class .nav from position: relative in the default style, to position: fixed with the media query (max-width: 768px).
Is there a way of enabling the menu to scroll, ideally with the main browser's scrollbar (with the body not scrolling behind)?
My JS for preventing body scrolling and potentially enabling menu scrolling, while adding an overlay to the body, is:
$(document).ready(function(){
$( ".nav-mobile" ).click(function() {
$( "#overlay" ).toggle();
$( "#mybody").toggleClass("scroll no-scroll");
$( "#SomeIDinTheNavSomewhere").toggleClass("scroll no-scroll");
});
});
with CSS:
#overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 100%;
background: rgba(40,40,40, .75);
}
.no-scroll {
overflow-y: scroll;
position: fixed;
}
.scroll {
overflow-y: scroll;
}
I have chosen to keep the scroll-track to avoid the burger jumping side to side when toggling as a result of enabling / disabling the body scrolling, rather than using overflow: hidden, but both create the same unwanted behaviour regardless anyway.
A cropped down and minimal version of the flaunt.js menu's html, css and js is below.
jsfiddle position: fixed here: https://jsfiddle.net/m_d_a/6gtjpvck/1/
jsiddle position: relative here: https://jsfiddle.net/m_d_a/6gtjpvck/ don't worry about the layout, just to prove scrolling exists when .nav is not fixed.
HTML
<nav class="nav">
<ul class="nav-list">
<li class="nav-item">
Home
<ul class="nav-submenu">
<li class="nav-submenu-item">
Submenu item 1
</li>
<li class="nav-submenu-item">
Submenu item 2
</li>
<li class="nav-submenu-item">
Submenu item 3
</li>
<li class="nav-submenu-item">
Submenu item 4
</li>
</ul>
</li>
<li class="nav-item">
About
</li>
<li class="nav-item">
Services
<ul class="nav-submenu">
<li class="nav-submenu-item">
Submenu item 1
</li>
<li class="nav-submenu-item">
Submenu item 2
</li>
<li class="nav-submenu-item">
Submenu item 3
</li>
<li class="nav-submenu-item">
Submenu item 4
</li>
</ul>
</li>
<li class="nav-item">
Portfolio
</li>
<li class="nav-item">
Testimonials
</li>
<li class="nav-item">
Contact
</li>
</ul>
</nav>
CSS
a, a:hover {
text-decoration:none;
}
ul, ol {
list-style:none;
}
.nav {
position:relative;
display:inline-block;
font-size:14px;
font-weight:900;
}
.nav-list {
text-align:left;
}
.nav-item {
float:left;
*display:inline;
zoom:1;
position:relative;
}
.nav-item a {
display:block;
color:#FFF;
padding:15px 20px;
background:#7A1E61;
border-bottom:1px solid #8B2870;
}
.nav-item > a:hover {
background:#822368;
}
.nav-item:hover .nav-submenu {
display:block;
}
.nav-submenu {
display:none;
position:absolute;
left:0;
width:180px;
}
.nav-submenu-item a {
background:#8B2770;
border-bottom:1px solid #9A337E;
display:block;
padding:15px;
}
.nav-submenu-item a:hover {
background:#932C77;
}
.nav-mobile {
display:none; /* Hide from browsers that don't support media queries */
cursor:pointer;
position:fixed;
top:0;
right:0;
background:#3D3D3B;
background-size:18px;
height:50px;
width:50px;
}
.nav-click {
position:absolute;
top:0;
right:0;
display:none;
border-left:1px solid #8B2870;
height:49px;
width:50px;
cursor:pointer;
}
.nav-click i {
display:block;
height:48px;
width:48px;
background:url(https://toddmotto.com/labs/flaunt-js/img/drop.svg) no-repeat center center;
background-size:20px;
}
.nav-click:hover {
background-color:#6E1656;
}
.nav-rotate {
-webkit-transform:rotate(180deg);
-moz-transform:rotate(180deg);
-ms-transform:rotate(180deg);
-o-transform:rotate(180deg);
transform:rotate(180deg);
}
/*-----------*\
Media Queries
\*-----------*/
#media only screen and (min-width: 320px) and (max-width: 768px) {
.nav-mobile {
display:block;
position: fixed;
}
.nav {
width:100%;
padding:50px 0 0;
}
.nav-list {
display:none;
}
.nav-item {
width:100%;
float:none;
}
.nav-item > a {
padding:15px;
}
.nav-click {
display:block;
}
.nav-mobile-open {
border-radius:5px 5px 0 0;
-webkit-border-radius:5px 5px 0 0;
-moz-border-radius:5px 5px 0 0;
}
.nav-item:hover .nav-submenu {
display:none;
}
.nav-submenu {
position:static;
width:100%;
}
}
JS
;(function($) {
// DOM ready
$(function() {
// Append the mobile icon nav
$('.nav').append($('<div class="nav-mobile"></div>'));
// Add a <span> to every .nav-item that has a <ul> inside
$('.nav-item').has('ul').prepend('<span class="nav-click"><i class="nav-arrow"></i></span>');
// Click to reveal the nav
$('.nav-mobile').click(function(){
$('.nav-list').toggle();
});
// Dynamic binding to on 'click'
$('.nav-list').on('click', '.nav-click', function(){
// Toggle the nested nav
$(this).siblings('.nav-submenu').toggle();
// Toggle the arrow using CSS3 transforms
$(this).children('.nav-arrow').toggleClass('nav-rotate');
});
});
})(jQuery);
Thank you. I realise there may be a bit to wade through here.
Thanks to a user on another site the problem I was having was because I hadn't specified a height for the nav.
For scrollbars to work with overflow, a height must be set.
max-height: calc(100% - 50px);
overflow-y: auto;
This gets the scrollbars working. However, as I would like the main window to have the scrollbars, I will remove the actual nav from being in position: fixed; to being embedded in a full screen overlay instead. This aside, the CSS above solves the problem and answers the question asked.

Mobile Navigation Menu not working (HTML, CSS & JQuery)

I am attempting to make a mobile navigation menu based off of this example: Basic Hamburger Menu
However, for what ever reason it does not work. When I click on the button nothing happens except rotating the 3-line graphic. The menu does not expand / appear.
When troubleshooting I have found out that if .mobile is site for display:block; instead of display:none; when the page loads, the javascript works for collapsing / hiding the menu, and making it reappear. Only the rotation of the 3-line graphic is opposite of what it should be. So, I know the javascript is working.
I just can't understand why it doesn't work with the nav hidden by default like in the example. I have played around with it for more then 3 hours so far and have gotten nowhere. There for I"m attempting to post it here to see if anyone might have any idea as to what might be going on as I am at a complete loss and about ready to wave the white flag.
This is the javascript on my page:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>
$('button').click(function () {
$(this).toggleClass('expanded').siblings('div').slideToggle();
});
//# sourceURL=pen.js
</script>
And the HTML / CSS is the same as the example except I have modified it so all the links are built into a UL.
HTML Code:
<div id="main_container">
<header>
<img src="<?php echo get_template_directory_uri(); ?>/assets/header3.jpg" alt"logo" width="100%">
</header>
<nav>
<div id="desktop_nav"><?php wp_nav_menu( $args ); ?></div>
</nav>
<nav>
<div id="mobile_nav" class="mobile">
<button>Toggle</button>
<div>
<?php wp_nav_menu( $args ); ?>
</div>
</div>
</nav>
And CSS Code:
#mobile_nav ul {
display: table;
width: 100%;
/*table-layout:fixed;*/
}
.mobile {
display:none;
position:relative;
width:100%;
min-height:50px;
}
.mobile div {
display:none;
}
.mobile button {
position:absolute;
top:10px;
left: 10px;
border:0;
text-indent:200%;
overflow:hidden;
background:#363636 url(assets/menu.png) center no-repeat;
border-radius:3px;
background-size:80%;
width:30px;
height:30px;
outline:none;
transition:all 400ms ease;
-webkit-transition:all 400ms ease;
transition:all 400ms ease;
}
.mobile button.expanded {
-webkit-transform:rotate(90deg);
-ms-transform:rotate(90deg);
transform:rotate(90deg);
border:0;
}
.mobile ul li a {
display: block;
background: #000;
text-align: center;
padding: 20px 0;
border-bottom: 1px solid #363636;
text-decoration: none;
color: white;
width: auto;
}
.mobile ul li:last-child {
border-bottom: none;
display: table-cell;
}
.mobile ul li a:hover,
.mobile ul li a:active,
.mobile ul li a:focus {
background: #363636;
width: 100%;
}
#media (max-width: 800px) {
.mobile {
display:block;
}
.mobile div {display:block}
#desktop_nav {
display:none;
}
}
Thanks
Adding a class to the div called "toggle" and changing the format of the javascript to the following solved the issue.
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery('button').click(function(){
jQuery(this).toggleClass('expanded');
jQuery(".toggle").slideToggle();
});
});
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

How to make drop-down menu appear over slideshow?

I have my drop down menu directly above the slideshow. Because of this, the sub-menus get hidden behind the slideshow when I hover over the menu. I would like the sub-menus to appear over the slideshow.
Slideshow Code
var o=String.fromCharCode(60);var c=String.fromCharCode(62)
document.write(o+'iframe sr'+'c="http://slideful.com/vid.htm" frameborder="0" sty'+'le="border:0px;padding:0px;margin:0px;width:900px;height:563px;" allowtransparency="true"'+c+o+'/iframe'+c)
Dropdown Code
.tab {
font-family: arial, verdana, san-serif;
font-size: 14px;
}
.asd {
text-decoration: none;
font-family: arial, verdana, san-serif;
font-size: 13px;
color:#4234ff;
}
/*****remove the list style****/
#nav {
margin:0;
padding:0;
list-style:none;
}
/*****LI display inline *****/
#nav li {
float:left;
display:block;
width:100px;
background:#1E5B91;
position:relative;
z-index:500;
margin:0 1px;
}
/*****parent menu*****/
#nav li a {
display:block;
padding:8px 5px 0 5px;
font-weight:700;
height:23px;
text-decoration:none;
color:#ffffff;
text-align:center;
color:#ffeecc;
}
#nav li a:hover {
color:#470020;
}
#nav a.selected { /* style for default selected value */
color:#4234ff;
}
#nav ul { /* submenu */
position:absolute;
left:0;
display:none;
margin:0 0 0 -1px;
padding:0;
list-style:none;
}
#nav ul li {
width:100px;
float:left;
border-top:1px solid #fff;
}
#nav ul a { /* display block will make the link fill the whole area of LI */
display:block;
height:15px;
padding: 8px 5px;
color:#ff7777;
}
#nav ul a:hover {
text-decoration:underline;
padding-left:15px;
}
Dropdown jQuery
$(document).ready(function () {
$('#nav li').hover(function () {
$('ul', this).slideDown(350); //show its submenu
}, function () {
$('ul', this).slideUp(350); //hide its submenu
});
});
Dropdown HTML
<input type=hidden name=arav value="1*#*#*2">
<ul id='nav'>
<li><a href='#'>SHOP</a>
<ul>
<li style='background-color:#b0c4de;'><a href=http://link.com>Womens</a></li>
<li style='background-color:#bebebe;'><a href=http://link.com>Mens</a></li>
</ul>
</li>
</ul>
</input
I would like my submenus that are shown when you hover over the "Shop" button to show up over the slideshow that is below it. They hide under it.
#nav ul { /* submenu */
position:absolute;
left:0;
display:none;
margin:0 0 0 -1px;
padding:0;
list-style:none;
z-index:9999;
}
#nav ul li {
width:100px;
float:left;
z-index:9999;
border-top:1px solid #fff;
}
Using z-index you can achieve this.
You will want to wrap your iframe and give that container a z-index value of 1 and the navigation container should have a z-index value of 2.
You will also need to set the position property value to relative for both of these containers.
#nav {position: relative; z-index: 2;}
#iframeContainerName {position: relative; z-index: 1;}
Also, you may want to look into other ways of implementing the slideshow. Using document.write has potential issues: Why is document.write considered a "bad practice"?
I'm not sure how this would work if you're viewing your slideshow as in your code above (I'm not very familiar with Javascript or how this would work with iframes).
However, I came here also searching for answers, so I will post my solution in the case that it may help anyone who finds this page as I did.
I had the same issue, although my slideshow code looked like this.
<ul class="bjqs">
<li><img src="kjdsajkdhsja.png"></li>
</ul>
I found that changing the z-index to all the elements relating to the slideshow to lower than the drop down elements would not work - until I made my images background images in divs, as so:
<ul class="bjqs">
<li><div style="background-image:url(kjdsajkdhsja.png);width:200px;height:75px;"></div></li>
</ul>
Crummy workaround, but it did me fine for the project I was on.
For showing dropdown menu over slide show
write the code in css where you have written dropdown menu code
.dropdown_menu { visibility: visible; z-index: 100; }
it will work

Importing a feature of phpFox to SocialEngine

phpFox has released a theme named "Nebula" with the version 3.5.0. On this theme, there is button on the Header and the menu slides down when the user clicks the button. (Actually not a button, but a div)
I want to add this feature to SocialEngine. But JavaScript Code contains a phpFox variable and I don't know what it refers to. I am not so good at JavaScript.
HTML:
<div id="nb_features">
Features
<div id="nb_features_holder">
Menu widget code will be added here...
</div>
</div>
JavaScript:
$Behavior.customNebula = function(){
$('#nb_features_link').click(function(){
if ($(this).hasClass('nb_is_clicked')) {
$(this).removeClass('nb_is_clicked');
$('#nb_features_holder').slideUp('fast');
} else {
$(this).addClass('nb_is_clicked');
$('#nb_features_holder').slideDown('fast');
}
return false;
});
};
CSS:
#nb_features {
position:absolute;
top:0px;
right:0px;
}
#nb_features_link,
#nb_features_link:hover {
display:block;
width:40px;
height:40px;
line-height:40px;
text-indent:-1000px;
overflow:hidden;
background:url(~/application/modules/Wonder/externals/images/nb_features_link.png') no-repeat;
margin-top:-7px;
margin-right:20px;
}
#nb_features_link:hover {
background:#334d83 url(~/application/modules/Wonder/externals/images/nb_features_link.png') no-repeat;
}
#nb_features a.nb_is_clicked,
#nb_features a.nb_is_clicked:hover {
background:#334d83 url(~/application/modules/Wonder/externals/images/nb_features_link.png') no-repeat;
}
#nb_features_holder {
position:absolute;
background:#4f4f4f;
right:0px;
width:980px;
border:1px #304779 solid;
border-top:0px;
display:none;
margin-top:20px;
}
#nb_features_holder ul li a,
#nb_features_holder ul li a:hover {
float:left;
color:#fff;
height:30px;
line-height:30px;
padding:0px 10px 0px 10px;
text-decoration:none;
}
#nb_features_holder ul li a.menu_is_selected,
#nb_features_holder ul li a.menu_is_selected:hover {
background:#009AEF;
color:#fff;
}
#nb_features_holder ul li a:hover {
background:#2F2F2F;
-webkit-transition: all 0.50s ease;
-moz-transition: all 0.50s ease;
-o-transition: all 0.50s ease;
}
What should I do to make this code work with SocialEngine?
Well the $Behavior namespace is a wrapper for the onLoad event, is this the js variable you were talking about? If it is you can replace it for the more conventional jquery/mootools/etc way and it would probably work although you would have to match the selectors properly, dont know if the code you posted is everything you need

How to convert a css only megamenu to jquery based

I am using a megamenu in my site, which is purely css based. The disadvantage is that, it doesn't have any animation. The dropdown is getting show all on a sudden. So I am thinking of converting it to jquery based toggle. Here is the current code. How can I convert it to jQuery based?
.dropdown-1column,
.dropdown-2columns,
.dropdown-3columns,
.dropdown-4columns,
.dropdown-5columns {
margin:-1px auto 0 -285px;
float:left;
position:absolute;
text-align:left;
padding:10px 5px 10px 5px;
border:1px solid #dedede;
background:#fff;
z-index:999;
display:none;
}
.menu li:hover .dropdown-1column,
.menu li:hover .dropdown-2columns,
.menu li:hover .dropdown-3columns,
.menu li:hover .dropdown-4columns,
.menu li:hover .dropdown-5columns {
display:block;
}
Here is the code http://jsfiddle.net/gsTNS/
This pretty much does what you're looking for I think. Could probably be refined:
http://jsfiddle.net/gsTNS/5/
Basically I've added a class of "has-dropdown" to each LI that has a dropdown and I've added a "dropdown" class to each dropdown DIV.
Then use jQuery to activate a slideToggle function:
jQuery("div#menu ul.menu li.has-dropdown").hover(
function () {
$(this).find("div.dropdown").slideToggle();
},
function () {
$(this).find("div.dropdown").slideToggle();
}
);

Categories

Resources