Sticky header jQuery addClass not working - javascript

I am trying to create sticky header but when I am scrolling down jQuery addClass function is not working I have also tried with $(this) but it is also not working. I am trying to add another class while scrolling but it is not working. I want to change the background color of the header
this is my HTML code
$(document).ready(function() {
$(window).scroll(function() {
var scroll = $(window).scrollTop();
var objectSelect = $(".myNavigation");
var objectPosition = objectSelect.offset().top;
if (scroll > objectPosition) {
$(this).addClass("active");
} else {
$(this).removeClass("active");
}
});
});
.active {
background: #147cc4 !important;
color: #fff !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="navbar navbar-expand-md fixed-top navbar-dark mb-4 myNavigation">
<div class="container">
<div class="col-md-2">
<ul class="navbar-nav mr-auto">
<form class="form-inline navbar-form" role="search">
<div class="search">
<span class="fa fa-search"></span>
<input type="text" class="form-control" placeholder="Search">
</div>
</form>
</ul>
</div>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="logoFont">Hifzil</a>
</li>
</ul>
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link">Donate</a>
</li>
<li class="nav-item">
<a class="nav-link">Login</a>
</li>
<li class="nav-item">
<a class="nav-link">Sign In</a>
</li>
</ul>
</div>
</div>
</nav>
And this is the css class in which i have changed the background colors

Problem:- In your case $(this) refers to window not .myNavigation.
Solution :-
$(this).addClass("active");
$(this).removeClass("active");
Need to be:-
objectSelect.addClass("active");
objectSelect.removeClass("active");
Working snippet:- https://jsfiddle.net/7ko4k75t/

The conditional statement behaves as expected, although consider using the .addClass() method with the variable objectSelect - which has already defined the element that will require the class change (.myNavigation).
$(this), in this case, is being used incorrectly, in regards to the scope, this refers to the window defined in the selector range of the .scroll() method.
Code Snippet Demonstration:
Note: console logging added to demonstrate when state changes occur
$(document).ready(function() {
$(window).scroll(function() {
var scroll = $(window).scrollTop();
var objectSelect = $(".myNavigation");
var objectPosition = objectSelect.offset().top;
if (scroll > objectPosition) {
$(objectSelect).addClass("active");
console.log('this:',$(objectSelect).attr('class'));
} else {
$(objectSelect).removeClass("active");
console.log('this:',$(objectSelect).attr('class'));
}
});
});
.active {
background: #147cc4 !important;
color: #fff !important;
}
html {
min-height: 1000px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="navbar navbar-expand-md fixed-top navbar-dark mb-4 myNavigation">
<div class="container">
<div class="col-md-2">
<ul class="navbar-nav mr-auto">
<form class="form-inline navbar-form" role="search">
<div class="search">
<span class="fa fa-search"></span>
<input type="text" class="form-control" placeholder="Search">
</div>
</form>
</ul>
</div>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="logoFont">Hifzil</a>
</li>
</ul>
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link">Donate</a>
</li>
<li class="nav-item">
<a class="nav-link">Login</a>
</li>
<li class="nav-item">
<a class="nav-link">Sign In</a>
</li>
</ul>
</div>
</div>
</nav>

Simple solution on pure JS:
var
head = document.getElementsByClassName('myNavigation')[0];
function stickyHeader() {
if (window.pageYOffset > 150) {
head.classList.add('active');
}
else if (window.pageYOffset <= 150) {
head.classList.remove('active');
}
}
window.addEventListener('scroll', function () {
stickyHeader();
});

Related

How can I change dropdown menu active background color with Bootstrap 4?

How do I change the background color of this menu only when expanded?
When inactive I want the background as shown, however, when the menu is active I'd like the color to change to a light grey. I can't work out how to do this without changing the whole background for both states.
Here is my code:
<nav
class="navbar navbar-expand-xl navbar-light fixed-top wrap pt-3"
id="mainNav"
>
<button
class="hamburger hamburger--squeeze"
type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="hamburger-box">
<span class="hamburger-inner"></span>
</span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-auto pt-2">
<li class="nav-item active">
<a class="nav-link" href="#"
>Illustration <span class="sr-only">(current)</span></a
>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Graphic Design</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact</a>
</li>
</ul>
</div>
</nav>
I already have this scroll function for all screens:
window.addEventListener('scroll', function (event) {
event.preventDefault();
if (window.scrollY <= 50) {
nav.style.backgroundColor = 'transparent';
} else {
nav.style.backgroundColor = '#fff';
nav.style.opacity = '0.9';
nav.style.transition = '0.4s ease';
}
If you are using this css plugin you can remove the scroll event and use a click event handler:
document.querySelectorAll(".hamburger").forEach(function(hamburger) {
hamburger.addEventListener("click", function() {
var nav = document.querySelector('#mainNav');
if (this.classList.contains('is-active') == false) {
nav.style.backgroundColor = 'red';
nav.style.opacity = '0.9';
nav.style.transition = '0.4s ease';
} else {
nav.style.backgroundColor = 'transparent';
}
this.classList.toggle("is-active");
}, false);
});
The snippet:
document.querySelectorAll(".hamburger").forEach(function(hamburger) {
hamburger.addEventListener("click", function() {
var nav = document.querySelector('#mainNav');
if (this.classList.contains('is-active') == false) {
nav.style.backgroundColor = 'red';
nav.style.opacity = '0.9';
nav.style.transition = '0.4s ease';
} else {
nav.style.backgroundColor = 'transparent';
}
this.classList.toggle("is-active");
}, false);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jonsuh/hamburgers#master/dist/hamburgers.min.css">
<nav class="navbar navbar-expand-xl navbar-light fixed-top wrap pt-3" id="mainNav">
<button class="hamburger hamburger--squeeze" type="button" data-toggle="collapse"
data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span class="hamburger-box">
<span class="hamburger-inner"></span>
</span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-auto pt-2">
<li class="nav-item active">
<a class="nav-link" href="#">Illustration <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Graphic Design</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact</a>
</li>
</ul>
</div>
</nav>
Try to update the default css for toggle button and styling active by this css tag:
[aria-expanded="true"] {
/* your custom style here */
}

how to change color of navbar when scrolling to bottom?

I have 2 probelems.
Problem-1: I am trying changing navbar background color when scrolling to bottom. I am trying to add the class but it couldn't override the bootstrap !important attribute. but I have override it using this line:
nav.scrolled {
background-color: #e8e4e1 !important;
box-shadow: 2px 10px 4px var(--section-bg-light);
}
problem-2: how to change navbar background with javascript while scrolling to the bottom of the page, footer of the page?
let navbar = document.querySelector('.navbar');
let section = document.querySelectorAll('section');
section.addEventListener('mouseover', addIt);
function addIt() {
navbar.classList.remove('bg-transparent');
navbar.classList.add('bg-dark');
}
nav.bg-dark {
background-color: #e8e4e1 !important;
}
<nav class="navbar navbar-expand-lg navbar-light bg-transparent fixed-top">
<div class="container-fluid">
<a class="navbar-brand" href="#"><img src="./img/logo-min.png" alt="JN-Fashion-Zone"></a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item home">
<a class="nav-link" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Products</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Services</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contacts</a>
</li>
</ul>
</div>
</div>
</nav>
Please check out How to override !important?
You need to use high specificity to override the !important rule.
Try adding more levels to your selector.
var nav = document.querySelector('nav');
window.addEventListener('scroll', function () {
if (window.pageYOffset > 100) {
nav.classList.add('bg-info', 'shadow');
} else {
nav.classList.remove('bg-info', 'shadow');
}
});

Bootstrap 4 navbar - collapse on nav-link click in vanilla JS

I am trying to make the Bootstrap 4 navbar only use vanilla js vs any jQuery. So far I've been able to get the toggler to trigger the nav to collapse and close on mobile. What I am now trying to figure out is how to make the navbar collapse when you click on a "nav-link"
Here is my HTML for the nav:
<nav class="navbar navbar-expand-lg navbar-light bg-light shadow-lg p-3 mb-5 bg-white fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Start Bootstrap</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive"
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item" >
<a class="nav-link" href="#about">About Us</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Browse Menu</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#visit">Contact</a>
</li>
</ul>
</div>
</div>
And my JS for the collapsing
(function () {
"use strict";
document.querySelectorAll("button.navbar-toggler")[0].addEventListener("click", function (event) {
var target = this.getAttribute("data-target");
var subbar = document.querySelectorAll(target)[0];
subbar.className = (subbar.className + " show").replace(/ show show/, "");
});
})();
But how do I make it so when a user clicks a <a class="nav-link" href="#"></a> it'll also collapse the navbar?
Thanks!
Since you are using custom code, it's unnecessary to have the target (data-target="#navbarResponsive") on the html. So we can rewrite the click handler to handle both elements, the toggler and the links. To toggle a class just use the method toggle on classList.
document.addEventListener("click", function(event) {
if (event.target.classList.contains("navbar-toggler-icon")) {
document.getElementById("navbarResponsive").classList.toggle("show");
} else if (event.target.classList.contains("nav-link")) {
document.getElementById("navbarResponsive").classList.remove("show");
}
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<nav class="navbar navbar-expand-lg navbar-light bg-light shadow-lg p-3 mb-5 bg-white fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Start Bootstrap</a>
<button class="navbar-toggler" type="button" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item"><a class="nav-link" href="#about">About Us</a></li>
<li class="nav-item"><a class="nav-link" href="#">Browse Menu</a> </li>
<li class="nav-item"> <a class="nav-link" href="#visit">Contact</a> </li>
</ul>
</div>
</div>
</nav>
A possible solution for your question is to find all the .nav-links and add a click listener to remove the show class from the class list.
Also, you could simplify a bit your code using Element.classList.toggle(), something like:
(function() {
let subbar = document.getElementById("navbarResponsive");
document
.querySelectorAll("button.navbar-toggler")[0]
.addEventListener("click", function(event) {
subbar.classList.toggle("show");
});
for (let navItem of document.querySelectorAll("a.nav-link")) {
navItem.addEventListener("click", function(event) {
subbar.classList.remove("show");
});
}
})();
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<nav class="navbar navbar-expand-lg navbar-light bg-light shadow-lg p-3 mb-5 bg-white fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Start Bootstrap</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="#about">About Us</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Browse Menu</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#visit">Contact</a>
</li>
</ul>
</div>
</div>
</nav>

Mobile menu doesn't collapse when a menu item is clicked

I'm having problem with a template where mobile menu doesn't collapse when a menu item is clicked. Tried to solve it adding extra class, extra ID's but persist. It only closes/hide when clicking again on hamburger icon. And this is particularly annoying...
The navbar html code is:
<!-- Fixed navbar -->
<div class="navbar navbar-smak navbar-fixed-top" id="navbar" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"><i class="fa fa-bars"></i></a>
<h1><a class="navbar-brand animate" href="#home">TEST SITE</a></h1>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right animate">
<li><a class="btn-navbar" href="#home">Home</a></li>
<li>Blog</li>
<li>Contacto</li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</div>
This is the dummy html file I'm working on, feel free to download and check it: https://aleare.com.ar/testing3/index2tst.html
This is the function that handle the collapsing menu:
$('a[href*=#]').each(function () {
if (filterPath(location.pathname) == filterPath(this.pathname) && location.hostname == this.hostname && this.hash.replace(/#/, '')) {
var $targetId = $(this.hash),
$targetAnchor = $('[name=' + this.hash.slice(1) + ']');
var $target = $targetId.length ? $targetId : $targetAnchor.length ? $targetAnchor : false;
if ($target) {
$(this).click(function () {
//Hack collapse top navigation after clicking
topMenu.parent().attr('style', 'height:0px').removeClass('in'); //Close navigation
$('.navbar .btn-navbar').addClass('collapsed');
var targetOffset = $target.offset().top - 52;
$('html, body').animate({
scrollTop: targetOffset
}, 800);
return false;
});
}
}
});
Does someone know why it's failing?
You must have a little more markup, e.g. topMenu and filterPath.
However, if I understand your question correctly it sounds like you want the mobile menu to toggle closed when you select an item from the mobile menu. I am not using your code, but borrowed a navbar from the Bootstrap examples and added a little extra code to just close the menu when you click on a link in the menu. I would not be surprised if there is something like that built into bootstrap, which I assume you are using ? If not, you can probably do something similar by triggering a click on the hamburger when "appropriate":
$('.nav-link:not(.dropdown-toggle), .dropdown-item').each(function () {
$(this).on("click", function(e) {
$(".navbar-toggler").trigger("click");
alert($(this).attr("href"));
});
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha256-YLGeXaapI0/5IgZopewRJcFXomhRMlYYjugPLSyNjTY=" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" integrity="sha256-UzFD2WYH2U1dQpKDjjZK72VtPeWP50NoJjd26rnAdUI=" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha256-CjSoeELFOcH0/uxWu6mC/Vlrc1AARqbm/jiiImDGV3s=" crossorigin="anonymous"></script>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#home">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#link">Link</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#action">Action</a>
<a class="dropdown-item" href="#another">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#soemthingelse">Something else here</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Disabled</a>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
<div class="col">
2 of 3
</div>
<div class="col">
3 of 3
</div>

Making my navbar form search field full width

I have this navbar below and I'd like to make the search field in the form full width, so it expands as much of the navbar as possible without pushing anything else out of the way.
How would I do this?
I've tried a couple of different things like setting the width of different elements but nothing seems to work.
<nav class="navbar navbar-expand-md navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" [routerLink]="['/home']">Web App</a>
<form class="form-inline">
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
</form>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#test" aria-expanded="false"> <span class="navbar-toggler-icon"></span> </button>
<div class="collapse navbar-collapse" id="test">
<ul *ngIf="!loggedIn()" class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" [routerLink]="['/register']">Register</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['/login']">Login</a>
</li>
</ul>
</div>
</div>
</nav>
This can be achieved with display:flex; and wrapping the relevant elements in divs. I set the first and second div to flex-shrink:1;, which means they shrink to the content of the div. Then I have added flex-grow: 1;to the second div so it fills the remaining space.
I also added width:100%; to the input field.
.flex {
display:flex;
}
.flex > div {
padding:0 5px;
flex-shrink:1;
}
.flex > div:nth-child(2) {
flex-grow: 1;
}
input {
width:100%;
}
.collapse {
display:none;
}
<nav class="navbar navbar-expand-md navbar-dark bg-primary">
<div class="container flex">
<div>
<a class="navbar-brand" [routerLink]="['/home']">Web App</a>
</div>
<div>
<form class="form-inline">
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
</form>
</div>
<div>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#test" aria-expanded="false"> <span class="navbar-toggler-icon">Menu</span> </button>
<div class="collapse navbar-collapse" id="test">
<ul *ngIf="!loggedIn()" class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" [routerLink]="['/register']">Register</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['/login']">Login</a>
</li>
</ul>
</div>
</div>
</div>
</nav>
Add with and float on the below element:
<ul class="navbar-nav mr-auto">
CSS:
width: 100px;
float: right;
The float you set does not work as the width of the element is 100%. You can also set text-align: center but depends how you want your text starts.
To align it properly now, use margin-right and margin-left to display it right where you want.
Edit:
To have full width search bar:
form, input {
width: 100%;
}
Edit 2:
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<nav class="navbar navbar-expand-md navbar-dark bg-primary">
<div class="container">
<div class="row w-100">
<a class="col-2 navbar-brand" [routerLink]="['/home']" style="max-width:100px">Web App</a>
<form class="col form-inline">
<input class="form-control mr-sm-2 w-100" type="search" placeholder="Search" aria-label="Search">
</form>
<button class="col-1 navbar-toggler" type="button" data-toggle="collapse" data-target="#test" aria-expanded="false" style="min-width:50px">
<span class="navbar-toggler-icon"></span>
</button>
<div class="col-1 collapse navbar-collapse" id="test">
<ul *ngIf="!loggedIn()" class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" [routerLink]="['/register']">Register</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['/login']">Login</a>
</li>
</ul>
</div>
</div>
</div>
</nav>

Categories