JS for smooth scroll to the bottom of the page - javascript

I have a JS to make a smooth scroll from the bottom of the page to the top with this and it works:
<script>
$("a[href='#top']").click(function() {
$("html, body").animate({ scrollTop: 0 }, "slow");
return true;
});
</script>
But now I want to make a smooth scroll from the top to the bottom, I tried it with this:
<script>
$("a[href='#footer']").click(function() {
$("html, body").animate({ scrollToBottom: 0 }, "slow");
return true;
});
</script>`
It doesn't work, it's not a smooth scroll. Does anyone know what's wrong with this?

With pure JS:
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' })
and to the top as:
window.scrollTo({ top: 0, behavior: 'smooth' })

There is no such thing as scrollToBottom. Try this:
$("html, body").animate({ scrollTop: document.body.scrollHeight }, "slow");

For a more comprehensive list of methods for smooth scrolling, see my answer here.
To scroll to the bottom of the page, the y-position can be set to document.scrollingElement.scrollHeight.
For scrolling to a certain position in an exact amount of time, window.requestAnimationFrame can be put to use, calculating the appropriate current position each time. setTimeout can be used to a similar effect when requestAnimationFrame is not supported.
/*
#param pos: the y-position to scroll to (in pixels)
#param time: the exact amount of time the scrolling will take (in milliseconds)
*/
function scrollToSmoothly(pos, time) {
var currentPos = window.pageYOffset;
var start = null;
if(time == null) time = 500;
pos = +pos, time = +time;
window.requestAnimationFrame(function step(currentTime) {
start = !start ? currentTime : start;
var progress = currentTime - start;
if (currentPos < pos) {
window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos);
} else {
window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time));
}
if (progress < time) {
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
});
}
function scrollToSmoothly(pos, time) {
var currentPos = window.pageYOffset;
var start = null;
if(time == null) time = 500;
pos = +pos, time = +time;
window.requestAnimationFrame(function step(currentTime) {
start = !start ? currentTime : start;
var progress = currentTime - start;
if (currentPos < pos) {
window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos);
} else {
window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time));
}
if (progress < time) {
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
});
}
document.querySelector('button').addEventListener('click', function(e){
scrollToSmoothly(document.scrollingElement.scrollHeight, 1000);
});
html, body {
height: 5000px;
}
<button>Scroll to bottom</button>
The SmoothScroll.js library can be used as well, which handles more complex cases such as smooth scrolling both vertically and horizontally, scrolling inside other container elements, different easing behaviors, scrolling relatively from the current position, and more.
smoothScroll({yPos: 'end', duration: 1000});
document.querySelector('button').addEventListener('click', function(e){
smoothScroll({yPos: 'end', duration: 1000});
});
html, body {
height: 5000px;
}
<script src="https://cdn.jsdelivr.net/gh/LieutenantPeacock/SmoothScroll#1.2.0/src/smoothscroll.min.js" integrity="sha384-UdJHYJK9eDBy7vML0TvJGlCpvrJhCuOPGTc7tHbA+jHEgCgjWpPbmMvmd/2bzdXU" crossorigin="anonymous"></script>
<button>Scroll to bottom</button>

// Scroll smoothly to the bottom
domElement.scrollTo({
top: document.body.scrollHeight,
behavior: 'smooth',
})
All options for scrollTo are:
top: number
left: number
behavior: 'smooth' or behavior: 'auto'

The accepted answer and others are correct, but wanted to add another usecase that might help someone.
In some cases, you'd need to do the scrolling inside a setTimeout()'s callback with a short delay.
function scrollToBottom() {
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
}
setTimeout(function() { scrollToBottom(); }, 100);
For example: you have a <button> which adds a <div> element to the bottom of the page when clicked on, and you want to scroll to the bottom so the user can see this new div. In this case, sometimes (depends on the event-loop behavior), you'd need to do the scroll inside a setTimeout() because the same action that triggers the scroll actually changes the value of document.body.scrollHeight. By delaying it, you make it use the new updated value of document.body.scrollHeight after the div was added.

Related

Scroll to top link for website using pure JAVASCRIPT without(jquery)

I want normal scroll to top for website.
The scroll to top link appears at the bottom of page(near footer) which only visible after 200px mouse scroll down and should be hidden when scroll back to top. WITHOUT JQUERY
Here is the demo
In this demo back to top is already at the bottom. Is there any way to show back to top link fixed as I mention above?
if you want it as simple as possible, just use:
<a href="#" onClick="window.scrollTo(0,0)">
this will scroll you to the top of your site.
For this case, the MDN docs leave an awesome solution, we can now use the following example:
const el = document.getElementById('the-scroll-box');
el.scrollTo({
top: 0,
left: 0,
behavior: 'smooth', // or can get `auto` variable
});
The behavior if have smooth value, the scrolling motion is smooth if have auto value the motion happen in one jump.
Here is the answer
HTML
<a id="scroll_to_top_id"></a>
CSS
#scroll_to_top_id {
display: none;
position: fixed;
right: 30px;
bottom: 30px;
background
}
PURE JAVASCRIPT(NO JQUERY)
/*
* Scroll To Top
*/
var your_header = document.getElementById('header_id'),
scroll_to_top = document.getElementById('scroll_to_top_id');
window.onscroll = function(ev) {
var scrollTop = window.pageYOffset || document.body.scrollTop;
if (scrollTop > your_header.offsetHeight + 100) {
scroll_to_top.style.display = 'block';
}
else{
scroll_to_top.style.display = 'none';
}
};
scroll_to_top.onclick = function () {
scrollTo(document.body, 0, 100);
}
/*
* scroll to body top
* element, position and time duration
*/
function scrollTo(element, to, duration) {
if (duration < 0) return;
var difference = to - element.scrollTop;
var perTick = difference / duration * 2;
setTimeout(function() {
element.scrollTop = element.scrollTop + perTick;
scrollTo(element, to, duration - 2);
}, 10);
}

JS animation loop when returning to hide element

I have an element which I animate to move across the screen. From left:-100px to left:screen-width. I loop this 4 times.
When returning the element back to its original position left:-100px, I don’t want it to be seen moving across the screen (from right to left) really fast.
I tried to do it by hiding the element with .hide() and then showing it after a while (so that it has time to move back to its initial position). But this doesn’t work:
$('.snake-image').hide();
$('.snake-image').css('top', height / 2).css('left', currentPos);
setTimeout(function(){$('.snake-image').show();},1000);
Code:
$('body').append('<a href="#"><img src="https://dl.dropboxusercontent.com/u/48552248/projects/covve/website/2015/public/images/snake.png" class="snake-image" style="position:absolute;top:0;" />');
function goRight(currentPos) {
$('.snake-image').animate({
left: currentPos
}, 100);
}
function moveSnake() {
while (currentPos <= width) {
goRight(currentPos);
currentPos += 20;
console.log(width + " x " + currentPos);
}
}
var currentPos,
height = $(window).height(),
width = $(window).width(),
i = 4;
var intervalID = setInterval(function(){
if (i > 0){
currentPos = -100;
$('.snake-image').hide();
$('.snake-image').css('top', height / 2).css('left', currentPos);
setTimeout(function(){$('.snake-image').show();},1000);
moveSnake();
i--;
console.log('Interval 1');
} else {
clearInterval(intervalID);
}
}, 100);
Demo: http://jsfiddle.net/m0epjLym/
you could use the animate callback
triggered at the end of the animation, you can move your item back in the origina position and then call again the animation
Fiddle:http://jsfiddle.net/xgknu376/
You can do this:
$('.snake-image').animate({'opacity': 0}, 0);
$('.snake-image').animate({'top': height / 2}, 0).animate({'left': currentPos}, 0).delay(1000).animate({'opacity': 1}, 0);
The delay function will only work on items that are in the animation queue.
Fiddle: http://jsfiddle.net/y995cts3/3/

Smooth mouse wheel scrolling

I use chrome and scrolling is fast but its dont smooth. Text jumps multiple times.
But on this site http://www.if-not-true-then-false.com/ scroll works very smooth! And FAST!
http://bassta.bg/demos/smooth-page-scroll/ This scroll is smooth but very sloow and lagga (fast mount wheel dont change speed of scroll screen)
How this site have this smooth scroll? I cant find it(
try this one
<script type="text/javascript">
if (window.addEventListener) window.addEventListener('DOMMouseScroll', wheel, false);
window.onmousewheel = document.onmousewheel = wheel;
function wheel(event) {
var delta = 0;
if (event.wheelDelta) delta = event.wheelDelta / 120;
else if (event.detail) delta = -event.detail / 3;
handle(delta);
if (event.preventDefault) event.preventDefault();
event.returnValue = false;
}
function handle(delta) {
var time = 1000;
var distance = 300;
$('html, body').stop().animate({
scrollTop: $(window).scrollTop() - (distance * delta)
}, time );
}
</script>
First make a link with #top link then try the following code
try this
<script type="text/javascript">
$("a[href='#top']").click(function() {
$("html, body").animate({ scrollTop: 0 }, 1000);//here you can specify your time for smooth operation
return false;
});
</script>

javascript scroll div into view with smooth scroll effect?

I am using the following javascript code to scroll my div into view when a user click on a div.
<script>
function showDiv2() {
document.getElementById('about').style.display = "none";
document.getElementById('terms').style.display = "none";
document.getElementById('breaker').style.display = "block";
document.getElementById('contact_us').style.display = "block";
document.getElementById( 'contact_us' ).scrollIntoView('slow');
}
</script>
this code works and scrolls the div into view, but there is no effect, instead of the page scrolling smoothly down to my div it sort of just jumps to the div. Is there a way I can make this smoothly and slowly scroll down to my div? Thanks
According to Element.scrollIntoView() documentation try this:
element.scrollIntoView({block: "end", behavior: "smooth"});
but you must remember that this is an experimental feature and works good only in Firefox
For a more comprehensive list of methods for smooth scrolling, see my answer here.
To scroll to a certain position in an exact amount of time, window.requestAnimationFrame can be put to use, calculating the appropriate current position each time. To scroll to an element, just set the y-position to element.offsetTop.
/*
#param pos: the y-position to scroll to (in pixels)
#param time: the exact amount of time the scrolling will take (in milliseconds)
*/
function scrollToSmoothly(pos, time) {
var currentPos = window.pageYOffset;
var start = null;
if(time == null) time = 500;
pos = +pos, time = +time;
window.requestAnimationFrame(function step(currentTime) {
start = !start ? currentTime : start;
var progress = currentTime - start;
if (currentPos < pos) {
window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos);
} else {
window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time));
}
if (progress < time) {
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
});
}
Demo:
function scrollToSmoothly(pos, time) {
var currentPos = window.pageYOffset;
var start = null;
if(time == null) time = 500;
pos = +pos, time = +time;
window.requestAnimationFrame(function step(currentTime) {
start = !start ? currentTime : start;
var progress = currentTime - start;
if (currentPos < pos) {
window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos);
} else {
window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time));
}
if (progress < time) {
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
});
}
document.getElementById("toElement").addEventListener("click", function(e){
scrollToSmoothly(document.querySelector('div').offsetTop, 500 /* milliseconds */);
});
document.getElementById("backToTop").addEventListener("click", function(e){
scrollToSmoothly(0, 500);
});
<button id="toElement">Scroll To Element</button>
<div style="margin: 1000px 0px; text-align: center;">Div element
<button id="backToTop">Scroll back to top</button>
</div>
The SmoothScroll.js library can also be used, which supports scrolling to an element on the page in addition to more complex features such as smooth scrolling both vertically and horizontally, scrolling inside other container elements, different easing behaviors, scrolling relatively from the current position, and more.
document.getElementById("toElement").addEventListener("click", function(e){
smoothScroll({toElement: document.querySelector('div'), duration: 500});
});
document.getElementById("backToTop").addEventListener("click", function(e){
smoothScroll({yPos: 'start', duration: 500});
});
<script src="https://cdn.jsdelivr.net/gh/LieutenantPeacock/SmoothScroll#1.2.0/src/smoothscroll.min.js" integrity="sha384-UdJHYJK9eDBy7vML0TvJGlCpvrJhCuOPGTc7tHbA+jHEgCgjWpPbmMvmd/2bzdXU" crossorigin="anonymous"></script>
<button id="toElement">Scroll To Element</button>
<div style="margin: 1000px 0px; text-align: center;">Div element
<button id="backToTop">Scroll back to top</button>
</div>

jQuery scrollTop being buggy

I'm trying to make a sub navigation menu animate a fixed position change after a user has scrolled down 200 pixels from the top. It works but it's very buggy, like when the user scrolls back to the top it doesn't always return to the original position, etc. I'm not strong with javascript / jquery, but I thought this would be simple to do. What am I missing?
Here's my fidde:
http://jsfiddle.net/visevo/bx67Z/
and a code snippet:
(function() {
console.log( "hello" );
var target = $('#side-nav');
var scrollDis = 200;
var reset = 20;
var speed = 500;
$(window).scroll(function() {
console.log( $(window).scrollTop() );
if( $(window).scrollTop() > scrollDis ) {
$(target).animate({
top: reset + 'px'
}, speed);
} else {
$(target).animate({
top: scrollDis + 'px'
}, speed);
}
});
})();
How about a little bit of css and jquery both ??
What I did is added transition to side-nav to animate it and rectified your js to just change it's css. You can set how fast it moves by changing the time in transition.
FIDDLE
#side-nav {
position: fixed;
top: 100px;
left: 10px;
width: 100px;
background: #ccc;
-webkit-transition:all 0.5s ease-in-out;
}
(function () {
var target = $('#side-nav');
var scrollDis = 100;
var reset = 20;
var speed = 500;
$(window).scroll(function () {
if ($(this).scrollTop() >= scrollDis) {
target.css("top", reset);
} else {
target.css("top", scrollDis);
}
});
})();
NOTE: When you cache a jQuery object like this
var target = $("#side-nav");
You don't need to use $ again around the variable.
Since I am commenting all over the place I should probably actually contribute an answer.
The issue is that you are adding scroll events every time a scroll occurs, which is causing more scrolling to occur, which causes more scroll events, hence infinite loop. While cancelling previous events will fix the problem, it's cleaner to only fire the event when you pass the threshold, IE:
(function () {
console.log("hello");
var target = $('#side-nav');
var scrollDis = 200;
var reset = 20;
var speed = 500;
var passedPosition = false;
var bolMoving = false;
$(window).scroll(function () {
if (bolMoving) return; // Cancel double calls.
console.log($(window).scrollTop());
if (($(window).scrollTop() > scrollDis) && !passedPosition) {
bolMoving = true; //
$(target).animate({
top: reset + 'px'
}, speed, function() { bolMoving = false; passedPosition = true; });
} else if (passedPosition && $(window).scrollTop() <= scrollDis) {
bolMoving = true;
$(target).animate({
top: scrollDis + 'px'
}, speed, function() { bolMoving = false; passedPosition = false; });
}
});
})();
http://jsfiddle.net/bx67Z/12/
http://jsfiddle.net/bx67Z/3/
I just added .stop() in front of the .animate() , and it works a lot better already.
$(target).stop().animate({
top: reset + 'px'
}, speed);
} else {
$(target).stop().animate({
top: scrollDis + 'px'
}, speed);
You can also use .stop(true)
http://jsfiddle.net/bx67Z/5/
$(target).stop(true).animate({
top: reset + 'px'
}, speed);
} else {
$(target).stop(true).animate({
top: scrollDis + 'px'
}, speed);
You can also use .stop(true, true)
http://jsfiddle.net/bx67Z/4/
$(target).stop(true, true).animate({
top: reset + 'px'
}, speed);
} else {
$(target).stop(true, true).animate({
top: scrollDis + 'px'
}, speed);
So the reason .stop(true) works so well, is that it clears the animation queue. The reason yours was being "buggy" is because on every scroll the animation queue was "bubbling up" , thus it took a long time for it to reach the point where it would scroll back to the original position.
For information about .stop() , see here http://api.jquery.com/stop

Categories

Resources