Display some element user scrolling - javascript

I would like to display some element (div for example) when the user scrolling.
I seeing that a scrollTop, but isn't work. Because for sure I use badly.
I can't find some help without JQuery. I don't want to use JQuery.
I try this :
var scroll = document.body.scrollTop;
var divLis = document.querySelectorAll("div");
for(let i = 0; i < divLis.length; i++) {
if(scroll === divLis[i]) {
divLis[i].style.transform = "translateX(0)";
divLis[i].style.transition = "2s";
}
}

I honestly can't really tell what you're trying to do, but given your response to #uom-pgregorio's answer, I'm guessing you might just want a pure JS scroll listener:
window.addEventListener('scroll', function() {});

Edit: Sorry I just noticed that you didn't want jQuery but I'll just leave this here in case you change your mind.
$(window).scroll(function() {
// show the div(s)
});
That's an event handler where the function runs or fires up whenever the window or viewport scrolls.

Ok... I understand.
I wanted to try this :
* {
margin: 0;
padding: 0;
border: 0;
}
body {
height: 200vh;
}
.left {
width: 300px;
height: 300px;
background-color: red;
position: absolute;
top: 150%;
transform: translateX(-300px);
transition: 5s;
}
// HTML :
<div class="left"></div>
// JS
var divLis = document.querySelector(".left");
window.addEventListener("scroll", function (e) {
if(window.pageYOffset > 500) {
console.log(window.pageYOffset)
divLis.style.transform = "translateX(0)";
}
})
So, it's very simple and I took my head for nothing.
So thanks so much for answering me !
Enjoy your Weekend

Related

Changing the size of the image in the sticky header when scrolling down

On the website (please don't share), in WordPress, I set a sticky header using CSS
header#masthead {
position: sticky;
top: 0;
left: 0;
right: 0;
z-index: 10000;
}
This works correctly. However, the image in the header is too big, that's why I resized it with an animation when scrolling down
jQuery(document).ready(function() {
jQuery(function() {
var $nav = jQuery('#masthead .custom-logo');
var height_original = jQuery('#masthead .custom-logo').css("height").replace("px","");
var height_small = height_original * 0.666;
var width_original = jQuery('#masthead .custom-logo').css("width").replace("px","");
var width_small = width_original * 0.666;
jQuery(document).scroll( function() {
var value = jQuery(this).scrollTop();
if ( value > 0 ){
$nav.stop().animate({height:height_small,width:width_small},100);
} else if (value == 0 ) {
$nav.stop().animate({height:height_original,width:width_original},100);
}
});
});
});
But, it doesn't work properly.
I primarily use Opera GX, where it behaves like this - when scrolling down, the animation is slowed down. Also, if you just scroll down a little, the animation doesn't run all the way and the image goes back to its original size, scrolling up works without a problem.
The strange thing is that I've also tried it in Firefox, Chrome and Edge. It behaves differently in everyone, but nowhere does it work 100% correctly.
What is wrong with the code please?
Thank you
I think instead of that long jquery code you can use this simple javascript code with some css to get the results you want:
I hope this helps you to reach what you looking for :)
JS
// Add a class to the header when scrolling
let header = document.querySelector('header');
window.addEventListener('scroll' , function () {
let window_top = this.scrollY;
if (window_top == 0) {
header.classList.remove('resize');
}else {
header.classList.add('resize');
}
});
CSS
/* these are the default styles (when the user doesnt scroll down yet) */
header#masthead {
position: sticky;
top: 0;
left: 0;
right: 0;
z-index: 10000;
transition: .3s;
}
header#masthead img{
transition: .3s; /*here i added transition to give the image a smooth animation*/
}
/* these are the styles when the user scrolls */
header#masthead.resize img{
height: 50px; /* <=== here i gived the image a smaller size */
}

How to activate different functions if you are at certain part of the page?

I want to make two functions, "functionattoppage" and "functionat1000pxpage". I want to make the function "functionattoppage" activate when the user is at the top of a webpage and "functionat1000pxpage" activate when the user is down about 1000px from the top of the page, is this possible?
Here is the only thing I could come up with:
window.onscroll = function () {
scrollFunction()
};
function scrollFunction() {
if (document.body.scrollTop > 1000 || document.documentElement.scrollTop > 1000) {
document.body.classList.add("body.changed");
}
if (document.body.scrollTop > 0 || document.documentElement.scrollTop > 0) {
document.body.classList.remove("body.changed");
}
}
<h1>Please look at the JavaScript section, it is what my best guess would be on how to make this work</h1>
Sorry if I didn't explain this very well, I don't have much time right now. If you need more information please ask me.
After console logging document.body.scrollTopin the fiddle came out to be zero. Plus your conditions are bound to fail because when scrollTop > 1000 then it is > 0 too.
you should either make it a else or move the >0 condition to the first
window.onscroll = function() {
scrollFunction()
};
function scrollFunction() {
console.log(document.documentElement.scrollTop);
if (document.documentElement.scrollTop > 200) {
document.getElementsByTagName('h1')[1].classList.add("changed");
}
else{
document.getElementsByTagName('h1')[1].classList.remove("changed");
}
}
.changed {
color: red
}
<h1>Please look at the JavaScript section, it is what my best guess would be on how to make this work</h1>
<div style="height: 400px;background: grey;"></div>
<h1>Please look at the JavaScript section, it is what my best guess would be on how to make this work</h1>
<div style="height: 400px;background: grey;"></div>
Looks like you are trying to hide a class when the scroll position for the window is within 0 and 1000 pixels yes? The a conditional that will check if the scrollY position of the window, window.scrollY is greater than 0, but less than 1000, add the class else remove the class.
window.onscroll = () => {
scrollFunction()
}
const scrollFunction = () => {
window.scrollY > 0 && window.scrollY < 1000 ?
document.body.classList.add("changed") :
document.body.classList.remove("changed")
document.getElementById("scroll_position").textContent = window.scrollY;
}
#scroll_position {
position: fixed;
top: 0;
right: 0;
background: red;
color: #fff;
padding: 8px;
width: 100px;
}
#cont {
height: 3000px;
}
#cont h1 {
position: sticky;
top: 50px;
}
.changed {
background: black;
color: white;
}
<p id="scroll_position"></p>
<div id="cont">
<h1>Please look at the JavaScript section, it is what my best guess would be on how to make this work</h1>
</div>
You can use a div as your marker. And when it is >= 0 execute one function and when it gets to -1000px execute another. Use getBoundingClientRect() to get an elements coordinates.
HTML
<div id=“marker1”></div>
JS
window.addEventListener( "scroll", function(){
let marker1 = document.getElementById("marker1").getBoundingClientRect();
if (marker1.top >= 0) atTop();
if (marker1.top <= -1000) at1000px();
})
function atTop() {
document.body.style.backgroundColor = "blue";
}
function at1000px() {
document.body.style.backgroundColor = "red";
}
Be aware the atTop won’t execute until you start scrolling because of the type of event listener. If you want it executed on load also then you’ll need to add that.
You can do it through sensing the scroll event as you are doing, but it's quite overheady.
Instead you could use an IntersectionObserver on a couple of elements, This will tell you when they come into and go out of the viewport and you don't have to worry about any intermediate scrolling.
If you already have elements that you want to sense in those positions you could sense those going into and out of the viewport. If not you can 'plant' a couple of 1px divs at the top and at 1000px and sense them coming in and out.
This snippet just logs the comings and goings to the console but of course you put whatever code you want in their place.
function callback (entries) {
for (let i = 0; i < entries.length; i++) {
if (entries[i].isIntersecting) {console.log(entries[i].target.classList + ' is in the viewport'); }
else {console.log(entries[i].target.classList + ' is not in the viewport'); }
}
}
const observer = new IntersectionObserver(callback);
const sensors = document.querySelectorAll('.sensor');
for (let i = 0; i < sensors.length; i++) {
observer.observe(sensors[i]);
}
.talldiv {
width: 100vw;
height: 2000px;
background-image: linear-gradient(to bottom, red, blue, orange, green, purple, cyan); /*just so we notice scrolling */
}
.sensor {
position: absolute;
left: 50%;
top: var(--top);
width: 1px;
height: 1px;
background: transparent;
}
.sensetop {
--top: 0px;
}
.sense1000px {
--top: 999px;
}
<div class="sensor sensetop"></div>
<div class="sensor sense1000px"></div>
<div class="talldiv"></div>

What is missing within my javascript for a disappearing navbar?

I want to avoid jQuery so I can get a better feel for Javascript. For now I have a Codepen set up that displays a large majority of my first project. I know the code is probably sloppy and I am a beginner. I simply want to get the JS working with my navbar completely disappearing onScroll then I will optimize it from there. Thanks!
I have searched youtube, google, SO but everyone seems to use jQuery.
https://codepen.io/dev20tx/pen/wbKyJq
The CSS:
.nav {
border-bottom: 1px solid #EAEAEB;
text-align: right;
height: 70px;
line-height: 70px;
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: white;
opacity: 0.8;
z-index: 2;
}
And the Javascript:
window.onscroll = function() {navFunction()};
function navFunction() {
if (document.body.scrollTop > 50 ||
document.documentElement.scrollTop > 50) {
document.queryselector(".nav").className = "test";
} else {
document.queryselector(".nav").className = "";
}
}
Disappearing navbar.
I've updated the codepen at https://codepen.io/anon/pen/rgOdXy
Following is the updated JavaScript code, first problem was that you was attaching event listener to window, instead of the element which is to be scrolled and second mistake was the spelling mistake of querySelector method
function navFunction(e) {
if (e.target.scrollTop > 50 || document.documentElement.scrollTop > 50) {
document.querySelector(".nav").className = "nav test";
} else {
document.querySelector(".nav").className = "nav";
}
}
document.querySelector(".container").addEventListener("scroll",navFunction);
Allright, so, few things.
First, queryselector should be querySelector (with a capital S). Also note that setting the .nav's className to "test" or "" will remove the "nav" class from that element.
Second, you should make sure you attach the onscroll event after the page has loaded.
Lastly, you're attaching the onscroll event to the window, but you actually want to attach it to the .container element, as that's the element you're scrolling.
I'm not just throwing the entire solution in your lap, as you seem to want to play around yourself a little bit. If you do want a more elaborate answer, don't hesitate to ask.

jQuery animate scrollTop goes up then back down

I have a function that checks if there are any errors on the page and auto scrolls to them. The problem that I'm having is it scrolls up to them but then comes back down to where it was before. I'd like it to scroll up and stay there.
$(".submit_button").click(function (event) {
event.preventDefault();
var errorElements = $(".error").filter(":visible");
if (errorElements.size() > 0) {
target_top = $(errorElements).offset().top;
$('html, body').animate({
scrollTop: target_top
}, 800);
}
return false;
});
The problem is in your selector. I know why it's done. Any web dev that's been in this long enough has been using that for as much cross browser compat as possible, and yet still encountered this issue. The problem is, you're calling animate:scroll on 2 items consecutively using this selector.
The better way, in short, would be to check if it is a WebKit browser or not. Reason being is that non-WebKit tend to use html whereas WebKit browsers tend to use body (and sometime html). This can cause such confusion as you face now.
The simple short term solution is to use something like /WebKit/i.test(navigator.userAgent) in your click callback. This will help you assign only one selector to the animate call.
Example
var selector = /WebKit/i.test(navigator.userAgent) ? 'body' : 'html';
$(selector).animate( // ...
Test Snippet
$(function() {
// simply to make filler divs for scrolling
for (var i=0;i<10;i++) $('<div />', { 'id': 'div'+i, 'style': 'background-color: '+String.randColorHex()+';' }).append($('.temp').clone().removeClass('temp')).height($(window).height()).appendTo($('body'));
/*------------------------------------------*/
/***S*O*L*U*T*I*O*N***/
var divID = 0;
function btnCheck() { // IGNORE, simply to turn buttons on and off when reaching end
$('#btnScrollDown').prop('disabled', divID>=9);
$('#btnScrollUp').prop('disabled', divID<=0);
}
$(document)
.on('click', '#btnScrollDown', function() {
if (divID < 10) {
divID++;
// broke everything down so it's easy to see. You can shorten this in a few ways.
/*THIS HERE-> */var selector = /WebKit/i.test(navigator.userAgent) ? 'body' : 'html',
scrollSelector = '#div' + (divID),
scrollTop = $(scrollSelector).offset().top
props = { scrollTop: scrollTop },
time = 800;
$(selector).animate(props, time);
// simply to turn buttons on and off when reaching end
btnCheck();
}
})
.on('click', '#btnScrollUp', function() {
if (divID > 0) {
divID--
// broke everything down so it's easy to see. You can shorten this in a few ways.
/*THIS HERE-> */var selector = /WebKit/i.test(navigator.userAgent) ? 'body' : 'html',
scrollSelector = '#div' + (divID),
scrollTop = $(scrollSelector).offset().top
props = { scrollTop: scrollTop },
time = 800;
$(selector).animate(props, time);
// simply to turn buttons on and off when reaching end
btnCheck();
}
});
});
html, body, div { margin: 0; padding: 0; width: 100%; }
.buttons { display: inline-block; left: 1em; position: fixed; text-align: center; top: 1em; }
button { margin: .25em; padding: .1em .3em; width: 100%; }
.temp { dislpay: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/JDMcKinstry/String.randColorHex/0c9bb2ff/String.randColorHex.js"></script>
<section class="buttons">
<button id="btnScrollUp" disabled>Scroll To Next Div Up</button><br />
<button id="btnScrollDown">Scroll To Next Down</button>
<sub><i>this isn't fully managed, only use buttons to scroll!</i></sub>
</section>
<table class="temp"><tr><td></td></tr></table>

jQuery doesn't show and hide the header

I'm trying to make a header that appears at a certain place of the page.
So what I'm doing is checking the scroll to top of the page and the top offset of the element after which the header should appear. If the scrollTop is greater than offset the header is shown, otherwise it disappears.
But! When I scroll to the place, the header position is constantly switching between top: -13% and top: -12.999998%. After some time it finally shows the header but it never disappears.
What am I doing wrong?!
JSFiddle: https://jsfiddle.net/5k5s016f/
Well, i think the problem is that the .animate() functions are running constantly, causing the animations to "restart" before its ends.
It is not the most beautiful solution, but just adding a flag that controls the execution of the functions and a timeout to run the handler less frequently solves the problem.
https://jsfiddle.net/5k5s016f/2/
var visible = false;
$(window).scroll(function() {
setTimeout(function(){
var height = $(window).scrollTop();
var $page2 = $("#page2");
var offset = $page2.offset().top;
if (height > offset) {
if (visible) {
return;
}
visible = true;
$(".floating-header").show().animate({
top: 0
});
} else {
if (!visible) {
return;
}
visible = false;
$(".floating-header").animate({
top: "-13%"
});
}
}, 200)
});
The issue you are seeing is because each time a scroll event gets called animation queues up. If you wait long enough, you can see that the animation to set top to 0 actually works.
You can use the stop() function to stop all animation before attempting to run another one.
Something like this
if (height > offset) {
$(".floating-header").stop().show().animate({
top: "0"
}, 700);
} else {
$(".floating-header").stop().animate({
top: "-13%"
}, 700);
}
A couple of improvements I can suggest are
Debounce the scroll event handler
Check the current state of the header before queuing animation. i.e. do not try to hide it if it is already hidden and vice versa
Your logic is all messed up. Basically, you want to make sure that you are only animating when you absolutely need to - no more, no less. And since scroll events happen hundreds of times... constantly rapid firing as the user scrolls... you want to make sure you are doing the least amount of work possible during each scroll event. This especially means that you don't want to be querying the DOM on every scroll event if you don't have to (ps. $('selector') is a dom query). Take a look at this fiddle:
https://jsfiddle.net/5k5s016f/6/
Looks like I'm last to the party due to interruptions, but since I wrote it up I'll post the answer FWIW.
jsFiddle Demo
You need to debounce your code. Here is a simple system, but studing Ben Alman's explanation/examples is also recommended.
var $m1 = $('#m1'), $m2 = $('#m2'); //TESTING ONLY
var $win = $(window), $page2 = $("#page2"), $hdr=$(".floating-header");
var $offset = $page2.offset().top;
var hvis = false, curpos;
$win.scroll(function() {
curpos = $win.scrollTop();
$m1.html(curpos); //TESTING ONLY
$m2.html($offset);//TESTING ONLY
if ( curpos > $offset ) {
if ( !hvis ){
hvis = true;
//$m1.html(curpos);
$hdr.finish().animate({
top: "0"
}, 700);
}
} else {
if ( hvis ){
$hdr.finish().animate({
top: "-60px"
}, 700);
hvis = false;
}
}
});
html,
body {
height: 100vh;
width: 100vw;
}
#page1,
#page2,
#page3 {
height: 100%;
width: 100%;
background-color: #fff;
}
.floating-header {
position: fixed;
top: -60px;
background-color: #000;
width: 100%;
height: 60px;
}
.msg{position:fixed;bottom:10px;height:30px;width:80px;text-align:center;}
.msg{padding-top:10px;}
#m1 {left:3px; border:1px solid orange;background:wheat;}
#m2 {right:3px;border:1px solid green; background:palegreen;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<header class="floating-header">Header</header>
<div id="page1">
<p>Page1</p>
</div>
<div id="page2">
<p>Page2</p>
</div>
<div id="page3">
<p>Page3</p>
</div>
<div id="m1" class="msg"></div>
<div id="m2" class="msg"></div>

Categories

Resources