Flicker in nav bar styling when scrolling - javascript

I'm having a flickering issue with my bottom-border (nav link) when I scroll within a certain section. I suppose it's not really a flicker, but a transition that's being resetted every time I scroll within that section. For example (refer to source below), if my window is currently in a section and I scroll little by little, the border-bottom of my active nav link will flicker. In addition, if I hold onto the scroll bar and scroll down, the border-bottom disappears.
I'd like for it to:
1) Not flicker when scrolling.
2) When scrolling on the page with the scroll bar, keep the border-bottom present.
http://jsfiddle.net/binhxn89/zzmbex55/16/
HTML:
<body>
<div class="navbar">
<div class="container cf">
<ul>
<li>Home</li>
<li>Link1</li>
<li>link2</li>
<li>link3</li>
<li>link4</li>
</ul>
</div>
</div>
<section id="welcome" class="welcome"></section>
<section id="link1" class="link1"></section>
<section id="link2" class="link2"></section>
<section id="link3" class="link3"></section>
<section id="link4" class="link4"></section>
</body>
CSS:
body, html {
height: 100%;
color: #f3f3f3;
font-family: Arial, sans-serif;
}
body {
margin: 0;
overflow-x: hidden;
}
.container {
width: 90%;
margin: 0 auto;
}
.navbar {
background: rgba(0,0,0, 0.9);
width: 100%;
position: fixed;
z-index: 20;
}
.navbar ul li {
list-style: none;
float: left;
}
.navbar ul li a {
color: #fff;
display: block;
font-size: 14px;
margin: 0 10px;
padding: 20px 5px;
text-decoration: none;
-webkit-transition: all 0.2s ease-in-out;
-moz-transition: all 0.2s ease-in-out;
transition: all 0.2s ease-in-out;
}
.navbar ul li a:hover,
.navbar ul li a.active {
margin-top: -3px;
font-weight: bold;
padding-bottom: 8px;
border-bottom: 2px solid #fff;
}
section {
height:100%;
z-index: 10;
position: relative;
}
.welcome {
background: #ebebeb;
}
.link1 {
background: #aaa;
}
.link2 {
background: #bbb;
}
.link3 {
background: #ccc;
}
.link4 {
background: #ddd;
}
JS:
$(document).ready(function() {
$(window).scroll(function () {
var y = $(this).scrollTop();
$('.link').each(function (event) {
if (y >= $($(this).attr('href')).offset().top - 10) {
$('.link').not(this).removeClass('active');
$(this).addClass('active');
}
});
});
$('a[href*=#]:not([href=#])').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
if (target.length) {
$('html,body').animate({
scrollTop: target.offset().top
}, 600);
return false;
}
}
});
})
If anyone could help or refer me to a particular source regarding this issue, that would be great. Thanks!

Please take a look here or take a look at the code below. First, I calculate the heigh of one element and get his position. After that I compare the part to the current position. So far, no flickering on Safari or Chrome, I hope this will fix it. It seams that your solution raised multiple events, if you look at the console.log(y); you will notice a lot of double values for part 2, 3, 4 and 5.
$(window).scroll(function() {
var y = $(this).scrollTop();
var sectionHeigth = $('section').height();
var part = Math.round((y / sectionHeigth));
$('.link').each(function(event) {
var position = $($(this).attr('href')).offset().top;
if ((part * sectionHeigth) != position) {
$(this).removeClass('active');
} else {
$(this).addClass('active');
}
});
});
Here is the update to your comment. I'll check if the current position is between the start and start + height position. That's all.
$(window).scroll(function() {
var y = $(this).scrollTop();
$('.link').each(function(event) {
var position = $($(this).attr('href')).offset().top;
var a = $($(this).attr('href')).height();
if (y >= position && y <= position + a) {
$(this).addClass('active');
} else {
$(this).removeClass('active');
}
});
});

Related

Adding class dynamically based on which element is being scrolled past

I have a nav which contains letters and sections which are associated to letters in the nav.
When a user scrolls to a section, I want to addClass active to that letter. For example:
User scrolls to section with the id of a, the anchor with the data-letter with a will be active.
Currently, on scroll, all my letters in the nav become active and this is because it's always thinking it's on section A.
Demo:
$(function() {
$(window).scroll(function() {
// step 1: get id of section
var visible_section = $('section:visible'), id = visible_section.attr('id');
console.log(id);
// step 2: add class where id and data-letter match
$("nav a").removeClass("active");
$("nav a[data-letter='"+id+"']").addClass("active");
});
});
.nav {
background: grey;
padding: 30px 15px;
position: fixed;
top: 0;
width: 100%;
}
.nav a {
padding: 0 15px;
text-decoration: none;
}
.nav a:hover {
background: black;
color: white;
}
.nav a.active {
background: black;
color: white;
}
.sections {
margin-top: 100px;
}
section {
padding: 200px 0;
color: red;
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
}
section:nth-child(odd) {
background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<main>
<nav class="nav">
A
B
C
D
</nav>
<div class="sections">
<section id="a">A</section>
<section id="b">B</section>
<section id="c">C</section>
<section id="d">D</section>
</div>
</main>
FYI: https://stackoverflow.com/a/5354536/4571790
function isVisible(elm) {
var rect = elm.getBoundingClientRect();
var viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
return !(rect.bottom < 0 || rect.top - viewHeight >= 0);
}
$(function() {
$(window).scroll(function() {
// step 1: get id of section
var visible_section = $('section:visible'), id="";
// this code will find which section is the first visible
$(".sections").find("section").each((i,a)=>id==""?(isVisible(a)?id=$(a).attr("id"):id):id);
$("#result").html(id +" is visible now");
//console.log(id);
// step 2: add class where id and data-letter match
$("nav a").removeClass("active");
$("nav a[data-letter='"+id+"']").addClass("active");
});
});
.nav {
background: grey;
padding: 30px 15px;
position: fixed;
top: 0;
width: 100%;
}
.nav a {
padding: 0 15px;
text-decoration: none;
}
.nav a:hover {
background: black;
color: white;
}
.nav a.active {
background: black;
color: white;
}
.sections {
margin-top: 100px;
}
section {
padding: 200px 0;
color: red;
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
}
section:nth-child(odd) {
background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<main>
<nav class="nav">
A
B
C
D
<span id="result"></span>
</nav>
<div class="sections">
<section id="a">A</section>
<section id="b">B</section>
<section id="c">C</section>
<section id="d">D</section>
</div>
</main>
You should differentiate the nav tabs by setting their data-letter as you described to a, b, c and d:
<nav class="nav">
A
B
C
D
</nav>
All your nav become active not because it always thinks it's on a, but because all data-letter are set to a.
You can change ratio from 0.1 to 1:
$(function () {
let ratio = 0.6; // From 0.1 to 1
$(window).scroll(function () {
let sections = $('.sections section');
let scrollTop = $(window).scrollTop();
let screen_height = $(window).height();
$.each(sections, function () {
let top = $(this).offset().top;
let calc = (top - scrollTop) / screen_height;
if (calc >= (ratio * -1) && calc <= ratio) {
let id = $(this).attr('id');
$("nav a").removeClass("active");
$("nav a[data-letter='" + id + "']").addClass("active");
//console.log(`${id} is Active`);
}
});
});
});
.nav {
background: grey;
padding: 30px 15px;
position: fixed;
top: 0;
width: 100%;
}
.nav a {
padding: 0 15px;
text-decoration: none;
}
.nav a:hover {
background: black;
color: white;
}
.nav a.active {
background: black;
color: white;
}
.sections {
margin-top: 100px;
}
section {
padding: 200px 0;
color: red;
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
}
section:nth-child(odd) {
background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<main>
<nav class="nav">
A
B
C
D
</nav>
<div class="sections">
<section id="a">A</section>
<section id="b">B</section>
<section id="c">C</section>
<section id="d">D</section>
</div>
</main>
Your confusion seems to stem from the fact that you have an inaccurate understanding of what :visible selector in jQuery selects. From documentation: "Elements are considered visible if they consume space in the document. Visible elements have a width or height that is greater than zero." By this definition, all of the sections are "visible".
To achieve your use case you need to calculate coordinates of individual sections and compare them with scroll position in the document. The following appears to do what you are looking for (try it out here):
$(function () {
$(window).scroll(function () {
// determine element that is fully in the viewport
const fullyVisibleSection = Array.from(document.querySelectorAll('section')).find((section) => {
const topY = section.offsetTop;
const bottomY = topY + section.offsetHeight;
return (topY >= window.scrollY) && (bottomY <= (window.scrollY + window.innerHeight));
});
// only update classes if the section is fully visible
if (fullyVisibleSection) {
$("nav a").removeClass("active");
// add class where id and data-letter match
$("nav a[data-letter='" + fullyVisibleSection.id + "']").addClass("active");
}
});
});

How to fix my header getting cut off on mobile browsers?

I need help with fixing my header I can not find the problem! At the beginning it looks fine but when you scroll down it cuts part of it off. But when you scroll back up it goes normal. I think it is with the hamburger menu because when you click on it, it increases the cut off. Here is the link to the website. https://perfectparadox8400.000webhostapp.com/ and here is a gif of what happens!
Link to the picture of what happens!
I only happens when you are on a phone. I used the inspector tools to test it and I did try it on a phone to.
Here is the header code.
<header id="headerrr" class="fixed-top lode">
<div class="container">
<div id="lode" class="logo float-center">
<!-- Uncomment below if you prefer to use an image logo -->
<!-- <h1 class="text-light"><span>NewBiz</span></h1> -->
<a href="#intro">
<img id="headerr" class="bigg" src="img/l.png" heigth="100%"><div id="lod" class="lod" style=display:inline-block;vertical-align:center> Perfect Paradox's 8400</div></a>
<div id="dlod" class="loder">
<div class="fixx">
<div class="float-center lodbar">Loding...
<div id="barr" class="persent"> </div>
</div>
</div>
</div>
</div>
<script>
var w = 5;
var foo = setInterval(function () {
if(w>109) {cancelInterval(foo)}
w = w + 6.25;
document.getElementById('barr').style.width = w + '%';
}, 1000);
</script>
<nav id="lood" class="lod main-nav float-right d-none d-lg-block header">
<ul>
<li class="drop-down"><a>Home</a>
<ul>
<li>About Us</li>
<li>Portfolio</li>
<li>Team</li>
</ul>
</li>
<li class="drop-down" ><a>FTC</a>
<ul>
<li>FTC Page</li>
<li>
FTC At Home
</li>
<li>About FTC</li>
</ul>
</li>
<li>FLL</li>
<li>Junior FLL</li>
<li class="drop-down"><a>More</a>
<ul>
<li>Old Website
</li>
<li>FLL</li>
<li>Junior FLL</li>
<li>More</li>
</ul>
</li>
<li>Contact Us</li>
</ul>
</nav><!-- .main-nav -->
</div>
</header><!-- #header -->
The css.
#-webkit-keyframes rotate {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
}
}
.lode {
height: 100% !important;
transition: all 0.5s;
}
.lod {
display: none !important;
transition: all 0.5s;
}
.bigg {
margin-left: 25% !important;
margin-right: 25% !important;
width: 50% !important;
-webkit-animation-name: rotate;
-webkit-animation-duration: 3s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
transition: all 0.5s;
}
.float-center {
margin-top: 8% !important;
transition: all 0.5s;
}
.loder {
width: 80%;
transition: all 0.5s;
}
.fixx {
position: relative;
}
.lodbar {
width: 125%;
transition: all 0.5s;
background-color: #afb0b3;
height: 0.5%;
}
.persent {
width: 0%;
transition: all 0.5s;
background-color: #5e068a;
position: absolute;
top: 0;
left: 0;
z-index: 0;
}
/*--------------------------------------------------------------
# Header
--------------------------------------------------------------*/
#headerrr {
height: 80px;
transition: all 0.5s;
z-index: 997;
transition: all 0.5s;
padding: 0px 0;
background: #fff;
box-shadow: 0px 0px 30px rgba(127, 137, 161, 0.3);
transition: all 0.5s;
}
.header {
height: 80px;
transition: all 0.5s;
z-index: 997;
padding: 20px 0;
background: transparent !important;
}
#headerrr.header-scrolledd {
height: 60px;
transition: all 0.5s;
}
#headerr.header-scrolleddd {
width: 76px;
transition: all 0.5s;
}
#headerr {
width: 100px;
transition: all 0.5s;
}
.header.header-scrolled,
.header.header-pages {
height: 60px;
padding: 10px 0;
transition: all 0.5s;
}
#headerrr .logo h1 {
font-size: 36px;
margin: 0;
padding: 0;
line-height: 1;
font-weight: 400;
letter-spacing: 3px;
text-transform: uppercase;
transition: all 0.5s;
}
#headerrr .logo h1 a {
margin: 7px 0;
transition: all 0.5s;
}
#headerrr .logo h1 a:hover {
color: #5e068a;
text-decoration: none;
transition: all 0.5s;
}
#headerrr .logo img{
padding: 0;
margin: 0px 0;
height: 100%;
transition: all 0.5s;
}
The javascript.
(function ($) {
"use strict";
// Preloader (if the #preloader div exists)
$(window).on('load', function () {
if ($('#preloader').length) {
$('#preloader').delay(100).fadeOut('slow', function () {
$(this).remove();
});
}
});
// Back to top button
$(window).scroll(function() {
if ($(this).scrollTop() > 100) {
$('.back-to-top').fadeIn('slow');
} else {
$('.back-to-top').fadeOut('slow');
}
});
$('.back-to-top').click(function(){
$('html, body').animate({scrollTop : 0},1500, 'easeInOutExpo');
return false;
});
// Initiate the wowjs animation library
new WOW().init();
// Header scroll class
$(window).scroll(function() {
if ($(this).scrollTop() > 100) {
$('.header').addClass('header-scrolled');
$('#headerrr').addClass('header-scrolledd');
$('#headerr').addClass('header-scrolleddd');
} else {
$('.header').removeClass('header-scrolled');
$('#headerrr').removeClass('header-scrolledd');
$('#headerr').removeClass('header-scrolleddd');
}
});
if ($(window).scrollTop() > 100) {
$('.header').addClass('header-scrolled');
$('#headerrr').addClass('header-scrolledd');
$('#headerr').addClass('header-scrolleddd');
}
// Smooth scroll for the navigation and links with .scrollto classes
$('.main-nav a, .mobile-nav a, .scrollto').on('click', function() {
if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) {
var target = $(this.hash);
if (target.length) {
var top_space = 0;
if ($('#headerrr').length) {
top_space = $('#headerrr').outerHeight();
if (! $('#headerrr').hasClass('header-scrolledd')) {
top_space = top_space - 0;
}
}
$('html, body').animate({
scrollTop: target.offset().top - top_space
}, 1500, 'easeInOutExpo');
if ($(this).parents('.main-nav, .mobile-nav').length) {
$('.main-nav .active, .mobile-nav .active').removeClass('active');
$(this).closest('li').addClass('active');
}
if ($('body').hasClass('mobile-nav-active')) {
$('body').removeClass('mobile-nav-active');
$('.mobile-nav-toggle i').toggleClass('fa-times fa-bars');
$('.mobile-nav-overly').fadeOut();
}
return false;
}
}
});
// Navigation active state on scroll
var nav_sections = $('section');
var main_nav = $('.main-nav, .mobile-nav');
var main_nav_height = $('#headerrr').outerHeight();
$(window).on('scroll', function () {
var cur_pos = $(this).scrollTop();
nav_sections.each(function() {
var top = $(this).offset().top - main_nav_height,
bottom = top + $(this).outerHeight();
if (cur_pos >= top && cur_pos <= bottom) {
main_nav.find('li').removeClass('active');
main_nav.find('a[href="#'+$(this).attr('id')+'"]').parent('li').addClass('active');
}
});
});
// jQuery counterUp (used in Whu Us section)
$('[data-toggle="counter-up"]').counterUp({
delay: 10,
time: 1000
});
// Porfolio isotope and filter
$(window).on('load', function () {
var portfolioIsotope = $('.portfolio-container').isotope({
itemSelector: '.portfolio-item'
});
$('#portfolio-flters li').on( 'click', function() {
$("#portfolio-flters li").removeClass('filter-active');
$(this).addClass('filter-active');
portfolioIsotope.isotope({ filter: $(this).data('filter') });
});
});
// Testimonials carousel (uses the Owl Carousel library)
$(".testimonials-carousel").owlCarousel({
autoplay: true,
dots: true,
loop: true,
items: 1,
delay: 100
});
})(jQuery);
These are the parts with the header involved!
Please help!
I tried removing the javascript but it did not help!
You adding the on scroll shrink effect to the header
There is two ways to solve this
removing header-scrolled css or change the height of header-scrolled to according to main height mentioned in headerrr css
#headerrr.header-scrolledd {
height: 60px;
transition: all 0.5s;
}
The main height of the header is 80px you adding the header-scrolledcss onscroll in javascript the header-scrolled height of is 66px so when you scroll down the screen get shrink so change the height of header-scrolled to 80px to avoid shrink
second way is to remove the javascript for header
// Header scroll class
$(window).scroll(function() {
if ($(this).scrollTop() > 100) {
$('.header').addClass('header-scrolled');
$('#headerrr').addClass('header-scrolledd');
$('#headerr').addClass('header-scrolleddd');
} else {
$('.header').removeClass('header-scrolled');
$('#headerrr').removeClass('header-scrolledd');
$('#headerr').removeClass('header-scrolleddd');
}
});
if ($(window).scrollTop() > 100) {
$('.header').addClass('header-scrolled');
$('#headerrr').addClass('header-scrolledd');
$('#headerr').addClass('header-scrolleddd');
}
remove this code block it will remove the onscroll function for header removig this will leads to your header will not shrink on scroll
you can choose any one way
my suggestion to remove both header-scrolled and javascript code
I added this: html, body {width: auto!important; overflow-x: hidden!important} and it fixed the problem.

solution for use button with HREF scrolling or modify <a> link to a button

i have 5 button i wanna use them to scroll to section
for the first i make button, i customize button with css , and after when i try to make a scroll , i got problem, dosent work
i try to use a link , the problem is setting button on css dont work very good , the text is on TOP left
i try to use now on css scroll slow with JS ? or HTML with #link
thanks
HTML ( many version of boutton i make for u ONLY FORT TESTING )
<section id="jour">
<div class="container20">
Dimanche
<button onclick="window.location.href='#Lundi'"class="btn1">Lundi</br><b>13</b></button>
<button onclick="window.location.href='#Mardi'"class="btn1">Mardi</br><b>12</b></button>
<button onclick="scrollTo.location.href='#Mercredi'"class="btn1">Mercredi</br><b>13</b></button>
<button onclick="scrollTo.location.href='#Jeudi'"class="btn1">Jeudi</br><b>14</b></button>
<button class="btn1">Dimanche</br><b>12</b></button>
</div>
</section>
CSS :
.container20 {
display: flex;
justify-content: center;
}
.btn1 {
display: block;
height: 80px;
width: 80px;
color : #262552;
font-family: "Montserrat", sans-serif;
font-weight: 900;
font-size: 12px;
letter-spacing: 0.6px;
padding: 1px 1px;
border-radius: 3px;
transition: 0.3s;
margin: 30px 1px ;
background: #9FEDD7;
border: 3px solid #f7ee6f;
}
#jour .btn1:hover {
background-color:#f7ee6f;
border: 2px solid #f7ee6f;
color : #262552 ;
}
// Cache selectors
var lastId,
topMenu = $("#top-menu"),
topMenuHeight = topMenu.outerHeight()+15,
// All list items
menuItems = topMenu.find("a"),
// Anchors corresponding to menu items
scrollItems = menuItems.map(function(){
var item = $($(this).attr("href"));
if (item.length) { return item; }
});
// Bind click handler to menu items
// so we can get a fancy scroll animation
menuItems.click(function(e){
var href = $(this).attr("href"),
offsetTop = href === "#" ? 0 : $(href).offset().top-topMenuHeight+1;
$('html, body').stop().animate({
scrollTop: offsetTop
}, 300);
e.preventDefault();
});
// Bind to scroll
$(window).scroll(function(){
// Get container scroll position
var fromTop = $(this).scrollTop()+topMenuHeight;
// Get id of current scroll item
var cur = scrollItems.map(function(){
if ($(this).offset().top < fromTop)
return this;
});
// Get the id of the current element
cur = cur[cur.length-1];
var id = cur && cur.length ? cur[0].id : "";
if (lastId !== id) {
lastId = id;
// Set/remove active class
menuItems
.parent().removeClass("active")
.end().filter("[href='#"+id+"']").parent().addClass("active");
}
});
body {
height: 6000px;
font-family: Helvetica, Arial;
}
#top-menu {
position: fixed;
z-index: 1;
background: white;
left: 0;
right: 0;
top: 0;
}
#top-menu li {
float: left;
}
#top-menu a {
display: block;
padding: 5px 25px 7px 25px;
width: 4em;
text-align: center;
-webkit-transition: .5s all ease-out;
-moz-transition: .5s all ease-out;
transition: .5s all ease-out;
border-top: 3px solid white;
color: #aaa;
text-decoration: none;
}
#top-menu a:hover {
color: #000;
}
#top-menu li.active a {
border-top: 3px solid #333;
color: #333;
}
#foo {
position: absolute;
top: 400px;
}
#bar {
position: absolute;
top: 800px;
}
#baz {
position: absolute;
top: 1200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<ul id="top-menu">
<li class="active">
Top
</li>
<li>
Foo
</li>
<li>
Bar
</li>
<li>
Baz
</li>
</ul>
<a id="foo">Foo</a>
<a id="bar">Bar</a>
<a id="baz">Baz</a>

Allowing for changes in element height during a scroll animation

Got a JS/JQuery issue I'm struggling to solve.
I'm building a simple one page site with a fixed header and anchor based scrolling navigation. When a user clicks a link the the scrollTop of the body is animated to the top of the relevant section. Included in this function is a calculation that subtracts the height of the header from the scroll distance to ensure the fixed header doesn't obscure the top of the section
The issue I'm having is because of a separate function that applies a class to the header if a user scrolls past a certain distance. This class causes a few properties to change and therefore the height of the header element changes.
This means that the value of $('header').outerHeight(); at the end of the scrolling animation is smaller than what it was when the animation began. This change means that the distance scrolled is wrong and the window ends up slightly too short of the desired location.
How do I allow for this change in value during the scrolling animation? Ideally I want everything to stay dynamic rather than specifying fixed heights/sizes. TIA.
$('a[href^="#"]').on("click", function() {
let headerHeight = $('header').outerHeight();
$('html, body').animate({
scrollTop: $($.attr(this, 'href')).offset().top - headerHeight
}, 500);
});
$(window).on('load resize scroll', function() {
if ($(window).scrollTop() >= 100 ) { // this refers to window
$('header').addClass('scroll');
} else {
$('header').removeClass('scroll');
}
});
body,html {
margin: 0;
padding: 0;
}
header {
padding: 30px 30px;
position:fixed;
left:0;
right: 0;
top: 0;
z-index:99;
transition: all .3s ease;
}
header h1 {
display:inline-block;
width:10%;
color: white;
}
header.scroll {
background: black;
padding: 15px 30px;
}
header nav {
display:inline-block;
width: 89%;
}
header nav ul {
margin: 0;
list-style: none;
text-align:right;
}
header nav ul li {
display:inline-block;
}
header nav ul li a {
color: white;
padding: 0 10px;
}
.hero {
height: 600px;
background: blue;
}
section h2 {
position: relative;
top: 50%;
transform: translateY(-50%);
margin: 0;
text-align: center;
color: white;
}
section {
height: 600px;
}
#one {
background: red;
}
#two {
background: green;
}
#three {
background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
<h1>Title</h1>
<nav>
<ul>
<li>Section 1 </li>
<li>Section 2 </li>
<li>Section 3 </li>
</ul>
</nav>
</header>
<section class="hero"><h2>Hero</h2></section>
<section id="one"><h2>Section 1</h2></section>
<section id="two"><h2>Section 2</h2></section>
<section id="three"><h2>Section 3</h2></section>
If you run the above snippet and click on the link for "Section 1" at the top of the page. You can see the distance scrolled is slightly too short and the bottom of the .hero element is still visible due to the change in height.
Try this, I'm subtracting 30 from header's height because in start padding was "30px 30px" and then it's going to be "15px 30px" means header height should be:
height = actualHeight - - ,
and this required when your header is expanded(means header does not have class scroll) so I added condition.
$('a[href^="#"]').on("click", function() {
let headerHeight = $('header').outerHeight();
if(!$('header').hasClass('scroll')) {
headerHeight -= 30; //The padding removed
}
$('html, body').animate({
scrollTop: $($.attr(this, 'href')).offset().top - headerHeight
}, 500);
});
$(window).on('load resize scroll', function() {
if ($(window).scrollTop() >= 100 ) { // this refers to window
$('header').addClass('scroll');
} else {
$('header').removeClass('scroll');
}
});
body,html {
margin: 0;
padding: 0;
}
header {
padding: 30px 30px;
position:fixed;
left:0;
right: 0;
top: 0;
z-index:99;
transition: all .3s ease;
}
header h1 {
display:inline-block;
width:10%;
color: white;
}
header.scroll {
background: black;
padding: 15px 30px;
}
header nav {
display:inline-block;
width: 89%;
}
header nav ul {
margin: 0;
list-style: none;
text-align:right;
}
header nav ul li {
display:inline-block;
}
header nav ul li a {
color: white;
padding: 0 10px;
}
.hero {
height: 600px;
background: blue;
}
section h2 {
position: relative;
top: 50%;
transform: translateY(-50%);
margin: 0;
text-align: center;
color: white;
}
section {
height: 600px;
}
#one {
background: red;
}
#two {
background: green;
}
#three {
background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
<h1>Title</h1>
<nav>
<ul>
<li>Section 1 </li>
<li>Section 2 </li>
<li>Section 3 </li>
</ul>
</nav>
</header>
<section class="hero"><h2>Hero</h2></section>
<section id="one"><h2>Section 1</h2></section>
<section id="two"><h2>Section 2</h2></section>
<section id="three"><h2>Section 3</h2></section>
Ended up solving this by adding a callback to my animation function. The callback checks if the height of the header has changed since the function was first called and if it has, then the scrollTop is increased by this amount.
$('a[href^="#"]').on("click", function() {
let headerHeightOne = $('header').outerHeight();
$('html, body').animate({
scrollTop: $($.attr(this, 'href')).offset().top - headerHeightOne
}, 500, function() {
let headerHeightTwo = $('header').outerHeight();
let difference = headerHeightOne - headerHeightTwo;
if (difference > 0 ) {
$('html,body').animate({
scrollTop: $(window).scrollTop() + difference
}, 100);
}
});
});

target .class:after:hover in jQuery

I need to target this :after in jQuery:
.a1 {
position: relative;
}
.a1:after {
content: '';
position: absolute;
width: 0;
height: 3px;
display: block;
margin-top: 5px;
right: 0;
background: #3f92c3;
transition: width .4s linear;
-webkit-transition: width .4s linear;
}
.a1:hover:after {
width: 100%;
left: 0;
background: #3f92c3;
}
The scroll code looks like this (example):
$(function() {
var header = $("#header");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 100) {
header.addClass("scrolled");
} else {}
});
});
HTML:
<li><a class="a1" href="#">Portfolio</a></li>
<li><a class="a1" href="#">Services</a></li>
<li><a class="a1" href="#">Contact</a></li>
I found this out after searching alot and it worked byt i don't know how the underline can keep the hover color after i mouseleave .a1 :
$('#menuwrapper').mouseenter(function() {
if ($('#pseudo').length) {
$('#pseudo').remove();
} else {
var css = '<style id="pseudo">.a1::after{background: red !important;}</style>';
document.head.insertAdjacentHTML('beforeEnd', css);
};
});
I tried mouseleave but it didn't work.
So i just want that if i scroll (that i know how it works) that the underline under the menu .a1 stay's black , because if i leave the underline hover it goes back to
.a1:after {
background: #3f92c3;
}
I want it to stay black.
pseudo elements like :before and :after are not the part of DOM because they are not real elements as called pseudo...so you can't target them using jQuery
As you are adding class scrolled on scroll, so better to use this class in css like
.scrolled .a1:after{
background: black;
}
$(function() {
var header = $("#header");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 100) {
header.addClass("scrolled");
} else {
header.removeClass("scrolled");
}
});
});
body {
margin-top: 150px;
font: 13px Verdana;
height: 500px
}
#header {
list-style: none;
padding: 0;
display: flex;
}
#header li {
margin: 0 10px;
}
.a1 {
position: relative;
font-weight: bold;
text-decoration: none;
}
.a1:after {
content: '';
position: absolute;
width: 0;
height: 3px;
display: block;
margin-top: 5px;
right: 0;
background: #3f92c3;
transition: width .4s linear;
-webkit-transition: width .4s linear;
}
.a1:hover:after {
width: 100%;
left: 0;
}
.scrolled .a1:after {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="header">
<li><a class="a1" href="#">Portfolio</a></li>
<li><a class="a1" href="#">Services</a></li>
<li><a class="a1" href="#">Contact</a></li>
</ul>
try to use jQuery hover method, but also you cant touch :after :before elements from jQuery
$("p").hover(function(){
$(this).css("background-color", "yellow");
}, function(){
$(this).css("background-color", "pink");});

Categories