I'm working on a navigation bar for my website and I've made some Javascript to go along with the CSS. Before you run it, make sure the result window is less than 760 pixels wide.
function compressNavbar() {
var x = document.getElementById("navbar");
if (x.className === "responsive-h2") {
x.className += " responsive-h2-expand";
} else {
x.className = "responsive-h2";
}
}
ul.blue {
background-color: DodgerBlue;
}
ul.blue * {
color: white;
}
/* Horizontal navbar */
ul.horizontal-navbar {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
}
.horizontal-navbar li {
float: left;
}
.horizontal-navbar li a {
display: block;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
/* responsive */
#media screen and (max-width: 760px) {
ul.responsive-h2 li {
display: block;
}
ul.responsive-h2 li:not(:first-child):not(:last-child) {
display: none;
/* Remove all links except home and the menu button */
}
ul.responsive-h2-expand {
position: relative;
}
.responsive-h2-expand li:last-child {
position: absolute;
right: 0;
top: 0;
}
ul.responsive-h2-expand li {
float: none !important;
display: block !important;
}
ul.responsive-h2-expand li * {
text-align: left !important;
}
ul.responsive-h2-expand li a {
padding: 10px 14px;
padding-left: 18px;
padding-bottom: 11px;
}
ul.responsive-h2-expand li {
list-style-type: none;
}
}
<ul class="responsive-h2 horizontal-navbar blue" id="navbar">
<li>Home</li>
<li>link</li>
<li>link</li>
<li>
<a href="javascript:void(0)" onclick="compressNavbar()">
Menu
</a>
</li>
</ul>
The beginning works fine - we have a nice, styled navbar with all links missing except Home and the menu button. But when I press the menu button, the expanded navbar is not styled with my blue class and does not feature all of my links. Additionally, when Menu is pressed again, most of my styling is missing.
What's wrong with my code that's making this happen? As I'm new to JS, I assume it's that- I think I might be doing something wrong with className but I don't know what or how to fix it.
Thanks in advance.
I think it's better to use classList.toggle:
function compressNavbar() {
var x = document.getElementById("navbar");
x.classList.toggle("responsive-h2-expand");
}
I think you are not replacing class properly
function compressNavbar() {
var x = document.getElementById("navbar");
if (x.className === "responsive-h2") {
x.className += " responsive-h2-expand";
// you are not adding "blue" and "horizontal-navbar" classes back
// ex: x.className = "responsive-h2 responsive-h2-expand horizontal-navbar blue"
} else {
x.className = "responsive-h2";
}
}
you can use classList methods to manipulate class effeciently
Related
I have this javascript code I am using to add a hamburger menu in my webpage
const hamburger = document.querySelector(".hamburger");
hamburger.addEventListener("click", mobileMenu);
function mobileMenu() {
hamburger.classList.toggle("active");
Menu.classList.toggle("active");
}
menuLink.forEach(n => n.addEventListener("click", closeMenu));
function closeMenu() {
hamburger.classList.remove("active");
Menu.classList.remove("active");
}
and i want to add a hamburger menu so webpage would be responsive for small devices.. no errors are occurring but still no results are being showed when i run my code.
how can i change this code in order to work
const Menu = document.getElementById('navbar__list');
const sections = document.querySelectorAll('section');
/**
* End Global Variables
*/
// build the nav
NavBuilder = () => {
//to loop from section 1 to 4 and add sections to navigation
for (s = 0; s < sections.length; s++) {
const liElem = document.createElement('li');
//const divElem = document.createElement("div");
const Id = sections[s].id;
const DataNav = sections[s].dataset.nav;
liElem.innerHTML = `<a class="menu__link" href="#${Id}">${DataNav}</a>`;
Menu.appendChild(liElem);
}
}
NavBuilder();
//when scroll add your-active class to section and class active to navigation bar elements
window.addEventListener('scroll', () => {
sections.forEach(s => {
const topDistance = s.getBoundingClientRect().top;
// if the distance to the top is between 0-150px
if (topDistance >= 0 && topDistance < 150) {
s.classList.add('your-active-class');
// add class active to navugation in order to highlight the navigation when scrolling
document.querySelector(`a[href="#${s.id}"]`).classList.add("active");
// otherwise, remove the class
} else {
s.classList.remove('your-active-class');
document.querySelector(`a[href="#${s.id}"]`).classList.remove("active");
}
});
});
//set style to highlight active navigation bar elements
const menuLink = document.querySelectorAll(".menu__link");
addStyle = () => {
menuLink.forEach((anchor) => {
anchor.addEventListener("click", function() {
menuLink.forEach((anchor) => {
anchor.classList.remove("active");
});
anchor.classList.add("active");
});
});
}
addStyle();
scrollFunction = () => {
const menuLink = document.querySelectorAll(".menu__link");
menuLink.forEach((anchor) => {
anchor.addEventListener("click", function(event) {
event.preventDefault();
document.querySelector(anchor.getAttribute("href")).scrollIntoView({
behavior: "smooth",
});
});
});
};
scrollFunction();
const hamburger = document.querySelector(".hamburger");
hamburger.addEventListener("click", mobileMenu);
function mobileMenu() {
hamburger.classList.toggle("active");
Menu.classList.toggle("active");
}
menuLink.forEach(n => n.addEventListener("click", closeMenu));
function closeMenu() {
hamburger.classList.remove("active");
Menu.classList.remove("active");
}
#media only screen and (max-width: 768px) {
.navbar__list {
position: fixed;
left: -100%;
top: 5rem;
flex-direction: column;
background-color: #fff;
width: 100%;
border-radius: 10px;
text-align: center;
transition: 0.3s;
box-shadow: 0 10px 27px rgba(0, 0, 0, 0.05);
}
.navbar__list.active {
left: 0;
}
.hamburger {
display: block;
cursor: pointer;
}
}
.navbar__menu ul {
padding: 2px;
padding-left: 0;
margin: 0;
text-align: left;
background-color: gray;
}
.navbar__menu li {
display: inline-block;
}
.navbar__menu .menu__link {
display: inline-block;
padding: 7px;
font-weight: bold;
text-decoration: none;
color: #fff;
}
.navbar__menu .menu__link:hover {
background: #333;
color: #fff;
transition: ease 0.3s all;
}
<link href="https://fonts.googleapis.com/css?family=Fira+Sans:900|Merriweather&display=swap" rel="stylesheet">
<!-- HTML Follows BEM naming conventions
IDs are only used for sections to connect menu achors to sections -->
<header class="page__header">
<nav class="navbar__menu">
<!-- Navigation starts as empty UL that will be populated with JS -->
<ul id="navbar__list"></ul>
<div class="hamburger">
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
</div>
</nav>
</header>
In the solution below I just focused on creating <a> elements dynamically and applying the .active class style by firing their click events. There are undefined behaviors in the solution you developed:
You tried to use the sections variable in many places even though the <section> element is not defined.
The local variable s used in the for loop is not defined using the let or var keywords.
You must add <a> elements to <li> elements and <li> elements as child nodes to <ul> for its current style to be applicable.
The page height must be greater than 100% for the scroll event to be triggered.
To capture the click events of dynamically created elements, you need a more specialized technique than the classical method.
const Menu = document.getElementById('navbar__list');
const sections = document.querySelectorAll('section');
const menuLink = document.querySelectorAll(".menu__link");
/* The structure you are using does not allow the creation of <a> elements because the <section> element is not defined. */
NavBuilder = (counter) => {
for (let s = 1; s <= counter ; s++) {
let liElement = document.createElement('li');
let aElement = document.createElement('a');
let textNode = document.createTextNode(s);
aElement.className = "menu__link";
aElement.setAttribute("href", "#");
aElement.appendChild(textNode);
aElement.setAttribute("id", `${s}`);
liElement.appendChild(aElement);
Menu.appendChild(liElement);
}
}
/* I used jQuery to catch "click" events as the <a> elements are created dynamically. */
$(document).on('click', '.menu__link', function() {
console.clear();
console.log(this);
$('.menu__link').removeClass("active");
$(this).addClass("active");
});
/* The <a> elements are created when the page loads. */
window.addEventListener('load', function(e) {
NavBuilder(10);
});
.navbar__menu ul {
padding: 2px;
padding-left: 0;
margin: 0;
text-align: left;
background-color: gray;
}
.active {
color: red !important;
}
.navbar__menu li {
display: inline-block;
}
.navbar__menu .menu__link {
display: inline-block;
padding: 7px;
font-weight: bold;
text-decoration: none;
color: #fff;
}
.navbar__menu .menu__link:hover {
background: #333;
color: #fff;
transition: ease 0.3s all;
}
#media only screen and (max-width: 768px) {
.navbar__list {
position: fixed;
left: -100%;
top: 5rem;
flex-direction: column;
background-color: #fff;
width: 100%;
border-radius: 10px;
text-align: center;
transition: 0.3s;
box-shadow: 0 10px 27px rgba(0, 0, 0, 0.05);
}
.navbar__list.active {
left: 0;
}
.hamburger {
display: block;
cursor: pointer;
}
}
<link href="https://fonts.googleapis.com/css?family=Fira+Sans:900|Merriweather&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header class="page__header">
<nav class="navbar__menu">
<ul id="navbar__list">
<!--
<li><a class="menu__link" href="#">First</a></li>
<li><a class="menu__link" href="#">Second</a></li>
<li><a class="menu__link" href="#">Thirth</a></li>
-->
</ul>
<div class="hamburger">
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
</div>
</nav>
</header>
This question already has answers here:
setting the float value from Javascript
(2 answers)
Closed 4 years ago.
I'm having problems changing the float styling of a list tag using javascript. I am making a website and trying to make it responsive so that when the screen size is below 600px, there is a hamburger icon that can be pressed and the navigation bar appears, however I have set the float to left in the css code so that when the window is above 600px the menu stays horizontal. I am now trying to change it so that when the hamburger is pressed and the menu appears, each list element appears below each other, rather than next to each other.
This is my div for the navigation bar:
count = 1;
function clickHamburger() {
var navigation = document.getElementById('navigation');
var li = document.getElementsByTagName('li');
if (count % 2 != 0) {
navigation.style.display = 'block';
count++;
} else if (count % 2 == 0) {
navigation.style.display = 'none';
li.style.styleFloat = 'none';
count++;
}
}
#navigation {
width: 100%;
background-color: rgb(53, 53, 53);
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
margin-bottom: -4px;
background-color: rgb(53, 53, 53);
display: inline-block;
}
li {
float: left;
}
li a {
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
li a:hover {
background-color: #111;
}
.active {
background-color: rgb(106, 106, 241);
}
#media only screen and (max-width: 600px) {
#navigation {
display: none;
}
#hamburger {
display: block;
}
}
#media only screen and (min-width: 599px) {
#navigation {
display: block!important;
}
}
<div id='hamburger'><img id=imgham src="hamburger.png" onclick='clickHamburger();' /></div>
<div id='navigation'>
<ul>
<li>Home</li>
<li>XML Page</li>
<li>Register</li>
<li>Slideshow</li>
<li>Report</li>
</ul>
</div>
Thanks in advance for any help.
getElementsByTagName returns an HtmlCollection of all your li elements which are 5 here. So you need to loop through them and set the style. You are also setting float to none where the menu is getting closed. I think you want to move it to the other if block where the navigation is set to display. The correct property name is cssFloat. styleFloat is the property name in IE 8 and lower.
count=1;
function clickHamburger () {
var navigation = document.getElementById('navigation');
var liElems = document.getElementsByTagName('li');
if (count % 2 != 0) {
navigation.style.display = 'block';
for (var i = 0; i < liElems.length; i++) {
liElems[i].style.cssFloat = 'none';
}
count++;
} else if (count % 2 == 0) {
navigation.style.display = 'none';
count++;
}
}
Last but not least the recommended method to handle styles using javascript is by adding and removing classes. For example:
var div = document.getElementById('navigation');
setTimeout(() => div.classList.add('red'), 1000);
setTimeout(() => div.classList.remove('blue'), 2000);
.red {
background: red;
}
.blue {
border: 10px solid blue;
}
<div id="navigation" class="blue">DIV</div>
You can add and remove classes on your navigation element and control the style of children using css.
I am using the Bourbon Refill navigation menu, and want to modify it so when a link is clicked on in small mode the menu slides back up. At the moment the menu drops down, but when a menu item is clicked the menu stays dropped down. As I am using scroll-on-page with a fixed top menu this means a lot of the content is hidden behind the menu.
Here is the code on Codepen:
http://codepen.io/mikehdesign/pen/LVjbPv/
My existing code is below:
HTML
<header class="navigation" role="banner">
<div class="navigation-wrapper">
<a href="javascript:void(0)" class="logo">
<img src="https://raw.githubusercontent.com/thoughtbot/refills/master/source/images/placeholder_logo_1_dark.png" alt="Logo Image">
</a>
Menu
<nav role="navigation">
<ul id="js-navigation-menu" class="navigation-menu show">
<li class="nav-link">About Us</li>
<li class="nav-link">Contact</li>
<li class="nav-link">Testimonials</li>
<li class="nav-link">Sign up</li>
</ul>
</nav>
SCSS
.navigation {
$large-screen: em(860) !default;
$large-screen: $large-screen;
// Mobile view
.navigation-menu-button {
display: block;
float: right;
margin: 0;
padding-top: 0.5em;
#include media ($large-screen) {
display: none;
}
}
// Nav menu
.navigation-wrapper {
#include clearfix;
position: relative;
}
.logo {
float: left;
img {
max-height: 2em;
padding-right: 1em;
}
}
nav {
float: none;
#include media ($large-screen) {
float: left;
line-height: 1.5em;
padding-top: 0.3em;
}
}
ul.navigation-menu {
clear: both;
display: none;
margin: 0 auto;
overflow: visible;
padding: 0;
width: 100%;
#include media ($large-screen) {
display: block;
margin: 0;
padding: 0;
}
&.show {
display: block;
}
}
// Nav items
ul li.nav-link {
display: block;
text-align: right;
width: 100%;
#include media ($large-screen) {
background: transparent;
display: inline;
text-decoration: none;
width: auto;
}
}
li.nav-link a {
display: inline-block;
#include media ($large-screen) {
padding-right: 1em;
}
}
}
JS
$(document).ready(function() {
var menuToggle = $('#js-mobile-menu').unbind();
$('#js-navigation-menu').removeClass("show");
menuToggle.on('click', function(e) {
e.preventDefault();
$('#js-navigation-menu').slideToggle(function(){
if($('#js-navigation-menu').is(':hidden')) {
$('#js-navigation-menu').removeAttr('style');
}
});
});
});
Help greatly appreciated
Mike
Check out the following demo tested working in small and large version as your expectation.
EDIT 2
Updated toggling for small version as per your requirement.
Codepen
jQuery
function smallVersion() {
$("#js-navigation-menu a").on('click', function(e) {
$('#js-navigation-menu').slideToggle(function() {
if ($('#js-navigation-menu').is(':hidden')) {
$('#js-navigation-menu').removeAttr('style');
}
});
});
}
function dothis(){
var ww = $(window).width();
var emToPx = 53.75 * parseFloat($("html").css("font-size"));
if( ww < emToPx ) {
smallVersion();
}
}
$(document).ready(function() {
var menuToggle = $('#js-mobile-menu').unbind();
$('#js-navigation-menu').removeClass("show");
menuToggle.on('click', function(e) {
e.preventDefault();
$('#js-navigation-menu').slideToggle(function(){
if($('#js-navigation-menu').is(':hidden')) {
$('#js-navigation-menu').removeAttr('style');
}
});
});
dothis();
});
You could try...
$('header.navigation').on('click',function(){
$('header.navigation ul.submenu').css('display','none');
})
Check following code, hope it helps.
I have used matchmedia to check screen resolution. IE 10 and above supports it. You can use matchmedia polyfill https://github.com/paulirish/matchMedia.js/ for IE9 and below.
"min-width: 53.75em" is from Refills css after this point it changes to mobile navigation.
$('li.nav-link').on('click', function(){
if(!window.matchMedia("(min-width: 53.75em)").matches) {
menuToggle.trigger('click');
}
})
http://codepen.io/praveenvijayan/pen/YXrbKB
So I sorted this by detecting whether the menu button was visible, and then using that as the toggle in the JQuery:
$(document).ready(function() {
var menuToggle = $('#js-mobile-menu').unbind();
$('#js-navigation-menu').removeClass("show");
$('li.nav-link').on('click', function(){
if($(".navigation-menu-button").is(":visible") ) {
menuToggle.trigger('click');
}
});
menuToggle.on('click', function(e) {
e.preventDefault();
$('#js-navigation-menu').slideToggle(function(){
if($('#js-navigation-menu').is(':hidden')) {
$('#js-navigation-menu').removeAttr('style');
}
});
});
});
I have a LOGO on top left and a search bar on top right side of the page. I have a position:fixed navigation bar below to that LOGO and search bar and it act as fixed once the LOGO part is scrolled down.
Now the problem is when i scrolled down the logo part, search bar and one more element should come in to the visible mode in navigation bar.
Here is the Fiddle
please help me out to do this, have searched a lot but this drained my day.
window.onscroll = changePos;function changePos() {
var header = document.getElementById("header");
if (window.pageYOffset > 70) {
header.style.position = "fixed";
header.style.top = "0";
} else {
header.style.position = "";
header.style.top = "";
}}
You can try this:
First add a class to hide your elemnts:
<li class="hiden"> Logo</li>
<li class="hiden"> Search</li>
.wrapper #nav li.hiden {
display:none;
}
Then add to your function show() and hide() Jquery methods for that class:
function changePos() {
var header = $('#header'),
sT = $(window).scrollTop();
if (sT > 70) {
header.css({'position':'fixed','top':'0'});
$('.hiden').show();
} else {
header.css({'position':'relative','top':' '});
$('.hiden').hide();
}
The demo http://jsfiddle.net/v97qg/8/
I'd put the Logo and Search into the header and let them be positioned absolute/relative as long as the header isn't fixed. Which means I wouldn't fix it directly with JS but give the header a CSS class which has the fixed property.
I wrote completely new stuff because I restructured the HTML a little bit, because I think it's not necessary to write redundant HTML. A jsfiddle is at the end of the post.
HTML:
<div id="top-space"></div>
<div id="navigation">
<span id="logo">Logo</span>
<span id="search">Search</span>
Link 1
Link 2
Link 3
Link 4
</div>
<div id="content">...</div>
JS is just like your function but with a className property instead:
window.onscroll = changePos;
function changePos () {
var header = document.getElementById("navigation");
if (window.pageYOffset > 70) {
header.className = 'fixed';
} else {
header.className = '';
}
}
And CSS stuff:
html, body { margin: 0; padding: 0; }
body { font-family: sans-serif; }
#top-space {
height: 70px;
}
#navigation {
top: 0;
width: 100%;
position: static;
height: 40px;
line-height: 40px;
vertical-align: middle;
background: black;
}
#navigation.fixed {
position: fixed;
}
#navigation a {
display: inline-block;
text-decoration: none;
color: white;
padding: 0 1em;
}
#logo {
position: absolute;
float: left;
}
#search {
position: relative;
float: right;
}
#domain-name, #search {
margin-top: -70px;
}
#navigation.fixed #domain-name,
#navigation.fixed #search {
position: static;
color: white;
margin-top: 0;
}
Or just look it up in the jsfiddle.
Do you mean something like this?
http://jsfiddle.net/cugN7/3/
Goal:
When you are entering the address calculation or project.html, one of the main element in the menu should be marked with a background color based on the webpage you are entering. For instance, if you are entering calculation.html the selection named Calculation (from the menu) should be selected by having a different background color compare to others.
Problem:
I don't know how to make a mark by having a background color once you
have clicked the link. I would like the code to be written in jQuery.
If possible, it would be great to add "id" in the element "a href" to change the background color.
The value "Project" and "calculation" from jQuery is the value of element title from the html code.
HTML:
<div id="nav-menu">
<ul id="kthh">
<li>Kalkylering</li>
<li>Projekt</li>
</ul>
</div>
Javascript:
$(document).ready(function()
{
var data = $('title');
if(data[0].textContent == "Project")
{
$('#kthh').closest('li').next('li').find('a').addClass("asdd");
}
if(data[0].textContent == "calculation")
{
//$('title').html('someHTML');
}
}); // ready
CSS:
/* Menu for display */
#nav-menu ul
{
list-style: none;
padding: 0;
margin: 0;
}
#nav-menu li
{
float: right;
}
#nav-menu li a
{
height: 70px;
line-height: 110px;
float: left;
padding-left: 13px;
padding-right: 13px;
display: block;
color: #FFFFFF;
text-decoration: none;
text-align: center;
font-family: Verdana;
font-weight:bold;
}
#nav-menu li a:hover { background: #AA1133;}
#nav-menu li.last-child { padding-right: 50px;}
.asdd
{
background: #AA1133;
}
I think you should not use textcontentbut text:
$(document).ready(function()
{
var data = $('title');
if(data[0].text () == "Project")
{
$('#myFirstButton').addClass("asdd");
}
if(data[0].text() == "calculation")
{
//...
}
});
You can simplify your life by adding an Id to all your button also:
<div id="nav-menu">
<ul id="kthh">
<li><a id="myFirstButton" href="calculation.html">Kalkylering</a></li>
<li><a id="mySecondButton" href="project.html">Projekt</a></li>
</ul>
</div>