I'm creating a web app that has a custom responsive menu. It's just your basic three list-item menu dropdown. When user clicks "hamburger" icon, it slides down. When they click on the "X", it slides up.
The problem having is that when the user clicks the "hamburger" icon in the mobile menu's closed state and then they click another link on the page outside of the mobile menu, the menu stays in its open/slid down state and becomes unusable unless the user reloads the page.
What do I need to put in my JS function or my CSS to prevent this behavior? I appreciate the help.
The code:
HTML:
<nav class="home-header-content__nav--menu">
<ul>
<li>About</li>
<li>Terms</li>
<li>Help</li>
</ul>
</nav>
<nav class="home-header-content__nav--mobile-menu">
<i class="fa fa-bars"></i>
<i class="fa fa-times"></i>
<ul>
<li>About</li>
<li>Terms</li>
<li>Help</li>
</ul>
</nav>
CSS (only the relevant stuff):
.home-header-content__nav--menu {
#media (max-width: $site-screen__iphone5s--landscape + 1px) {
display: none;
}
}
.home-header-content__nav--mobile-menu {
display: none;
text-align: right;
position: relative;
.fa {
font-size: 28px;
&:hover {
color: $site-color__secondary;
#include transition(0.2s ease-in);
cursor: pointer;
}
}
.fa-times {
display: none;
}
ul {
text-align: right;
font-weight: 700;
position: absolute;
top: 40px;
right: 0px;
background-color: $site-color__secondary;
border-radius: 5px;
padding: 10px 10px 10px 20px;
font-size: 18px;
}
a {
color: $site-color__white;
&:hover {
color: $site-color__secondary--darker;
}
}
#media (max-width: $site-screen__iphone5s--landscape) {
display: inline-block;
}
}
Javascript:
$(function responsiveHomeMenu(){
// Store content nodes in DOM
var $menuIcon = $('.home-header-content__nav--mobile-menu .fa');
var $menuList = $('.home-header-content__nav--mobile-menu ul');
// Hide menu links by default
$menuList.hide();
// Toggle menu with icon
$menuIcon.on("click", function(e){
$menuIcon.toggle();
$menuList.slideToggle(300);
$(document).off("click",function(){
$menuList.toggle();
})
});
});
Try this
// Toggle menu with icon
menuIcon.on("click", function(e){
menuIcon.slideToggle();
menuList.slideToggle(300);
});
$(document).on("click",function(){
menuList.slideUp();
});
});
Related
I want to start by apologizing for such a long question, I just hope I wont make it difficult to understand as a result.
I have created a side bar with three Menu elements in an UL which expand to show child elements, change background color and remove hover effect when clicked. I did this by defining a function that adds and remove classes containing relevant properties when the menu element is clicked.
The four specific things that I want the sidebar to do but cant seem to get it to do are as follows;
only one selected/clicked item to expand at a time while all the
rest of the unselected menu elements are collapsed. That means if I
click the first item, it expands and when I click the second one,
the first one collapses while the one I clicked expands etc.
The selected/clicked element changes its background color to
indicate it's selected.
The selected/clicked element has no hover effect on the text while
the unselected elements have a hover effect of text color change on
them.
I also want the selected menu element be able to toggle the
expansion on and off not affecting the other elements in the UL.
I think where I'm having most trouble with my code is in the adding and removal of classes especially given that the <a>Tags which are nested inside the <li> Tags (clicked elements) are where the "hover" class needs to be added/removed, as well as the <ul>Tags that expand are also nested inside the clicked elements.
function toggleMenu(e) {
var kids = document.querySelector("#menuList").children;
var unselectedLink = document.querySelectorAll(".unselected a");
var unselectedDropdown = document.querySelectorAll(".unselected ul");
//adds "unselected" class to all elements exept the selected one
for (var i = 0; i < kids.length; i++) {
kids[i].className = "unselected";
}
//adds "menuHover" class to all elements exept the selected element
for (var i = 0; i < unselectedLink.length; i++) {
unselectedLink[i].className = "menuHover";
}
for (var i = 0; i < unselectedDropdown.length; i++) {
unselectedDropdown[i].classList.remove("show")
}
//adds "selected" class, removes "menuHover" class and adds "toggle" to the selected element
e.className = "selected";
document.querySelector(".selected a").classList.remove("menuHover");
document.querySelector(".selected ul").classList.toggle("show");
}
.sidebar {
position: fixed;
width: 250px;
height: 100%;
left: 0px;
top: 0;
background: #1b1b1b;
font-family: sans-serif;
}
.menu-bar {
background: #1b1b1b;
height: 60px;
display: flex;
align-items: center;
padding-left: 42px;
}
.side-text {
color: #C5C5C5;
font-weight: bold;
font-size: 20px;
}
nav ul {
background: #1b1b1b;
height: 100%;
width: 100%;
list-style: none;
margin-left: 0;
padding-left: 0;
}
nav ul li {
line-height: 40px;
}
nav ul li a {
position: relative;
color: #C5C5C5;
text-decoration: none;
font-size: 14px;
padding-left: 43px;
font-weight: normal;
display: block;
width: 100%;
}
nav ul ul {
position: static;
display: none;
}
nav ul ul li a {
font-family: sans-serif;
font-size: 13px;
color: #e6e6e6;
padding-left: 80px;
font-weight: lighter;
}
.submenu-item:hover {
background: #1e1e1e!important;
}
/*...........selected and show..................*/
.selected {
background-color: #255DAA;
}
.show {
display: block;
}
/*...........unselected and hover..................*/
.unselected {
color: #1e1e1e;
}
.menuHover:hover {
color: #255DAA;
}
<nav class="sidebar">
<div class="menu-bar">
<label class="side-text">MENU</label>
</div>
<ul id="menuList">
<li class="selected" onclick="toggleMenu(this)">
Staff
<ul>
<li>New Staff</li>
<li>View Staff</li>
</ul>
</li>
<li class="unselected" onclick="toggleMenu(this)">
Notes
<ul>
<li>New Note</li>
<li>Edit Notes</li>
</ul>
</li>
<li class="unselected" onclick="toggleMenu(this)">
Tasks
<ul>
<li>New Tasks</li>
<li>Edit Task</li>
</ul>
</li>
</nav>
I am quite close but somehow, logically I am doing things the wrong way with the JavaScript, so any adjustments to the code to make it reach all four of the above goals will be much appreciated. thanks
A simple way to do this:
If the element was selected, just unselect it
If it wasnt, unselect all elements and select the clicked element
function toggleMenu(el) {
if (el.classList.contains("selected")) {
el.classList.remove("selected");
el.classList.add("unselected");
}
else {
for (const child of document.getElementById("menuList").children) {
child.classList.remove("selected");
child.classList.add("unselected");
}
el.classList.remove("unselected");
el.classList.add("selected");
}
}
Edit 1
You can use the following css to unhide the submenu of a selected menuitem:
.selected ul {
display: block;
}
Edit 2
I went to the trouble of actually implementing it.
function toggleMenu(el) {
if (el.classList.contains("selected")) {
el.classList.remove("selected");
el.classList.add("unselected");
}
else {
for (const child of document.getElementById("menuList").children) {
child.classList.remove("selected");
child.classList.add("unselected");
}
el.classList.remove("unselected");
el.classList.add("selected");
}
}
.sidebar {
position: fixed;
width: 250px;
height: 100%;
left: 0px;
top: 0;
background: #1b1b1b;
font-family: sans-serif;
}
.menu-bar {
background: #1b1b1b;
height: 60px;
display: flex;
align-items: center;
padding-left: 42px;
}
.side-text {
color: #C5C5C5;
font-weight: bold;
font-size: 20px;
}
/* menu */
.menu {
background: #1b1b1b;
height: 100%;
width: 100%;
list-style: none;
margin-left: 0;
padding-left: 0;
}
.menu-item {
line-height: 40px;
}
.menu-item a {
position: relative;
color: #C5C5C5;
text-decoration: none;
font-size: 14px;
padding-left: 43px;
font-weight: normal;
display: block;
width: 100%;
}
/* submenu */
.submenu {
position: static;
display: none;
list-style: none;
}
.submenu-item a {
font-family: sans-serif;
font-size: 13px;
color: #e6e6e6;
padding-left: 80px;
font-weight: lighter;
}
.submenu-item:hover {
background: #1e1e1e;
}
/* selected and unselected */
.selected {
background-color: #255DAA;
}
.selected .submenu {
display: block;
}
.unselected {
color: #1e1e1e;
}
.unselected:hover a {
color: #255DAA;
}
<nav class="sidebar">
<div class="menu-bar">
<label class="side-text">MENU</label>
</div>
<ul class="menu" id="menuList">
<li class="menu-item selected" onclick="toggleMenu(this)">
Staff
<ul class="submenu">
<li class="submenu-item">New Staff</li>
<li class="submenu-item">View Staff</li>
</ul>
</li>
<li class="menu-item unselected" onclick="toggleMenu(this)">
Notes
<ul class="submenu">
<li class="submenu-item">New Note</li>
<li class="submenu-item">Edit Notes</li>
</ul>
</li>
<li class="menu-item unselected" onclick="toggleMenu(this)">
Tasks
<ul class="submenu">
<li class="submenu-item">New Tasks</li>
<li class="submenu-item">Edit Task</li>
</ul>
</li>
</ul>
</nav>
As alternative to the accepted answer, here two different approaches I was working on...
#menuList li is a container for a list of <a> menu items which have adjacent <ul> sub-menu-items. For easy selection with CSS I assigned class .menu-item to those <a>.
The CSS logic for both versions is essentially equal:
set the .menu-item adjacent ul sub-menu-items hidden by default
define :hover colors
define colors for a selected .menu-item and adjacent ul (either :focus or .selected is true)
make .menu-item adjacent ul sub-menu-items visible when a .menu-item gets selected (ditto)
Difference: for CSS only we use the :focus selector, for CSS with Javascript we use class .selected.
CSS only (automatic focus and blur)
An <a> gets focus when clicked (like button, input, etc. :focus is true). When the user clicks/taps outside the focussed element it automatically loses focus again (gets blurred and :focus is false, as in :not(:focus) = 'blur'). We can use the CSS :focus selector to handle user clicks and modify elements, MDN: ':focus'.
CSS with Javascript (focus and blur on request)
The OP wants a selected .menu-item and its adjacent ul sub-menu-items to stay visible until the user specifically deselects it again. This cannot be done with the :focus selector, so we ignore that selector and use class .selected instead to handle focus and blur requirements ourselves, MDN: HTMLElement.blur().
The Javascript logic is fairly straightforward:
Attach a 'click'-eventListener (MDN: Element: click event) to main container #menuList handling:
when a .menu-item gets selected and it is the currently .selected then blur it (menuItemBlur())
otherwise
when we have a previously selected .menu-item open, blur that first (menuItemBlur())
and then focus the newly selected .menu-item (menuItemFocus())
Changes to OP code
removed unneeded CSS
removed unneeded class attributes from HTML
changed href="#" in <#menuList li a> to href="javascript:void(0)" to prevent it from creating an entry in the browser history (sub-menu-items will still create an entry).
The below snippet is heavily commented and should be self-explanatory.
'use-strict';
var activeItem; // Holds the currently '.selected''.submenu' (null/undefined if none)
// Attach 'click' event listener to the #menuList
document.getElementById('menuList')
.addEventListener('click', function(e) { menuItemToggle(e.target) });
function menuItemToggle(el) {
if (el.classList.contains('menu-item2')) { // When a '.menu-item' gets clicked (not its kids)
if (el.classList.contains('selected')) { // and it is the '.selected''.menu-item'
menuItemBlur(el); // then close it and remove focus()
}
else {
if (activeItem) // When there is a currently selected '.menu-item'
menuItemBlur(activeItem); // then deactivate it
menuItemFocus(el); // Now activate the clicked `.menu-item`
};
};
function menuItemBlur(el) {
el.classList.remove("selected"); // Set the '.menu-item' to not '.selected'
activeItem = null; // and remove the reference to it
el.blur(); // Remove focus from element for CSS ':focus'
// ...extend with other 'Blur' stuff...
};
function menuItemFocus(el) {
el.classList.add("selected"); // Set the '.menu-item' to '.selected'
activeItem = el; // and save a reference to it
// ...extend with other 'Focus' stuff...
};
};
.sidebar {
position: fixed;
width: 250px;
height: 100%;
left: 0px;
top: 0;
background: #1b1b1b;
font-family: sans-serif;
}
.menu-bar {
background: #1b1b1b;
height: 60px;
display: flex;
align-items: center;
padding-left: 42px;
}
.side-text {
color: #c5c5c5;
font-weight: bold;
font-size: 20px;
}
nav ul {
background: #1b1b1b;
height: 100%;
width: 100%;
list-style: none;
margin-left: 0;
padding-left: 0;
}
nav ul li {
line-height: 40px;
}
nav ul li a {
position: relative;
color: #c5c5c5;
text-decoration: none;
font-size: 14px;
padding-left: 43px;
font-weight: normal;
display: block;
width: 100%;
}
nav ul ul {
position: static;
display: none;
}
nav ul ul li a {
font-family: sans-serif;
font-size: 13px;
color: #e6e6e6;
padding-left: 80px;
font-weight: lighter;
}
/*************/
/* ADDED CSS */
/*************/
/* All classes starting with "menu-item" */
[class^="menu-item"] + ul { display: none } /* hide adjacent UL */
[class^="menu-item"]:hover { color: #255daa } /* hover color */
a + ul li a:hover { color: #c5c5c5; background-color: #1b1b1b }
/*
menu-item adjacent sub-menu-items hover colors
Here the generic form is used, but it would
probably be more clear to be specific and use:
- either .menu-item1:focus + ul li a:hover
- or .menu-item2.selected + ul li a:hover
*/
/*
':focus' version
This version uses the CSS ':focus' without any Javascript.
Main difference with the '.selected' version below is that when the
user clicks outside the '.menu-item', the '.menu-item' looses focus
and therefore gets hidden again (as :focus is no longer true).
*/
.menu-item1:focus,
.menu-item1:focus + ul { color: #e6e6e6; background-color: #255DAA } /* focus colors */
.menu-item1:focus + ul { display: block } /* show adjacent UL */
/*
'.selected' version, with Javascript.
Basically the same CSS, but now using class '.selected' instead of ':focus'.
Closing occurs only on user specific 'click'.
*/
.menu-item2.selected,
.menu-item2.selected + ul { color: #e6e6e6; background-color: #255DAA } /* focus colors */
.menu-item2.selected + ul { display: block } /* show adjacent UL */
/*********************/
/* for demo use only */
/*********************/
nav h3 {
color: rgba(100, 149, 237,.9); /* CornflowerBlue */
font-style: italic;
padding-left: 43px;
}
.anchor {
color: white;
padding-left: 43px;
}
.content {
font-size: 1.5rem;
margin: 5rem 300px;
}
/* preferred globals */
html,body { box-sizing: border-box; width: 100%; max-width: 100% }
*::before,*::after, * { box-sizing: inherit }
body { margin: 0 }
<nav class="sidebar">
<div class="menu-bar">
<label class="side-text">MENU</label>
</div>
<h3>test</h3>
<a class="anchor" href="javascript:void(0)">some '.sidebar' <a></a>
<ul id="menuList">
<h3>:focus version</h3>
<li>
<a class="menu-item1" href="javascript:void(0)">Staff</a>
<ul>
<li>New Staff</li>
<li>View Staff</li>
</ul>
</li>
<li>
<a class="menu-item1" href="javascript:void(0)">Notes</a>
<ul>
<li>New Note</li>
<li>Edit Notes</li>
</ul>
</li>
<li>
<a class="menu-item1" href="javascript:void(0)">Tasks</a>
<ul>
<li>New Tasks</li>
<li>Edit Task</li>
</ul>
</li>
<h3>.selected version</h3>
<li>
<a class="menu-item2" href="javascript:void(0)">Staff</a>
<ul>
<li>New Staff</li>
<li>View Staff</li>
</ul>
</li>
<li>
<a class="menu-item2" href="javascript:void(0)">Notes</a>
<ul>
<li>New Note</li>
<li>Edit Notes</li>
</ul>
</li>
<li>
<a class="menu-item2" href="javascript:void(0)">Tasks</a>
<ul>
<li>New Tasks</li>
<li>Edit Task</li>
</ul>
</li>
</ul>
</nav>
<div class="content">
<h3><b>Note</b></h3>
<p>
This demo uses two different approaches interchangeably creating a quirky behaviour,
which under normal circumstances would not exist.
</p>
<p>To reproduce:</p>
<ul>
<li>select a <i>':focus version'</i> menu item first
<li>then select a <i>'.selected version'</i> menu item
</ul>
<p>
As you can see, the selected <i>':focus version'</i> loses focus and a second
'click' is needed to activate the <i>'.selected version'</i> menu item.
This is because the first click event of the <i>'.selected version'</i> gets consumed by the blur event
of the <i>':focus version'</i>.
</p>
<p>Just so you know...</p>
</div>
For my webpage (Github Page), I want to make my menu sensible to the size of the screen, such that it collapses when they are too small and the elements do not fit. I am planning to add the following solution: w3schools, using a "burguer" icon to join all the elements when the screens are small.
I am able to create the menu with the different elements, to add the "burguer" icon, and then to hide it by default when the screen is big. However, the media queries and the js function must be wrong, because when I do my screen small, the "burguer" icon appears, but the other elements do not dissapear, and cliking on the "burguer" does nothing. I guess there is a mistakes or confussion with the id names somewhere. Could it be?
In the example from w3schools uses the div tab, but I am not. Is it indispensable for the example to work?
/* Toggle between adding and removing the "responsive" class to topnav when the user clicks on the icon */
function myFunction() {
var x = document.getElementById("nav");
if (x.className === "header_nav") {
x.className += " responsive";
} else {
x.className = "header_nav";
}
}
/* Header_nav ----- DRAFT */
#page-wrapper {
padding-top: 3.5em;
}
#header_nav {
background: rgba(0, 0, 0, 0);
box-shadow: 0 0 0.25em 0 rgba(0, 0, 0, 0);
cursor: default;
height: 3.5em;
left: 0;
line-height: 3.5em;
position: absolute;
top: 0;
width: 100%;
z-index: 100;
}
#header_nav .icon {
display: none;
}
#header_nav h1 {
height: inherit;
left: 1.25em;
line-height: inherit;
margin: 0;
position: absolute;
top: 0;
}
#header_nav nav {
position: absolute;
right: 1em;
top: 0;
}
#header_nav nav ul {
margin: 0;
}
#header_nav nav ul li {
display: inline-block;
margin-left: 1em;
}
#header_nav nav ul li a,
#header_nav nav ul li span {
border: 0;
color: inherit;
display: inline-block;
height: inherit;
line-height: inherit;
outline: 0;
}
#header_nav nav ul li a.button,
#header_nav nav ul li span.button {
height: 2em;
line-height: 2em;
padding: 0 1.25em;
}
#header_nav nav ul li a:not(.button):before,
#header_nav nav ul li span:not(.button):before {
margin-right: 0.5em;
}
#header_nav nav ul li.active>a,
#header_nav nav ul li.active>span {
color: #e44c65;
}
#header_nav nav ul li>ul {
display: none;
}
body.landing #page-wrapper {
padding-top: 0;
}
body.landing #header_nav {
background: transparent;
box-shadow: none;
position: absolute;
}
/* When the screen is less than 600 pixels wide, hide all links, except for the first one ("Home"). Show the link that contains should open and close the topnav (.icon) */
#media screen and (max-width: 600px) {
#header_nav a:not(:first-child) {
display: none;
}
#header_nav a.icon {
float: right;
display: block;
}
}
/* The "responsive" class is added to the topnav with JavaScript when the user clicks on the icon. This class makes the topnav look good on small screens (display the links vertically instead of horizontally) */
#media screen and (max-width: 600px) {
#header_nav.responsive {
position: relative;
}
#header_nav.responsive a.icon {
position: absolute;
right: 0;
top: 0;
}
#header_nav.responsive a {
float: none;
display: block;
text-align: left;
}
}
<html>
<head>
<title>Eduardo Alvarado</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="assets/css/main.css" />
<noscript><link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
<!-- Load an icon library to show a hamburger menu (bars) on small screens -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body class="is-preload">
<!-- Header Navigation Menu -->
<section id="header_nav">
<nav id="nav">
<ul>
<li>
<a href="index">
<p style="color:white">Home</p>
</a>
</li>
<li>
<a href="">
<p style="color:white">Research</p>
</a>
</li>
<li>
<a href="">
<p style="color:white">Game-dev</p>
</a>
</li>
<li>
<a href="photography">
<p style="color:white">Photography</p>
</a>
</li>
<li><i class="fa fa-bars"></i></li>
</ul>
</nav>
</section>
The whole code can be found in the repo (Github Repo).
Can you see maybe the error that I am not able to spot? Why the example from w3school is not applicable?
I would really appreciate your help here. Thank you very much in advance!
Here's a small reproducible solution based on your code:
https://jsfiddle.net/hneromu4/5/
I added a class fixed to the link elements that were supposed to stay when we resized the window:
<section id="header_nav">
<nav id="nav">
<ul>
<li class="fixed">Home</li>
<li>Research</li>
<li>Game-dev</li>
<li>Photography</li>
<li class="fixed hamburguer"><i class="fa fa-bars"></i></li>
</ul>
</nav>
</section>
I also tweaked your css and js.
In your CSS and HTML I have made some alterations as your hamburger menu was inside the same thing which you were trying to hide which is not really a good idea I have also adjusted your CSS slightly as you were setting a position to relative but not setting display to block. Hope this helps!
CSS (line 2525 - 2547):
#media screen and (max-width: 600px) {
#nav {display: none;}
#header_nav a.icon {
float: right;
display: block;
}
}
/* The "responsive" class is added to the topnav with JavaScript when the user clicks on the icon. This class makes the topnav look good on small screens (display the links vertically instead of horizontally) */
#media screen and (max-width: 600px) {
#nav.responsive {position: relative;display: block;}
#header_nav.responsive a.icon {
position: absolute;
right: 0;
top: 0;
}
#nav.responsive a {
float: none;
display: block;
text-align: left;
}
}
HTML:
<!-- Header Navigation Menu -->
<section id="header_nav">
<a class="icon" onclick="myFunction()"><i class="fa fa-bars"></i></a><nav id="nav" class="header_nav">
<ul>
<li><p style="color:white">Home</p></li>
<li><p style="color:white">Research</p></li>
<li><p style="color:white">Game-dev</p></li>
<li><p style="color:white">Photography</p></li>
</ul>
</nav>
</section>
I have set up a hamburger menu with a close icon already. I'm just not sure how to just turn off the hamburger menu with a simple click. Only thing I've been able to do is just reload the page completely. Perhaps there is some jquery that could be used to solve this issue.
The close menu button is item 1 in the menu list.
Here is my code.
<div class="menu-wrapper">
<nav>
<ul class="header-menu">
<li><i class="far fa-window-close"></i></li>
<li class="current">Home</li>
<li>Prints</li>
<li>Blog</li>
<li>Tutorials</li>
<li>Sports</li>
</ul>
</nav>
</div>
CSS:
#menu-icon {
display: hidden;
width: 40px;
height: 40px;
background: url(../img/menu-icon.png) center;
text-decoration: none;
}
#close-menu {
display: none;
}
#media only screen and (max-width: 600px) {
#menu-icon {
display:inline-block;
z-index: 10000;
}
#close-menu {
display: inline-block;
color: black !important;
font-size: 20px !important;
}
OK, here's an example of how to make a burger nav. Fiddle
HTML:
<nav data-state=closed>
<a>×</a>
<a href=something.html>Link 1</a>
<a href=something-else.html>Link 2</a>
<a href=etc.html>Link 3</a>
</nav>
See how we're preparing to toggle the open/closed state with a data attribute. (We could have used a class, but I prefer a DA in this case because it means we can toggle it; with a class, you'd have to remove one class and add anothe, e.g. remove 'closed' and add 'open'.)
The structure is simple; we use a nav element and use the first a within it as the close icon. We use the multiplication (times) entity for this.
CSS:
nav {
position: absolute;
right: 1rem;
top: 2rem;
padding: 1rem;
background-color: #d55 !important;
}
nav[data-state=closed] {
cursor: pointer;
background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Hamburger_icon.svg/220px-Hamburger_icon.svg.png') no-repeat 100%/100%;
width: 50px;
height: 50px;
}
nav a { display: block; }
nav a:not(:first-of-type) { border-bottom: solid 1px rgba(0, 0, 0, .2); padding: .8rem 0; }
nav[data-state=closed] * { display: none; }
nav a:first-of-type {
position: absolute;
right: .2rem;
top: -.1rem;
font-size: 2rem;
cursor: pointer;
font-weight: bold;
}
Now here's the key part, the JS:
//get nav element
let nav = $('nav');
//listen for clicks on it
nav.on('click', evt => {
//...get current state (open vs. closed)
let curr_state = nav.attr('data-state');
//...if open, and click was NOT to close icon (first A tag) ignore click
if (curr_state == 'open' && !$(evt.target).is('a:first-of-type')) return;
//...otherwise toggle state (open it or close it)
nav.attr('data-state', curr_state == 'closed' ? 'open' : 'closed');
})
Making movable menu items in html,
I have four menu items arranged in right corner of my site vertically one below the other like
Home
Services
Contact
About
Now i need On click of second element(services) the second element has come to top and first element(home) has to push down, similarly click on third element has to come to top and first has to push down .
Any help and any reference links Thanks ?
Here is how you could have the options jump straight to the top when you click them:
$(function() {
$('#menu').on('click', 'li', function(event) {
$(event.target).prependTo('#menu');
});
});
ul {
padding: 0;
}
li {
display: block;
list-style-type: none;
height: 30px;
line-height: 30px;
color: darkblue;
font-family: sans-serif;
background-color: #ddd;
padding-left: 10px;
margin: 5px 10px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="menu">
<li>Home</li>
<li>Services</li>
<li>Contact</li>
<li>About</li>
</ul>
jsFiddle link
I followed a great example of how to make a sub-menu appear/disappear on click here and made it work. Quite an accomplishment since I'm just starting with javascript. But just as I made it work a few other problems came up, I'll try to explain:
1.- I have a vertical main menu and one of the options, 'Products' has a sub-category that opens on hover below the parent item. When selecting one of its sub-categories, a bigger menu shows up in a new div to the right of the main menu. When this happens, the selected sub-category changes color and displays a bullet so the user knows which sub-category they are viewing. I was doing this using PHP to detect the current page and assign an "active" id. But when I had it like that the sub-menu show/hide didn't work and all the options were showing when first entering the page. So I changed the link reference from "page.php" to "#" ---which makes more sense since that option is not meant to be a link rather than just display another sub-menu but had to include it for the sake of displaying the 'active' id--- and now the show/hide works except after I click a sub-category, the menu to the right opens, but the previously selected sub-category that opens on hover closes and the php detect function doesn't work because I changed the reference to "#" and the link doesn't show an 'active' status; in fact, the 'home' option stays selected even when the second div is already showing.
It sounds confusing, I know. Here's the example, I hope it's clear what I'm trying to do. I'd appreciate if anyone knows a way around this.
2.- Once I can get this fixed, is there a way to make the second div slide from left to right instead of fading in?
Thanks in advance :)
See my update to your code.. http://jsfiddle.net/Jaybles/tkVfX/4/
CSS
.mainNav {
float: left;
width: 200px;
height: 100%;
min-width: 150px;
background-color: #e21a22;
}
.active{
font-weight:bold;
}
.mainSide {
font-size: 14px;
list-style: none;
font-family: Helvetica,"Helvetica Neue",Arial,sans-serif;
padding-top: 40px;
width: 143px;
margin-right: auto;
margin-left: auto;
}
.mainSide li a, .mainSide li {
color: #fff;
width: 143px;
display: block;
padding: 2px 0 2px 0;
text-decoration: none;
}
.mainSide ul li a {
width: 125px;
list-style: none;
padding: 6px 0 2px 18px;
}
.mainSide li a:hover {
color: #fdb046;
}
.mainSide li a#active, .mainSide ul li a#active {
color: #fdb046;
background: url("../img/bullet.jpg") right center no-repeat;
}
#subNavSys, #subNavApp, #subNavAcc {
float: left;
width: 200px;
height: 100%;
min-width: 150px;
background-color: #414143;
display:none;
}
#subSideSys, #subSideApp, #subSideAcc {
font-size: 14px;
list-style: none;
font-family: Helvetica,"Helvetica Neue",Arial,sans-serif;
padding-top: 163px;
width: 143px;
margin-right: auto;
margin-left: auto;
}
#subSideSys li a, #subSideSys li, #subSideApp li a, #subSideApp li, #subSideAcc li a, #subSideAcc li {
color: #fff;
width: 143px;
display: block;
padding: 2px 0 2px 0;
text-decoration: none;
}
#subSideSys li a:hover, #subSideApp li a:hover, #subSideAcc li a:hover {
color: #fdb046;
HTML
<div class="mainNav">
<img id="top" src="img/metal.jpg" width="143" height="43" alt="Index" />
<ul class="mainSide">
<li>Home</li>
<li>About us</li>
<li>Products
<ul>
<li>By system</li>
<li>By application</li>
<li>Accesories</li>
</ul>
</li>
</ul>
</div>
<div id="subNavSys">
<ul id="subSideSys">
<li>Sub-menu-1.1</li>
<li>Sub-menu-1.2</li>
<li>Sub-menu-1.3</li>
</ul>
</div>
<div id="subNavApp">
<ul id="subSideApp">
<li>Sub-menu-2.1</li>
<li>Sub-menu-2.2</li>
<li>Sub-menu-2.3</li>
</ul>
</div>
<div id="subNavAcc">
<ul id="subSideAcc">
<li>Sub-menu-3.1</li>
<li>Sub-menu-3.2</li>
<li>Sub-menu-3.3</li>
</ul>
</div>
JS
$(document).ready(function(){
$("#sys").click(function() {
$("#subNavApp").hide();
$("#subNavAcc").hide();
$("#subNavSys").fadeIn(800);
$('*').removeClass('active');
$(this).addClass('active');
});
$("#app").click(function() {
$("#subNavSys").hide();
$("#subNavAcc").hide();
$("#subNavApp").fadeIn(800);
$('*').removeClass('active');
$(this).addClass('active');
});
$("#acc").click(function() {
$("#subNavSys").hide();
$("#subNavApp").hide();
$("#subNavAcc").fadeIn(800);
$('*').removeClass('active');
$(this).addClass('active');
});
});