javascript: when window reaches the top - javascript

This code in my CodePen works to change the height of my div.box when I scroll down. It also works when I reverse scroll (scroll back up). When I reach the top of the window, it doesn't seem to work. Do you know what's wrong with my code when the window reaches the top, or what to add to make it work in all of these 3 cases?
Here is the full CodePen so you can see what I mean: https://codepen.io/celli/pen/LYNYNQq
gsap.set(".box", {
transformOrigin: "top left"
});
var lastScrollTop = 0;
window.addEventListener("scroll", function() {
var st = window.pageYOffset || document.documentElement.scrollTop;
if (st > lastScrollTop) {
// down-scroll code
gsap.to(".box", {
scaleY: .2
})
} else if (st < lastScrollTop) {
// up-scroll code
gsap.to(".box", {
scaleY: .5
})
} else if (window.pageYOffset == 0) {
// when the window reaches the top
gsap.to(".box", {
scaleY: 1
})
}
lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
}, false);
/*
gsap.to(".box", {
scaleY:1,
ease: "circ:out",
scrollTrigger: {
trigger: ".box",
markers:true,
start: "top top",
toggleActions:"play none none reverse"
},
});
*/
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.box {
width: 100%;
height: 200px;
background-color: aqua;
opacity: .5;
position: fixed;
}
.sp {
height: 1000px;
width: 100%;
background-color: #cccccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.2/gsap.min.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/ScrollTrigger.min.js"></script>
<div class="box"></div>
<div class="sp"></div>

You need to check the most specific conditions first; in this case, you should check if the y-position is 0 first, as that will also be covered by checking if the current position is less than the previous condition.
if(st === 0){
// when the window reaches the top
gsap.to(".box", {
scaleY: 1
})
} else if (st > lastScrollTop) {
// down-scroll code
gsap.to(".box", {
scaleY: .2
})
} else if (st < lastScrollTop) {
// up-scroll code
gsap.to(".box", {
scaleY: .5
})
}
gsap.set(".box", {
transformOrigin: "top left"
});
var lastScrollTop = 0;
window.addEventListener("scroll", function() {
var st = window.pageYOffset || document.documentElement.scrollTop;
if(st === 0){
// when the window reaches the top
gsap.to(".box", {
scaleY: 1
})
} else if (st > lastScrollTop) {
// down-scroll code
gsap.to(".box", {
scaleY: .2
})
} else if (st < lastScrollTop) {
// up-scroll code
gsap.to(".box", {
scaleY: .5
})
}
lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
}, false);
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.box {
width: 100%;
height: 200px;
background-color: aqua;
opacity: .5;
position: fixed;
}
.sp {
height: 1000px;
width: 100%;
background-color: #cccccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.2/gsap.min.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/ScrollTrigger.min.js"></script>
<div class="box"></div>
<div class="sp"></div>

Related

Why won't navbar fix to the top?

This code works when I take out the check of window width. Once I add in a reference to the window width the code no longer works. I only want the navbar to become fixed on screen sizes smaller than 768px. I'm rusty with jQuery so help is appreciated.
$(document).ready(function() {
var width = $(window).width();
$(window).scroll(function() {
if ($(width) < 768) {
if ($(this).scrollTop() > 567) {
$('.navbar').css('position', 'fixed').css('top', '0');
} else {
$('.navbar').css('position', 'relative');
}
} else {
$('.navbar').css('position', 'relative');
}
})
$(window).resize(function() {
if ($(width) < 768) {
if ($(this).scrollTop() > 567) {
$('.navbar').css('position', 'fixed').css('top', '0');
} else {
$('.navbar').css('position', 'relative');
}
} else {
$('.navbar').css('position', 'relative');
}
});
});
The main issue here is that you're placing width within a jQuery object when this is not necessary. Just use width directly in the conditions:
if (width < 768)
That being said, your code can be DRY'd up and also improved through the use of CSS classes and media queries. Try this:
jQuery(function($) {
$(window).on('scroll resize', function() {
$('.navbar').toggleClass('fixed', $(this).scrollTop() > 567);
});
});
html,
body {
height: 2000px;
padding: 0;
margin: 0;
}
.navbar {
padding: 10px;
background-color: #CCC;
}
#media only screen and (max-width: 768px) {
.navbar.fixed {
position: fixed;
top: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="navbar">Navbar</div>

Smooth transition on scroll after adding header on scroll up

I'm creating a header which:
Displays on default (transparent background)
When user scrolls down the page (25px), it will add the header--maroon class to header - which it does. The header-maroon class basically adds the background color and anchor styles.
But at this point (when the user has scrolled 25px down the page), I want the header to "fade up" smoothly and basically stay hidden when the user is scrolling down.
Lastly, when a user scrolls (10px) up the page, I want the header to fade in neatly at the top of the viewpoint.
Here's my current approach. It kind of works, but not as smooth as I'd like (as in the the header just appears, I want it to transition in). I have tried to add transitions, but it doesn't work?
/**********/
/* SCROLL */
/**********/
//Add transition when scrolling down
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 25) {
$("header").addClass("header--maroon");
} else {
$("header").removeClass("header--maroon");
}
});
// add scroll effect on page refresh too
$(function() {
var scroll = $(window).scrollTop();
if (scroll >= 10) {
$(".mainMenu").addClass("header--maroon");
} else {
$(".mainMenu").removeClass("header--maroon");
}
});
/******************************/
/* HIDE HEADER ON SCROLL DOWN */
/******************************/
var didScroll;
var lastScrollTop = 0;
var delta = 25;
var navbarHeight = $('header').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
if(Math.abs(lastScrollTop - st) <= delta)
return;
if (st > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header').removeClass('nav-down').addClass('nav-up');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
body{
background: wheat;
height:1000px;
}
header {
position: fixed;
transition: top 0.2s ease-in-out;
width: 100%;
height: 90px;
background: transparent;
}
.nav-up {
top: -90px;
transition: top 0.2s ease-in-out;
}
.header--maroon {
background: #521717;
transition: top 0.2s ease-in-out;
}
.mainMenu {
background-color: transparent;
width: 100%;
padding: 10px 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header class="nav-down">
<div class="mainMenu">Link</div>
</header>
<div class="gap"></div>
Try implementing this:
JSFiddle
HTML:
<header class="nav-down">
This is your menu.
</header>
<main>
This is your body.
</main>
<footer>
This is your footer.
</footer>
CSS:
body {
padding-top: 40px;
}
header {
background: #f5b335;
height: 40px;
position: fixed;
top: 0;
transition: top 0.2s ease-in-out;
width: 100%;
}
.nav-up {
top: -40px;
}
main {
background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAPklEQVQYV2O8dOnSfwYg0NPTYwTRuAAj0QqxmYBNM1briFaIzRbi3UiRZ75uNgUHGbfvabgfsHqGaIXYPAMAD8wgC/DOrZ4AAAAASUVORK5CYII=) repeat;
height: 2000px;
}
footer { background: #ddd;}
* { color: transparent}
JS:
// Hide Header on on scroll down
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('header').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScrollTop - st) <= delta)
return;
// If they scrolled down and are past the navbar, add class .nav-up.
// This is necessary so you never see what is "behind" the navbar.
if (st > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header').removeClass('nav-down').addClass('nav-up');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
(** Credit for this code goes to the creator of the JSFiddle)
Hope this helps!
You can use the .animate() class.
Replace...
$('header').removeClass('nav-down').addClass('nav-up');
With...
$("header").animate({ top: '-90px' },300);
And replace...
$('header').removeClass('nav-up').addClass('nav-down');
With...
$("header").animate({ top: '10px' },300);
Here is a JSFiddle example using your code.
Note that this is just a rough implementation.
You can play with it and tweak it until it works as you want it to.
Add transition to the class which you are adding on scroll.
.header-maroon{
transition: all 0.5s ease-in-out;
}

Transparent navigation at top of page

I have the following code which adds/removes a class to my navigation div when the user scrolls.
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 100);
function hasScrolled() {
if ($(window).width() > 768) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta) {
return;
}
if (st > lastScrollTop && lastScrollTop >= 0 && st > 0) {
$('#anim-nav').removeClass('nav-down').addClass('nav-up');
} else {
$('#anim-nav').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
});
I want to add .trans-bg to #anim-nav when the user is close to the top of the screen. It has a background of white, but when it gets to the top o the screen I want it transparent as it goes over an image. However when i added it to this function wasn't reliable. Sometimes it would stay transparent, or not turn transparent.
Not sure how to add something that constantly runs to make sure if the user is near/at the top it applies.
Maybe this can help?
$(window).on('scroll', function () {
if ($(window).scrollTop() > 10) {
$('body').addClass('scrolled');
} else {
$('body').removeClass('scrolled');
}
});
body {
background: url("https://www.toptal.com/designers/subtlepatterns/patterns/christmas-black.png");
height: 3000px;
}
.scrolled .header {
background-color: rgba(255, 255, 255, .8)
}
.header {
background-color: #fff;
height: 80px;
position: fixed;
left: 0;
top: 0;
right: 0;
transition: .2s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header class="header"></header>
Solution: Listen to scroll changes instead of checking for scrolls at a interval.
Example of listening to scroll at top using javaScript:
window.addEventListener('scroll', function(e) {
if (document.body.scrollTop == 0) {
alert("top");
}
});

Detect when an image enters a div?

I am creating a maze game, and I want to detect when the image following the cursor reaches a certain div, the finishing point. I have the image following the mouse, and I have the container that the image will be in. When the image reaches the div, I want something to trigger, lets say an alert. How can I achieve this?
var startMove;
$(document).mousemove(function(e) {
var DIFF_SNAP = 10;
var DIFF_UNSNAP = 100;
var difLeft = $('#image').offset().left - e.pageX;
var difTop = $('#image').offset().top - e.pageY;
if (!startMove && Math.abs(difLeft) < DIFF_SNAP && Math.abs(difTop) < DIFF_SNAP) {
startMove = true;
$('html').removeClass('showCursor');
} else if (startMove && !(Math.abs(difLeft) < DIFF_UNSNAP && Math.abs(difTop) < DIFF_UNSNAP)) {
startMove = false;
}
if (startMove) {
$("#image").css({
left: e.pageX,
top: e.pageY
});
} else {
$('html').addClass('showCursor');
}
});
$(document).mouseleave(function() {
startMove = false;
})
html {cursor: none;}
html.showCursor{cursor: default;}
#image{
position:absolute;
width:25px;
height:auto;
}
div{
margin-left: 500px;
width: 200px;
height: 50px;
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<img id="image" src="http://static.micheljansen.org/uploads/mac-osx-arrow-cursor.png"/>
<div></div>
Jsfiddle: https://jsfiddle.net/3x7cgLdr/25/
if ($('#TargetDiv').is(':hover')) {
// alert('hello');
$("#image").addClass("red");
}else{
$("#image").removeClass("red");
}
Using this .is() function with :hover selector inside the
if(startMove){
}
Section simply does that without any hassle the is() function Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments.
.is() function documentation
var startMove;
$(document).mousemove(function(e) {
var difLeft = $('#image').offset().left - e.pageX;
var difTop = $('#image').offset().top - e.pageY;
if (difLeft < 10 && difLeft > -10 && difTop < 10 && difTop > -10) {
startMove = true;
$('html').removeClass('showCursor');
}
if (startMove) {
$("#image").css({
left: e.pageX,
top: e.pageY
});
if ($('#TargetDiv').is(':hover')) {
// alert('hello');
$("#image").addClass("red");
} else {
$("#image").removeClass("red");
}
} else {
$('html').addClass('showCursor');
}
});
$(document).mouseleave(function() {
startMove = false;
})
html {
cursor: none;
}
html.showCursor {
cursor: default;
}
#image {
position: absolute;
width: 25px;
height: auto;
}
#TargetDiv {
height: 100px;
width: 100px;
background: green;
margin: 100px auto;
}
.red {
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<img id="image" src="http://static.micheljansen.org/uploads/mac-osx-arrow-cursor.png" />
<div id="TargetDiv">
</div>
I have added a class to set border red to the div when it hovers on the div with mouse and cursor image superimposed that is startMove="true".And removes when it is not hovered .I have commented the alert box;You can turn it on if you want
You already have a flag called startMove that is active whenever the cursor is dragged, use the mouseenter event on the target div as follows:
var startMove;
$(document).mousemove(function(e){
var difLeft = $('#image').offset().left - e.pageX;
var difTop = $('#image').offset().top - e.pageY;
if(difLeft < 10 && difLeft > -10 && difTop < 10 && difTop > -10 ){
startMove = true;
$('html').removeClass('showCursor');
}
if(startMove){
$("#image").css({left:e.pageX, top:e.pageY});
}
else{
$('html').addClass('showCursor');
}
});
$(document).mouseleave(function(){
startMove = false;
})
$("#drop").mouseenter(function(){
if(startMove)
alert("Success");
});
.
<img id="image" src="http://static.micheljansen.org/uploads/mac-osx-arrow-cursor.png"/>
<div id="drop">
</div>
.
html {cursor: none;}
html.showCursor{cursor: default;}
#image{
position:absolute;
width:25px;
z-index: 100;
height:auto;
}
#drop{
width:100px;
height:100px;
background:green;
position: absolute;
left:200px;
top: 300px;
z-index:99
}
see a demo: https://jsfiddle.net/hycd913y/

Responsive and Sticky Nav Bar

I have a nav bar that is fixed to the top of the page when the width is under 768px.
When it is over 768px it starts at the bottom and when the user scroll past it it become stuck to the top.
Both of these instance work fine on their own, but when the browser is resized there are some issues when going from under 768px to above. (Going from 768 to below works fine.)
When I load the page in a browser size under 768px and then resize the window above that is where I run in to problems.
I would like for the nav bar to smoothly transition between states. (It works beautifuly when loading above 768px then reszing to under and reszing above - Ideally this is how I would like it to work when loaded below 768px.) Or as an alternative just have the nav bar be fixed to the top when moving from under 768px to above.
This is the link to the site.
This is my CSS
.header{
width: 100%;
min-width: 300px;
height: 100px;
padding: 0px;
background: black;
position: absolute;
bottom: 0px;
z-index: 99999;
-webkit-font-smoothing: subpixel-antialiased;
}
.header.fixed{
width: 100%;
position: fixed;
top: 0px;
height: 100px;
-webkit-font-smoothing: subpixel-antialiased;
}
#media only screen and (max-width: 768px){
.header{
width: 100%;
background: black;
position: fixed;
top: 0px;
height: 100px;
-webkit-font-smoothing: subpixel-antialiased;
}
}
and this is the Javascript
<script>
jQuery(document).ready(function() {
var s = jQuery(".header");
var pos = s.position();
jQuery(window).scroll(function() {
var windowpos = jQuery(window).scrollTop();
if (windowpos >= pos.top) {
s.addClass("fixed");
} else {
s.removeClass("fixed");
}
});
});
</script>
I have also tried below to no luck.
<script>
if ( jQuery(window).width() > 768) {
jQuery(document).ready(function() {
var s = jQuery(".header");
var pos = s.position();
jQuery(window).scroll(function() {
var windowpos = jQuery(window).scrollTop();
if (windowpos >= pos.top) {
s.addClass("fixed");
} else {
s.removeClass("fixed");
}
});
});
}</script>
<script>
jQuery(window).resize(function(){
if ( jQuery(window).width() > 768) {
jQuery(document).ready(function() {
var s = jQuery(".header");
var pos = s.position();
jQuery(window).scroll(function() {
var windowpos = jQuery(window).scrollTop();
if (windowpos >= pos.top) {
s.addClass("fixed");
} else {
s.removeClass("fixed");
}
});
});
}})</script>
try this:
function sticky_navigation() {
var browserWidth = $(window).width();
var scroll_top = $(window).scrollTop(); // our current vertical position from the top
// if we've scrolled more than the page, change its position to fixed to stick to top,
// otherwise change it back to relative
if ((scroll_top > $('.header').height()) && (browserWidth > 720)) {
$('.header').css({ 'position': 'fixed', 'top':0, 'z-index':999999, 'opacity': 0.9, 'box-shadow': '0px 3px 5px #393939' });
} else {
$('.header').css({ 'position': 'relative', 'opacity': 1, 'box-shadow': 'none' });
}
};
// and run it again every time you scroll
$(window).scroll(function() {
sticky_navigation();
});
// and run every time you resize to boot
$(window).resize(function() {
sticky_navigation();
});

Categories