Why can't I center my nav bar? - javascript

I am using jQuery to create a drop down nav menu and it works fine, but I can not get it to center on my page.
I have tried using align="center" in the div "menu", but that did not work. I then tried aligning it using the css for the div and the lis and uls, but that also did not work.
Here is my code
jQuery:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript">
</script>
<link rel="stylesheet" type="text/css" href="style.css">
<script type="text/javascript">
$(document).ready(function () {
$("#menu li").hover(function () {
$(this).children(":hidden").slideDown();
}, function(){
$(this).parent().find("ul").slideUp();
});
});
</script>
HTML:
<div id="menu">
<ul>
<li>Home
</li>
<li>test
<ul>
<li>drop1</li>
<li>drop2</li>
<li>drop3</li>
</ul>
</li>
<li>test
<ul>
<li>drop1</li>
<li>drop2</li>
</ul>
</li>
</ul>
</div>
CSS:
#menu {
height: 30px;
background-color: #26C7FF;
margin-left: 0;
margin-right: 0;
}
#menu li li:hover {
background-color: yellow;
cursor: pointer;
}
#menu ul, #menu li {
list-style-type: none;
padding: 0;
margin: 0;
}
#menu li {
float: left;
width: 120px;
list-style-type: none;
line-height: 30px;
text-align: center;
}
#menu li ul {
position: absolute;
background-color: #26C7FF;
display: none;
}
#menu li li {
float: none;
padding: 2px;
}
#menu a {
color: #000;
text-decoration: none;
}

Use display:inline-block; instead of floating the li elements and then use text-align:center; for the container ul.
#menu > ul > li {
display: inline-block;
}
Here is a working example:
http://codepen.io/taneleero/pen/MwojLV

Wrap it in a container that has a max-width of whatever width you'd like your menu to be:
.container {
max-width: 600px; // Or whatever
width: 100%;
margin: 0 auto;
}
#menu {
height: 30px;
background: #26C7FF;
}
<div class="container">
<div id="menu">
</div>

Please check this code. I think this is what you wanted.
< script type = "text/javascript" >
$(document).ready(function() {
$("#menu li").hover(function() {
$(this).children(":hidden").slideDown();
}, function() {
$(this).parent().find("ul").slideUp();
});
}); < /script>
#menu {
height: 30px;
background-color: #26C7FF;
margin-left: 0;
margin-right: 0;
}
#menu li li:hover {
background-color: yellow;
cursor: pointer;
}
#menu ul,
#menu li {
list-style-type: none;
padding: 0;
margin: 0;
text-align: center;
position: relative;
}
#menu li {
float: none;
width: 120px;
list-style-type: none;
line-height: 30px;
text-align: center;
display: inline-block;
}
#menu li ul {
position: absolute;
background-color: #26C7FF;
display: none;
left: 0;
right: 0;
}
#menu li li {
float: none;
padding: 2px;
}
#menu a {
color: #000;
text-decoration: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript">
</script>
<link rel="stylesheet" type="text/css" href="style.css">
<div id="menu">
<ul>
<li>Home
</li>
<li>test
<ul>
<li>drop1
</li>
<li>drop2
</li>
<li>drop3
</li>
</ul>
</li>
<li>test
<ul>
<li>drop1
</li>
<li>drop2
</li>
</ul>
</li>
</ul>
</div>
this is the JSFIDDLE link

Since you're setting your ordered list tags at a fixed width, the following css should fix your problem.
#menu ul {
width: 369px;
margin: 0 auto;
}
Here's a working jsfiddle.

Related

How to Target a Child Node Without Knowing Its Position Using Only Vanilla Javascript

I have created a mockup navbar, and using the mouseenter event, have been able to display the submenus inside their parent li element.
This has been achieved using the children property and locating the position of the submenu, but was wondering how this is achieved without knowing so, or if there is a better idiomatic approach.
The submenus and list items have the same class names.
Below, you will find my code:
'use strict';
var dropdown = document.getElementsByClassName('dropdown');
document.addEventListener('DOMContentLoaded', function(e) {
e.preventDefault();
Array.from(dropdown).forEach(function(node) {
node.addEventListener('mouseenter', function(event) {
event.target.children[1].style.display = 'block';
});
});
Array.from(dropdown).forEach(function(node) {
node.addEventListener('mouseleave', function(event) {
event.target.children[1].style.display = 'none';
});
});
});
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
header {
height: 20vh;
width: 100vw;
background-color: #000;
}
.navbar {
position: relative;
width: 100%;
margin: 0;
padding: 0;
float: left;
}
.navbar > li {
display: inline-block;
list-style-type: none;
position: relative;
float: left;
margin: 0;
padding: 0;
}
.navbar li a {
text-align: center;
padding-left: 30px;
white-space: nowrap;
}
.menu {
display: none;
position: absolute;
top: 100%;
left: 0;
padding: 0;
}
.menu > li {
list-style-type: none;
padding: 10px 0;
float: none;
}
li {
width: 100px;
}
a {
font-family: Helvetica Neue;
text-decoration: none;
color: #fff;
display: block;
}
<header>
<nav>
<ul class="navbar">
<li class="dropdown">I drop down
<ul class="menu">
<li>1</li>
<li>2</li>
</ul>
</li>
<li class="dropdown">So do I
<ul class="menu">
<li>3</li>
<li>4</li>
</ul>
</li>
<li>No effect</li>
<li>Same here</li>
</ul>
</nav>
</header>
One option is to add ids (or classes) to the target elements, then add some attribute to the controlling element to express which target element it controls. Without knowledge of the DOM relationship between the two nodes, you're going to have to add some information to connect them.
I was going to use a data- attribute, but then I remembered that by using aria-controls you could add some a11y too.
'use strict';
var dropdown = document.getElementsByClassName('dropdown');
document.addEventListener('DOMContentLoaded', function(e) {
e.preventDefault();
Array.from(dropdown).forEach(function(node) {
node.addEventListener('mouseenter', function(event) {
var menuId = event.srcElement.getAttribute('aria-controls');
document.getElementById(menuId).style.display = 'block';
});
node.addEventListener('mouseleave', function(event) {
var menuId = event.srcElement.getAttribute('aria-controls');
document.getElementById(menuId).style.display = 'none';
});
});
});
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
header {
height: 20vh;
width: 100vw;
background-color: #000;
}
.navbar {
position: relative;
width: 100%;
margin: 0;
padding: 0;
float: left;
}
.navbar > li {
display: inline-block;
list-style-type: none;
position: relative;
float: left;
margin: 0;
padding: 0;
}
.navbar li a {
text-align: center;
padding-left: 30px;
white-space: nowrap;
}
.menu {
display: none;
position: absolute;
top: 100%;
left: 0;
padding: 0;
}
.menu > li {
list-style-type: none;
padding: 10px 0;
float: none;
}
li {
width: 100px;
}
a {
font-family: Helvetica Neue;
text-decoration: none;
color: #fff;
display: block;
}
<header>
<nav>
<ul class="navbar">
<li class="dropdown" aria-controls="menu1">I drop down
<ul class="menu" id="menu1">
<li>1</li>
<li>2</li>
</ul>
</li>
<li class="dropdown" aria-controls="menu2">So do I
<ul class="menu" id="menu2">
<li>3</li>
<li>4</li>
</ul>
</li>
<li>No effect</li>
<li>Same here</li>
</ul>
</nav>
</header>
Another way (one I prefer) would be to use the structure of the HTML to find the nodes. To do this the ul.menu must be a descendant of the currentTarget. Then you can use querySelector to locate it.
'use strict';
var dropdown = document.getElementsByClassName('dropdown');
document.addEventListener('DOMContentLoaded', function(e) {
e.preventDefault();
Array.from(dropdown).forEach(function(node) {
node.addEventListener('mouseenter', function(event) {
this.querySelector(':scope > ul.menu').style.display = 'block';
});
node.addEventListener('mouseleave', function(event) {
this.querySelector(':scope > ul.menu').style.display = 'none';
});
});
});
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
header {
height: 20vh;
width: 100vw;
background-color: #000;
}
.navbar {
position: relative;
width: 100%;
margin: 0;
padding: 0;
float: left;
}
.navbar > li {
display: inline-block;
list-style-type: none;
position: relative;
float: left;
margin: 0;
padding: 0;
}
.navbar li a {
text-align: center;
padding-left: 30px;
white-space: nowrap;
}
.menu {
display: none;
position: absolute;
top: 100%;
left: 0;
padding: 0;
}
.menu > li {
list-style-type: none;
padding: 10px 0;
float: none;
}
li {
width: 100px;
}
a {
font-family: Helvetica Neue;
text-decoration: none;
color: #fff;
display: block;
}
<header>
<nav>
<ul class="navbar">
<li class="dropdown">I drop down
<ul class="menu">
<li>1</li>
<li>2</li>
</ul>
</li>
<li class="dropdown">So do I
<ul class="menu">
<li>3</li>
<li>4</li>
</ul>
</li>
<li>No effect</li>
<li>Same here</li>
</ul>
</nav>
</header>

How to dropdown or hide and show submenu with EventListener in javascript?

Basically, My subtopics element is hiding, i want subtopics element show once we clicked at Topics element and hide subtopics element again once we clicked at Topics. Just like hide and show elements
I'm trying to use classList with addEventListener when i run code it shows up there is an error which didn't works for me.
I also found out that most of people are using jquery because it's very easy, but for me i want to practice in javascript first.
I'm still looking forward to the situation that works for me. If anyone know how to code with this function please give me some solution thank you very much.
Here is my code please take a look.
var togglemenu = (function () {
var togSubtopics = document.getElementById("subtopics");
togSubtopics.addEventListener("click", function () {
togSubtopics.classList.toggle("show");
});
return {
togglemenu: togglemenu()
};
})();
body {
margin: 0;
}
li, a{
text-decoration: none;
list-style-type: none;
text-decoration-line: none;
color: black;
}
/*main-menu*/
#mainmenu {
position: relative;
}
#mainmenu ul {
margin: 0;
padding: 0;
}
#mainmenu li {
display: inline-block;
}
#mainmenu a {
display: block;
width: 100px;
padding: 10px;
border: 1px solid;
text-align: center;
}
/*subtopics*/
#subtopics {
position: absolute;
display: none;
margin-top: 10px;
width: 100%;
left: 0;
}
.show {
display: block;
}
#subtopics ul {
margin: 0;
padding: 0;
}
#subtopics li {
display: block;
}
#subTopics a {
text-align: left;
}
/*columns*/
#column1, #column2, #column3 {
position: relative;
float: left;
left: 125px;
margin: 0px 5px 0px 0px;
}
/*hover underline*/
#mainmenu li:hover {
text-decoration: underline;
}
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" type="text/css" href="index2.css" />
</head>
<body>
<div id="mainmenu">
<ul>
<li>Logo</li>
<li>Home</li>
<li>Topics
<div id="subtopics">
<div id="column1" class="columns">
<ul>
<li>example1</li>
<li>example2</li>
<li>example3</li>
</ul>
</div>
</div>
</li>
</ul>
</div>
<script src="index2.js"></script>
</body>
</html>
One possible way to do that:
just onclick - toggle that element's class (add or remove class show)
And in CSS add rules that give display: block to .submenu that is under .show
UPD Before show subitems of any item - make sure that you have hidden other opened submenus
(function () {
var menuElems = document.querySelectorAll("#mainmenu ul > li")
menuElems.forEach(function(elem){
elem.addEventListener("click", function(){
//hide all open submenus
menuElems.forEach(function(e){
e.classList.remove("show");
})
//show the one that is clicked right now
elem.classList.add("show");
}, false)
});
})();
body {
margin: 0;
}
li, a{
text-decoration: none;
list-style-type: none;
text-decoration-line: none;
color: black;
}
/*main-menu*/
#mainmenu {
position: relative;
}
#mainmenu ul {
margin: 0;
padding: 0;
}
#mainmenu li {
display: inline-block;
}
#mainmenu a {
display: block;
width: 100px;
padding: 10px;
border: 1px solid;
text-align: center;
}
/*subtopics*/
.subtopics {
position: absolute;
display: none;
margin-top: 10px;
width: 100%;
left: 0;
}
.show .subtopics{
display: block;
}
.subtopics ul {
margin: 0;
padding: 0;
}
.subtopics li {
display: block;
}
.subTopics a {
text-align: left;
}
/*columns*/
#column1, #column2, #column3 {
position: relative;
float: left;
left: 125px;
margin: 0px 5px 0px 0px;
}
/*hover underline*/
#mainmenu li:hover {
text-decoration: underline;
}
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" type="text/css" href="index2.css" />
</head>
<body>
<div id="mainmenu">
<ul>
<li>Logo</li>
<li>Home
<div class="subtopics">
<div id="column1" class="columns">
<ul>
<li>Home_example1</li>
<li>Home_example2</li>
<li>Home_example3</li>
</ul>
</div>
</div>
</li>
<li>Topics
<div class="subtopics">
<div id="column1" class="columns">
<ul>
<li>Topic_example1</li>
<li>Topic_example2</li>
<li>Topic_example3</li>
</ul>
</div>
</div>
</li>
</ul>
</div>
<script src="index2.js"></script>
</body>
</html>
UPD
Code that removes show class from menuElems onclick to subtopic
var subtopicElems = document.querySelectorAll(".subtopics ul > li a")
subtopicElems.forEach(function(item){
item.addEventListener("click", function(event){
menuElems.forEach(function(menuElem){
menuElem.classList.remove("show")
})
event.stopPropagation(); //gotta stop bubbling
}, false)
})
about Bubbling and Capturing

responsive horizontal menu with dropdown menus

I have a horizontal responsive menu that works great, here is link to the page with it
I tried to make a new one with dropdown menus but can't get it to work. Instead of having a dropdown appear on hover, it shows the menus automatically in the line below. Here is link to codepen showing the errors http://codepen.io/mlegg10/pen/akLaVA
$(document).ready(function() {
$('nav').prepend('<div id="responsive-nav" style="display:none">Menu</div>');
$('#responsive-nav').on('click', function() {
$('nav ul').slideToggle()
});
$(window).resize(function() {
if ($(window).innerWidth() < 768) {
$('nav ul li').css('display', 'block');
$('nav ul').hide()
$('#responsive-nav').show()
} else {
$('nav ul li').css('display', 'inline-block');
$('nav ul').show()
$('#responsive-nav').hide()
}
});
$(window).resize();
});
$(document).on('scroll', function() {
if ($(document).scrollTop() > 100) {
$('#nav').addClass('fixed')
} else {
$('#nav').removeClass('fixed')
}
});
body {
margin: 0;
font-family: Georgia;
}
#menu-bar {
width: 100%;
height: auto;
margin: 50px auto 0;
background-color: #ff4500;
text-align: center;
}
#header h1 {
padding: 15px 0;
margin: 0;
}
#nav {
background-color: #036;
text-align: center;
}
#nav ul {
list-style: none;
padding: 0;
margin: 0
}
#nav ul li {
display: inline-block;
padding: 5px 0;
margin: 0;
}
#nav.fixed {
width: 100%;
position: fixed;
top: 0;
left: 0;
}
nav ul li a {
padding: 0 5px;
text-decoration: none;
color: #fff;
}
nav ul li:hover {
background-color: #ff0000;
}
#responsive-nav {
cursor: pointer;
color: #fff;
font-family: Georgia;
font-weight: bold;
padding: 5px 0;
}
#content {
width: 90%;
margin: 0 auto 20px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
border: 1px solid #ddd;
padding: 5px;
}
#drop-nav li ul li {
border-top: 0px;
#drop-nav li ul li {
border-top: 0px;
}
ul li a {
display: block;
background: #036;
padding: 5px 10px 5px 10px;
text-decoration: none;
white-space: nowrap;
color: #fff;
}
ul li a:hover {
background: #f00;
}
**this part is in the head tags:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://responsive-nav.com/demo/responsive-nav.js"></script>**
<header id="menu-bar">
<nav id="nav">
<ul>
<li>Home
</li>
<li>Accomodations
</li>
<li>Amenities
</li>
<li>Rates
</li>
<li>Links
<ul>
<li>Dropwdown 1
</li>
<li>Dropdown 2
</li>
</ul>
</li>
<li>Contact
</li>
</ul>
</nav>
</header>
Your javascript code has lots of unclosed line endings - you are missing the semicolons quiet often.
Additionally, jQuery will apply nav ul to all elements it finds. Meaning if there is a second occurrence, which is the case in your case, it will be applied to that too.
Instead: you should give your level 0 menu a clean, identifiable class, which you can preciesly target:
<!-- Your new HTML Markup -->
<nav class="mother-of-all-dropdown-lists">
and then in your jQuery:
$('.mother-of-all-dropdown-lists').slideToggle();
Sorry, that I keep writing, there are jQuery selectors wrong as well:
The id / hashtag is missing, so..:
$('nav ul li').css('display','inline-block');
$('nav ul').show()
should be:
$('#nav ul li').css('display','inline-block');
$('#nav ul').show();

Dropdown Menu not working on Index.html after adding java script

I am Creating my personal website but I can not get the drop down to work on desktop then when it is on a mobile devise hide nav and click(using js) to show nav. But its not working only on the Index.html
<div class="content">
<div class="header">
<div class="logo">GM
</div>
<span class="menu-trigger">Menu</span>
<nav class="nav clearfix">
<ul class="clearfix">
<li><a class="active" href="index.html">Home</a>
</li>
<li>About
</li>
<li>Portfolio <i class="fa fa-angle-down fa-1"></i>
<ul class="sub-nav">
<li>Music
</li>
<li>Code
</li>
</ul>
</li>
<li>Contact
</li>
</ul>
</nav>
<!-- end of Nav -->
</div>
</div>
CSS:
/**Header**/
.nav {
height: 61px;
background: #381120;
}
.logo a{
float: left;
text-decoration: none;
color: #7e7e7e;
font-size: 43px;
padding-top: 11px;
padding-left: 30px;
}
.nav ul {
margin: 0;
padding: 0;
float: right;
}
.nav ul li {
list-style: none;
float: left;
display: block;
padding: 19px;
}
.nav ul li a {
color: #7e7e7e;
text-decoration: none;
font-size: 25px;
}
.nav ul ul.sub-nav {
display: none;
background: #381120;
width: auto;
position: absolute;
}
.nav ul li:hover > ul {
display: block;
}
.nav ul ul li {
float: none;
padding-left: 24px;
}
.nav ul li a.active {
color: #08a1c7;
}
.nav ul li a:hover {
color: #efefef;
}
and:
.menu-trigger{
padding-top: 16px;
padding-right: 30px;
font-size: 25px;
text-align: center;
display: none;
float: right;
color: #7e7e7e
}
.menu-trigger p{
color: #7e7e7e
}
/**480px**/
#media only screen and (max-width : 480px) {
.menu-trigger{
display: block;
}
.nav, .mobile-nav{
display: none;
}
.nav-expanded{
display: block;
}
.nav ul li{
float: none;
border-bottom: 1px solid #7e7e7e;
}
.nav ul li:last-child{
border-bottom: none;
}
}
Here is the JS sorry I forgot to put it on here:
jQuery(document).ready(function() {
jQuery(".menu-trigger").click(function() {
jQuery(".nav").slideToggle(400, function() {
jQuery(this).toggleClass("nav-expanded").css('display', '');
});
});
});
You really should be able to animate all of this with just CSS. You don't even need jQuery for this, other than for the click action maybe.
Also, and this may not be the case, but in past I have had to write my click handlers like this to bypass some odd bugs. SlideToggle in jQuery can cause some glitchy effects and its not really a great way to do animated menu's. Try to avoid slideToggle().
$("[your-selector]").on("click",function(){
/// do something...
});
I have created a jsfiddle with your code and its seems to work fine. Its rather unclear from what you ask, But what I guess is that your dropdown doesnt work on mobile screen. A problem could be importing jquery in your HTML file. That might solve your problem
jQuery(document).ready(function() {
jQuery(".menu-trigger").click(function() {
jQuery(".nav").slideToggle(400, function() {
jQuery(this).toggleClass("nav-expanded").css('display', '');
});
});
});
Nevermind I fix it I added a
<div class="content">///content goes here</div>
twice causing it to break Thank You for all your help still.

CSS horizontal submenu

I'm working on the navigation bar for a website and currently the main menu is complete. However, the "Services" and "Products" buttons need to each have their own sub-menu. The sub-menu should normally be hidden from view and appears when the user mouse-overs on the respective button.
Here is a fiddle with the desired result. Obviously, I'd rather not use any javascript if possible.
The idea I had initially was to have sub-menu have position: absolute with a z-index value lower than that of the main-menu, so that it can slide underneath the main-menu. However, doing so messes up with the width if I give it width: 100% and since my site is responsive, I avoid static widths.
I also tried doing with relative positioning, but that doesn't work either.
Another thing I don't like with that approach is that the markup for the main menu and sub-menu get split. Is it possible to get the above result, but with this markup?
<nav>
<ul class="nav">
<li role="presentation" class="active">Home</li>
<li role="presentation">Services
<ul>
<li role="presentation">Link 1
<li role="presentation">Link 2
</ul>
</li>
<li role="presentation">Products
<ul>
<li role="presentation">Link 3
<li role="presentation">Link 4
</ul>
</li>
<li role="presentation">About</li>
<li role="presentation">Contact</li>
</ul>
</nav>
Here is my code:
CSS
body {
font-size: 0;
}
.bodyframe {
display: inline-block;
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.6);
}
.div_container {
max-width: 1460px;
width: 100%;
display: inline-block;
margin: 0 auto;
}
header {
width: 100%;
height: 49px;
}
.nav {
display: block;
position: relative;
list-style: none;
background: #304770;
z-index: 10;
}
.nav li {
display: inline-block;
background-color: #304770;
margin: 0 5px;
}
.nav li a {
padding: 12px 15px;
font-size: 18px;
color: #EFEFEF;
display: block;
}
.nav li.active a {
color: orange;
}
.nav li.active a:before {
width: 100%;
}
.nav li a:hover {
background-color: #304770;
color: orange;
transition: color 0.25s;
}
.nav li a:before {
content: "";
display: block;
position: absolute;
left: 0;
bottom: 0;
height: 3px;
width: 0;
background-color: orange;
-webkit-transition: width 0.2s;
transition: width 0.2s;
}
.nav li:nth-last-of-type(1) a:after {
display: none;
}
.nav li a:hover:before {
width: 100%;
}
.nav li a:after {
content: "";
display: block;
position: absolute;
right: -8px;
top: 21px;
height: 6px;
width: 6px;
background: #ffffff;
opacity: .5;
}
.subnav {
list-style-type: none;
display: block;
position: relative;
top: -49px;
margin: 0;
z-index: 1;
background-color: #ccc;
-webkit-transition: top 0.2s;
}
.subnav li {
display: inline-block;
background-color: #ccc;
margin: 0 5px;
}
.subnav li a {
padding: 8px 10px;
font-size: 14px;
color: #EFEFEF;
display: block;
}
HTML
<div class="bodyframe div_container">
<header>
<nav>
<ul class="nav">
<li role="presentation" class="active">Home</li>
<li role="presentation">Services</li>
<li role="presentation">Products</li>
<li role="presentation">About</li>
<li role="presentation">Contact</li>
</ul>
</nav>
<ul class="subnav">
<li>Test</li>
<li>1243</li>
</ul>
</header>
</div>
If you only need the submenu to mimic the one in the example, without using jQuery, using the second chunk of HTML with the CSS you supplied you could do:
nav:hover~ul {
top: 0px;
}
This shows the next ul element, in this case the subnav, whenever the nav is hovered over ("~" selector means select the ul element preceded by nav:hover).
However, if you want to do something more dynamic... id suggest just using JS/jQuery as well

Categories

Resources