Smooth scroll anchor links WITHOUT jQuery - javascript

Is it possible to use smooth scroll to anchor links but without jQuery? I am creating a new site and I don't want to use jQuery.

Extending this answer: https://stackoverflow.com/a/8918062/3851798
After defining your function of scrollTo, you can pass the element you want to scrollTo in the function.
function scrollTo(element, to, duration) {
if (duration <= 0) return;
var difference = to - element.scrollTop;
var perTick = difference / duration * 10;
setTimeout(function() {
element.scrollTop = element.scrollTop + perTick;
if (element.scrollTop === to) return;
scrollTo(element, to, duration - 10);
}, 10);
}
If you have a div with an id="footer"
<div id="footer" class="categories">…</div>
In the script that you run to scroll you can run this,
elmnt = document.getElementById("footer");
scrollTo(document.body, elmnt.offsetTop, 600);
And there you have it. Smooth scrolling without jQuery. You can actually play around with that code on your browser's console and fine tune it to your liking.

Using the function from here: JavaScript animation and modifying it to modify a property (not only a style's property), you can try something like this:
DEMO: http://jsfiddle.net/7TAa2/1/
Just saying...
function animate(elem, style, unit, from, to, time, prop) {
if (!elem) {
return;
}
var start = new Date().getTime(),
timer = setInterval(function() {
var step = Math.min(1, (new Date().getTime() - start) / time);
if (prop) {
elem[style] = (from + step * (to - from)) + unit;
} else {
elem.style[style] = (from + step * (to - from)) + unit;
}
if (step === 1) {
clearInterval(timer);
}
}, 25);
if (prop) {
elem[style] = from + unit;
} else {
elem.style[style] = from + unit;
}
}
window.onload = function() {
var target = document.getElementById("div5");
animate(document.scrollingElement || document.documentElement, "scrollTop", "", 0, target.offsetTop, 2000, true);
};
div {
height: 50px;
}
<div id="div1">asdf1</div>
<div id="div2">asdf2</div>
<div id="div3">asdf3</div>
<div id="div4">asdf4</div>
<div id="div5">asdf5</div>
<div id="div6">asdf6</div>
<div id="div7">asdf7</div>
<div id="div8">asdf8</div>
<div id="div9">asdf9</div>
<div id="div10">asdf10</div>
<div id="div10">asdf11</div>
<div id="div10">asdf12</div>
<div id="div10">asdf13</div>
<div id="div10">asdf14</div>
<div id="div10">asdf15</div>
<div id="div10">asdf16</div>
<div id="div10">asdf17</div>
<div id="div10">asdf18</div>
<div id="div10">asdf19</div>
<div id="div10">asdf20</div>

Actually, there is more lightweight and simple way to do that:
https://codepen.io/ugg0t/pen/mqBBBY
function scrollTo(element) {
window.scroll({
behavior: 'smooth',
left: 0,
top: element.offsetTop
});
}
document.getElementById("button").addEventListener('click', () => {
scrollTo(document.getElementById("8"));
});
div {
width: 100%;
height: 200px;
background-color: black;
}
div:nth-child(odd) {
background-color: white;
}
button {
position: absolute;
left: 10px;
top: 10px;
}
<div id="1"></div>
<div id="2"></div>
<div id="3"></div>
<div id="4"></div>
<div id="5"></div>
<div id="6"></div>
<div id="7"></div>
<div id="8"></div>
<div id="9"></div>
<div id="10"></div>
<button id="button">Button</button>

This is a pretty old question, but it's important to say that nowadays smooth scrolling is supported in CSS, so there's no need for any scripts:
html {
scroll-behavior: smooth;
}
As noted by #Andiih, as of late 2022 there is full browser support for this.

Use this:
let element = document.getElementById("box");
element.scrollIntoView();
element.scrollIntoView(false);
element.scrollIntoView({block: "end"});
element.scrollIntoView({behavior: "instant", block: "end", inline: "nearest"});
DEMO: https://jsfiddle.net/anderpo/x8ucc5ak/1/

Vanilla js variant using requestAnimationFrame with easings and all browsers supported:
const requestAnimationFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame;
function scrollTo(to) {
const start = window.scrollY || window.pageYOffset
const time = Date.now()
const duration = Math.abs(start - to) / 3;
(function step() {
var dx = Math.min(1, (Date.now() - time) / duration)
var pos = start + (to - start) * easeOutQuart(dx)
window.scrollTo(0, pos)
if (dx < 1) {
requestAnimationFrame(step)
}
})()
}
Any easing supported!

CSS3 transitions with a :target selector can give a nice result without any JS hacking. I was just contemplating whether to imlement this but without Jquery it does get a bit messy. See this question for details.

Try this code here:
window.scrollTo({
top: 0,
left: 0,
behavior: 'smooth'
});

Smooth Scroll behavior with polyfill...
Example:
document.querySelectorAll('a[href^="#"]').addEventListener("click", function(event) {
event.preventDefault();
document.querySelector(this.getAttribute("href")).scrollIntoView({ behavior: "smooth" });
});
Repository: https://github.com/iamdustan/smoothscroll

My favorite scroll-to library currently is Zenscroll because of the wide range of features and small size (currently only 3.17kb).
In the future it may make more sense to use the native scrollIntoView functionality, but since it'd have to be polyfilled in most production sites today due to the lack of IE support, I recommend using Zenscroll instead in all cases.

March 2022
I know this is an old question but wanted to put forward an answer that has simpler ways of doing it in modern days. As of today, almost all the major browsers are compatible with scroll-behavior including Safari with its latest release. Still, you might want to employ fallback methods or just use the javascript approach described in method 2 for compatibility in older browsers.
Method 1: HTML and CSS
You can just do this with
Click
.
.
.
<h2 id="target">Target</h2>
and CSS
html {
scroll-behavior: smooth
}
Method 2: JavaScript
Or if you have a unique case that needs javascript, go on elaborate with this method.
const scrollTrigger = document.getElementById('scroll-trigger');
const target = document.getElementById('target');
scrollTrigger.addEventListener('click', function (e) {
window.scroll({
top: target.offsetTop,
left:0,
behavior: 'smooth' });
}, false)

It's upgraded version from #Ian
// Animated scroll with pure JS
// duration constant in ms
const animationDuration = 600;
// scrollable layout
const layout = document.querySelector('main');
const fps = 12; // in ms per scroll step, less value - smoother animation
function scrollAnimate(elem, style, unit, from, to, time, prop) {
if (!elem) {
return;
}
var start = new Date().getTime(),
timer = setInterval(function () {
var step = Math.min(1, (new Date().getTime() - start) / time);
var value = (from + step * (to - from)) + unit;
if (prop) {
elem[style] = value;
} else {
elem.style[style] = value;
}
if (step === 1) {
clearInterval(timer);
}
}, fps);
if (prop) {
elem[style] = from + unit;
} else {
elem.style[style] = from + unit;
}
}
function scrollTo(hash) {
const target = document.getElementById(hash);
const from = window.location.hash.substring(1) || 'start';
const offsetFrom = document.getElementById(from).offsetTop;
const offsetTo = target.offsetTop;
scrollAnimate(layout,
"scrollTop", "", offsetFrom, offsetTo, animationDuration, true);
setTimeout(function () {
window.location.hash = hash;
}, animationDuration+25)
};
// add scroll when click on menu items
var menu_items = document.querySelectorAll('a.mdl-navigation__link');
menu_items.forEach(function (elem) {
elem.addEventListener("click",
function (e) {
e.preventDefault();
scrollTo(elem.getAttribute('href').substring(1));
});
});
// scroll when open link with anchor
window.onload = function () {
if (window.location.hash) {
var target = document.getElementById(window.location.hash.substring(1));
scrollAnimate(layout, "scrollTop", "", 0, target.offsetTop, animationDuration, true);
}
}

For anyone in 2019,
first, you add an event listener
document.getElementById('id').addEventListener('click', () => scrollTo())
then you target the element and go smoothly to it
function scrollTo() {
let target = document.getElementById('target');
target.scrollIntoView({
behavior: "smooth",
block: "end",
inline: "nearest"
})
}

Based on MDN docs for scroll options we can use the following code:
element.scrollTo({
top: 100,
left: 100,
behavior: 'smooth'
});
In fact, the behavior key can accept smooth and auto variables. first for smooth motion and second for a single jump.
‍‍

Here is a simple solution in pure JavaScript. It takes advantage of CSS property scroll-behavior: smooth
function scroll_to(id) {
document.documentElement.style.scrollBehavior = 'smooth'
element = document.createElement('a');
element.setAttribute('href', id)
element.click();
}
Usage:
Say we have 10 divs:
<div id='df7ds89' class='my_div'>ONE</div>
<div id='sdofo8f' class='my_div'>TWO</div>
<div id='34kj434' class='my_div'>THREE</div>
<div id='gbgfh98' class='my_div'>FOUR</div>
<div id='df89sdd' class='my_div'>FIVE</div>
<div id='34l3j3r' class='my_div'>SIX</div>
<div id='56j5453' class='my_div'>SEVEN</div>
<div id='75j6h4r' class='my_div'>EIGHT</div>
<div id='657kh54' class='my_div'>NINE</div>
<div id='43kjhjh' class='my_div'>TEN</div>
We can scroll to the ID of choice:
scroll_to('#657kh54')
You simply call this function on your click event (e.g. click button then scroll to div #9).
Result:
Of course it looks much smoother in real life.
FIDDLE
Unfortunately, IE and Safari don't support scrollBehavior = 'smooth' as of 2019
MDN Web Docs

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. 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);
}
});
}
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) {
var elem = document.querySelector("div");
scrollToSmoothly(elem.offsetTop);
});
document.getElementById("toTop").addEventListener('click', function(e){
scrollToSmoothly(0, 700);
});
<button id="toElement">Scroll To Element</button>
<div style="margin: 1000px 0px; text-align: center;">Div element
<button id="toTop">Scroll back to top</button>
</div>
For more complex cases, the SmoothScroll.js library can be used, which handles 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("toTop").addEventListener('click', function(e){
smoothScroll({yPos: 0, duration: 700});
});
<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="toTop">Scroll back to top</button>
</div>
Alternatively, you can pass an options object to window.scroll which scrolls to a specific x and y position and window.scrollBy which scrolls a certain amount from the current position:
// Scroll to specific values
// scrollTo is the same
window.scroll({
top: 2500,
left: 0,
behavior: 'smooth'
});
// Scroll certain amounts from current position
window.scrollBy({
top: 100, // could be negative value
left: 0,
behavior: 'smooth'
});
Demo:
<button onClick="scrollToDiv()">Scroll To Element</button>
<div style="margin: 500px 0px;">Div</div>
<script>
function scrollToDiv(){
var elem = document.querySelector("div");
window.scroll({
top: elem.offsetTop,
left: 0,
behavior: 'smooth'
});
}
</script>
Modern browsers support the scroll-behavior CSS property, which can be used to make scrolling in the document smooth (without the need for JavaScript). Anchor tags can be used for this by giving the anchor tag a href of # plus the id of the element to scroll to). You can also set the scroll-behavior property for a specific container like a div to make its contents scroll smoothly.
html, body{
scroll-behavior: smooth;
}
Scroll To Element
<div id="elem" style="margin: 500px 0px;">Div</div>

Without jQuery
const links = document.querySelectorAll('header nav ul a')
for (const link of links) {
link.onclick = function clickHandler(e) {
e.preventDefault()
const href = this.getAttribute('href')
document.querySelector(href).scrollIntoView({ behavior: 'smooth' })
}
}
body {
background-color: black;
height:7000px
}
header {
margin-top: 1.3rem;
margin-bottom: 25rem;
display: flex;
justify-content: center;
align-items: center;
}
nav ul {
display: flex;
}
nav ul li {
all: unset;
margin: 2rem;
cursor: pointer;
}
nav ul li a {
all: unset;
font: bold 1.8rem robto;
color: white;
letter-spacing: 1px;
cursor: pointer;
padding-top: 3rem;
padding-bottom: 2rem;
}
#team,
#contact,
#about {
background-color: #e2df0d;
width: 100%;
height: 35rem;
display: flex;
justify-content: center;
align-items: center;
color: black;
font: bold 4rem roboto;
letter-spacing: 6.2px;
margin-top: 70rem;
}
<header>
<!-- NavBar -->
<nav>
<ul>
<li>Team</li>
<li>Contact</li>
<li>About</li>
</ul>
</nav>
</header>
<!-- ----------- Team ----------------------- -->
<div id="team">
<h2>Team</h2>
</div>
<!-- ----------- Contact ----------------------- -->
<div id="contact">
<h2>Contact</h2>
</div>
<!-- ----------- About ----------------------- -->
<div id="about">
<h2>About</h2>
</div>
Or with just CSS, but it's not supported in all browsers yet
html {scroll-behavior: smooth}

If you want to set all of your deep links # to scroll smoothly you can do this:
const allLinks = document.querySelectorAll('a[href^="#"]')
allLinks.forEach(link => {
const
targetSelector = link.getAttribute('href'),
target = document.querySelector(targetSelector)
if (target) {
link.addEventListener('click', function(e) {
e.preventDefault()
const top = target.offsetTop // consider decreasing your main nav's height from this number
window.scroll({
behavior: 'smooth',
left: 0,
top: top
});
})
}
})
An example code to consider also your main nav's height (this code goes where top const is declared):
const
mainHeader = document.querySelector('header#masthead'), //change to your correct main nav selector
mainHeaderHeight = mainHeader.offsetHeight,
// now calculate top like this:
top = target.offsetTop - mainHeaderHeight

Here is the most elegant and concise solution.
Links:
CSS:
html {
scroll-behavior: smooth;
}
Remember to add a unique id="elementIDtoScrollTo" to each HTML element.

Related

Smooth horizontal wheel only scrolling

It is very annoing to hold shift when wheeling for horizontal scrolling.
There are some ways to horizontally scrool with wheel only but they directly copy wheel deltaY into scrollLeft which results in uncomfortable jump-scrolling.
Is there a mobile-friendly way to perform smooth horizontal scrolling on elements using wheel only? By "smooth" I mean something like default browser vertical wheel scroll behaviour.
Smooth scrolling can be achieved by using requestAnimationFrame.
You might want to play with denominator in getScrollStep function to adjust the smoothness of scrolling.
function horizontalWheel(container) {
/** Max `scrollLeft` value */
let scrollWidth;
/** Desired scroll distance per animation frame */
let getScrollStep = () => scrollWidth / 50 /* ADJUST TO YOUR WISH */ ;
/** Target value for `scrollLeft` */
let targetLeft;
function scrollLeft() {
let beforeLeft = container.scrollLeft;
let wantDx = getScrollStep();
let diff = targetLeft - container.scrollLeft;
let dX = wantDx >= Math.abs(diff) ? diff : Math.sign(diff) * wantDx;
// Performing horizontal scroll
container.scrollBy(dX, 0);
// Break if smaller `diff` instead of `wantDx` was used
if (dX === diff)
return;
// Break if can't scroll anymore or target reached
if (beforeLeft === container.scrollLeft || container.scrollLeft === targetLeft)
return;
requestAnimationFrame(scrollLeft);
}
container.addEventListener('wheel', e => {
e.preventDefault();
scrollWidth = container.scrollWidth - container.clientWidth;
targetLeft = Math.min(scrollWidth, Math.max(0, container.scrollLeft + e.deltaY));
requestAnimationFrame(scrollLeft);
});
}
Just pass elements you want to horizontally scroll with wheel in this function:
let list = document.querySelector('.hList');
horizontalWheel(list);
Example:
function horizontalWheel(container) {
/** Max `scrollLeft` value */
let scrollWidth;
/** Desired scroll distance per animation frame */
let getScrollStep = () => scrollWidth / 50 /* ADJUST TO YOUR WISH */ ;
/** Target value for `scrollLeft` */
let targetLeft;
function scrollLeft() {
let beforeLeft = container.scrollLeft;
let wantDx = getScrollStep();
let diff = targetLeft - container.scrollLeft;
let dX = wantDx >= Math.abs(diff) ? diff : Math.sign(diff) * wantDx;
// Performing horizontal scroll
container.scrollBy(dX, 0);
// Break if smaller `diff` instead of `wantDx` was used
if (dX === diff)
return;
// Break if can't scroll anymore or target reached
if (beforeLeft === container.scrollLeft || container.scrollLeft === targetLeft)
return;
requestAnimationFrame(scrollLeft);
}
container.addEventListener('wheel', e => {
e.preventDefault();
scrollWidth = container.scrollWidth - container.clientWidth;
targetLeft = Math.min(scrollWidth, Math.max(0, container.scrollLeft + e.deltaY));
requestAnimationFrame(scrollLeft);
});
}
//
// Usage
//
window.addEventListener('load', () => {
let list = document.querySelector('.hList');
horizontalWheel(list);
});
.hList {
width: 300px;
border: 2px solid red;
display: flex;
overflow: auto;
}
.element {
display: flex;
align-items: center;
justify-content: center;
color: white;
font-family: sans-serif;
flex-shrink: 0;
width: 150px;
height: 75px;
background: green;
border-right: 2px solid yellow;
}
.element:last-of-type {
border: none;
}
<div class="hList">
<div class="element">Element 1</div>
<div class="element">Element 2</div>
<div class="element">Element 3</div>
<div class="element">Element 4</div>
<div class="element">Element 5</div>
</div>

Add and Remove class on window scroll [duplicate]

So basically I'd like to remove the class from 'header' after the user scrolls down a little and add another class to change it's look.
Trying to figure out the simplest way of doing this but I can't make it work.
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll <= 500) {
$(".clearheader").removeClass("clearHeader").addClass("darkHeader");
}
}
CSS
.clearHeader{
height: 200px;
background-color: rgba(107,107,107,0.66);
position: fixed;
top:200;
width: 100%;
}
.darkHeader { height: 100px; }
.wrapper {
height:2000px;
}
HTML
<header class="clearHeader"> </header>
<div class="wrapper"> </div>
I'm sure I'm doing something very elementary wrong.
$(window).scroll(function() {
var scroll = $(window).scrollTop();
//>=, not <=
if (scroll >= 500) {
//clearHeader, not clearheader - caps H
$(".clearHeader").addClass("darkHeader");
}
}); //missing );
Fiddle
Also, by removing the clearHeader class, you're removing the position:fixed; from the element as well as the ability of re-selecting it through the $(".clearHeader") selector. I'd suggest not removing that class and adding a new CSS class on top of it for styling purposes.
And if you want to "reset" the class addition when the users scrolls back up:
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 500) {
$(".clearHeader").addClass("darkHeader");
} else {
$(".clearHeader").removeClass("darkHeader");
}
});
Fiddle
edit: Here's version caching the header selector - better performance as it won't query the DOM every time you scroll and you can safely remove/add any class to the header element without losing the reference:
$(function() {
//caches a jQuery object containing the header element
var header = $(".clearHeader");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 500) {
header.removeClass('clearHeader').addClass("darkHeader");
} else {
header.removeClass("darkHeader").addClass('clearHeader');
}
});
});
Fiddle
Pure javascript
Here's javascript-only example of handling classes during scrolling.
const navbar = document.getElementById('navbar')
// OnScroll event handler
const onScroll = () => {
// Get scroll value
const scroll = document.documentElement.scrollTop
// If scroll value is more than 0 - add class
if (scroll > 0) {
navbar.classList.add("scrolled");
} else {
navbar.classList.remove("scrolled")
}
}
// Use the function
window.addEventListener('scroll', onScroll)
#navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
height: 60px;
background-color: #89d0f7;
box-shadow: 0px 5px 0px rgba(0, 0, 0, 0);
transition: box-shadow 500ms;
}
#navbar.scrolled {
box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.25);
}
#content {
height: 3000px;
margin-top: 60px;
}
<!-- Optional - lodash library, used for throttlin onScroll handler-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
<header id="navbar"></header>
<div id="content"></div>
Some improvements
You'd probably want to throttle handling scroll events, more so as handler logic gets more complex, in that case throttle from lodash lib comes in handy.
And if you're doing spa, keep in mind that you need to clear event listeners with removeEventListener once they're not needed (eg during onDestroy lifecycle hook of your component, like destroyed() for Vue, or maybe return function of useEffect hook for React).
Example throttling with lodash:
// Throttling onScroll handler at 100ms with lodash
const throttledOnScroll = _.throttle(onScroll, 100, {})
// Use
window.addEventListener('scroll', throttledOnScroll)
Add some transition effect to it if you like:
http://jsbin.com/boreme/17/edit?html,css,js
.clearHeader {
height:50px;
background:lightblue;
position:fixed;
top:0;
left:0;
width:100%;
-webkit-transition: background 2s; /* For Safari 3.1 to 6.0 */
transition: background 2s;
}
.clearHeader.darkHeader {
background:#000;
}
Its my code
jQuery(document).ready(function(e) {
var WindowHeight = jQuery(window).height();
var load_element = 0;
//position of element
var scroll_position = jQuery('.product-bottom').offset().top;
var screen_height = jQuery(window).height();
var activation_offset = 0;
var max_scroll_height = jQuery('body').height() + screen_height;
var scroll_activation_point = scroll_position - (screen_height * activation_offset);
jQuery(window).on('scroll', function(e) {
var y_scroll_pos = window.pageYOffset;
var element_in_view = y_scroll_pos > scroll_activation_point;
var has_reached_bottom_of_page = max_scroll_height <= y_scroll_pos && !element_in_view;
if (element_in_view || has_reached_bottom_of_page) {
jQuery('.product-bottom').addClass("change");
} else {
jQuery('.product-bottom').removeClass("change");
}
});
});
Its working Fine
Is this value intended? if (scroll <= 500) { ... This means it's happening from 0 to 500, and not 500 and greater. In the original post you said "after the user scrolls down a little"
In a similar case, I wanted to avoid always calling addClass or removeClass due to performance issues. I've split the scroll handler function into two individual functions, used according to the current state. I also added a debounce functionality according to this article: https://developers.google.com/web/fundamentals/performance/rendering/debounce-your-input-handlers
var $header = jQuery( ".clearHeader" );
var appScroll = appScrollForward;
var appScrollPosition = 0;
var scheduledAnimationFrame = false;
function appScrollReverse() {
scheduledAnimationFrame = false;
if ( appScrollPosition > 500 )
return;
$header.removeClass( "darkHeader" );
appScroll = appScrollForward;
}
function appScrollForward() {
scheduledAnimationFrame = false;
if ( appScrollPosition < 500 )
return;
$header.addClass( "darkHeader" );
appScroll = appScrollReverse;
}
function appScrollHandler() {
appScrollPosition = window.pageYOffset;
if ( scheduledAnimationFrame )
return;
scheduledAnimationFrame = true;
requestAnimationFrame( appScroll );
}
jQuery( window ).scroll( appScrollHandler );
Maybe someone finds this helpful.
For Android mobile $(window).scroll(function() and $(document).scroll(function() may or may not work. So instead use the following.
jQuery(document.body).scroll(function() {
var scroll = jQuery(document.body).scrollTop();
if (scroll >= 300) {
//alert();
header.addClass("sticky");
} else {
header.removeClass('sticky');
}
});
This code worked for me. Hope it will help you.
This is based of of #shahzad-yousuf's answer, but I only needed to compress a menu when the user scrolled down. I used the reference point of the top container rolling "off screen" to initiate the "squish"
<script type="text/javascript">
$(document).ready(function (e) {
//position of element
var scroll_position = $('div.mainContainer').offset().top;
var scroll_activation_point = scroll_position;
$(window).on('scroll', function (e) {
var y_scroll_pos = window.pageYOffset;
var element_in_view = scroll_activation_point < y_scroll_pos;
if (element_in_view) {
$('body').addClass("toolbar-compressed ");
$('div.toolbar').addClass("toolbar-compressed ");
} else {
$('body').removeClass("toolbar-compressed ");
$('div.toolbar').removeClass("toolbar-compressed ");
}
});
}); </script>

How to smoothly scroll to an element in pure JavaScript

I want to smoothly scroll to an element without using jQuery – just pure javascript. I would like a generic function to be able to both scroll down and scroll up smoothly to a specific position in the document.
I know I can use the following in jQuery:
$('html, body').animate({
scrollTop: $('#myelementid').offset().top
}, 500);
How would I do it with just javascript?
This is what I am trying to do:
function scrollToHalf(){
//what do I do?
}
function scrollToSection(){
//What should I do here?
}
<input type="button" onClick="scrollToHalf()" value="Scroll To 50% of Page">
<br>
<input type="button" onClick="scrollToSection()" value="Scroll To Section1">
<section style="margin-top: 1000px;" id="section1">
This is a section
</section>
In jquery I would do it like so:
html, body{
height: 3000px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="button" onClick="scrollToHalf()" value="Scroll To 50% of Page">
<br>
<input type="button" onClick="scrollToSection()" value="Scroll To Section1">
<section style="margin-top: 1000px;" id="section1">
This is a section
</section>
<script>
function scrollToHalf(){
var height = $('body').height();
$('html, body').animate({
scrollTop: height/2
}, 500);
}
function scrollToSection(){
$('html, body').animate({
scrollTop: $('#section1').offset().top
}, 500);
}
</script>
EDIT: I would also like to be able to smooth scroll to a certain position on the page
EDIT: CSS solutions are also welcome (although I would prefer javascript solutions)
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. 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);
}
});
}
Demo:
/*
#param time: the exact amount of time the scrolling will take (in milliseconds)
#param pos: the y-position to scroll to (in pixels)
*/
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);
}
});
}
<button onClick="scrollToSmoothly(document.querySelector('div').offsetTop, 300)">
Scroll To Div (300ms)
</button>
<button onClick="scrollToSmoothly(document.querySelector('div').offsetTop, 200)">
Scroll To Div (200ms)
</button>
<button onClick="scrollToSmoothly(document.querySelector('div').offsetTop, 100)">
Scroll To Div (100ms)
</button>
<button onClick="scrollToSmoothly(document.querySelector('div').offsetTop, 50)">
Scroll To Div (50ms)
</button>
<button onClick="scrollToSmoothly(document.querySelector('div').offsetTop, 1000)">
Scroll To Div (1000ms)
</button>
<div style="margin: 500px 0px;">
DIV<p/>
<button onClick="scrollToSmoothly(0, 500)">
Back To Top
</button>
<button onClick="scrollToSmoothly(document.body.scrollHeight)">
Scroll To Bottom
</button>
</div>
<div style="margin: 500px 0px;">
</div>
<button style="margin-top: 100px;" onClick="scrollToSmoothly(500, 3000)">
Scroll To y-position 500px (3000ms)
</button>
For more complex cases, the SmoothScroll.js library can be used, which handles smooth scrolling both vertically and horizontally, scrolling inside other container elements, different easing behaviors, scrolling relatively from the current position, and more.
var easings = document.getElementById("easings");
for(var key in smoothScroll.easing){
if(smoothScroll.easing.hasOwnProperty(key)){
var option = document.createElement('option');
option.text = option.value = key;
easings.add(option);
}
}
document.getElementById('to-bottom').addEventListener('click', function(e){
smoothScroll({yPos: 'end', easing: easings.value, duration: 2000});
});
document.getElementById('to-top').addEventListener('click', function(e){
smoothScroll({yPos: 'start', easing: easings.value, duration: 2000});
});
<script src="https://cdn.jsdelivr.net/gh/LieutenantPeacock/SmoothScroll#1.2.0/src/smoothscroll.min.js" integrity="sha384-UdJHYJK9eDBy7vML0TvJGlCpvrJhCuOPGTc7tHbA+jHEgCgjWpPbmMvmd/2bzdXU" crossorigin="anonymous"></script>
<!-- Taken from one of the library examples -->
Easing: <select id="easings"></select>
<button id="to-bottom">Scroll To Bottom</button>
<br>
<button id="to-top" style="margin-top: 5000px;">Scroll To Top</button>
Alternatively, you can pass an options object to window.scroll which scrolls to a specific x and y position and window.scrollBy which scrolls a certain amount from the current position:
// Scroll to specific values
// scrollTo is the same
window.scroll({
top: 2500,
left: 0,
behavior: 'smooth'
});
// Scroll certain amounts from current position
window.scrollBy({
top: 100, // could be negative value
left: 0,
behavior: 'smooth'
});
Demo:
<button onClick="scrollToDiv()">Scroll To Element</button>
<div style="margin: 500px 0px;">Div</div>
<script>
function scrollToDiv(){
var elem = document.querySelector("div");
window.scroll({
top: elem.offsetTop,
left: 0,
behavior: 'smooth'
});
}
</script>
If you only need to scroll to an element, not a specific position in the document, you can use Element.scrollIntoView with behavior set to smooth.
document.getElementById("elemID").scrollIntoView({
behavior: 'smooth'
});
Demo:
<button onClick="scrollToDiv()">Scroll To Element</button>
<div id="myDiv" style="margin: 500px 0px;">Div</div>
<script>
function scrollToDiv(){
document.getElementById("myDiv").scrollIntoView({
behavior: 'smooth'
});
}
</script>
Modern browsers support the scroll-behavior CSS property, which can be used to make scrolling in the document smooth (without the need for JavaScript). Anchor tags can be used for this by giving the anchor tag a href of # plus the id of the element to scroll to). You can also set the scroll-behavior property for a specific container like a div to make its contents scroll smoothly.
Demo:
html, body{
scroll-behavior: smooth;
}
a, a:visited{
color: initial;
}
Scroll To Element
<div id="elem" style="margin: 500px 0px;">Div</div>
The CSS scroll-behavior property works with JavaScript as well when using window.scrollTo.
Demo:
html, body{
scroll-behavior: smooth;
}
<button onClick="scrollToDiv()">Scroll To Element</button>
<div style="margin: 500px 0px;">Div</div>
<script>
function scrollToDiv(){
var elem = document.querySelector("div");
window.scrollTo(0, elem.offsetTop);
}
</script>
To check if the scroll-behavior property is supported, you can check if it exists as a key in the style of the HTML element.
var scrollBehaviorSupported = 'scroll-behavior' in document.documentElement.style;
console.log('scroll-behavior supported:', scrollBehaviorSupported);
Consider using Element.scrollIntoView().
As I mentioned in my comment, scrollIntoView is a good option to consider – that gets greater and greater browser support – when you try to scroll to a specified element such as what you are apparently trying to do with your scrollToSection function.
To scroll to the middle of the page you can set the scrollTop property of the body and/or the html element to half the difference of the scrollHeight of the body and the innerHeight of the window. Couple the above calculation with requestAnimationFrame and you are set.
Here's how you can incorporate the above suggestions in your code:
function scrollToHalf(duration) {
var
heightDiff = document.body.scrollHeight - window.innerHeight,
endValue = heightDiff / 2,
start = null;
/* Set a default for the duration, in case it's not given. */
duration = duration || 300;
/* Start the animation. */
window.requestAnimationFrame(function step (now) {
/* Normalise the start date and calculate the current progress. */
start = !start ? now : start;
var progress = now - start;
/* Increment by a calculate step the value of the scroll top. */
document.documentElement.scrollTop = endValue * progress / duration;
document.body.scrollTop = endValue * progress / duration;
/* Check whether the current progress is less than the given duration. */
if (progress < duration) {
/* Execute the function recursively. */
window.requestAnimationFrame(step);
}
else {
/* Set the scroll top to the end value. */
document.documentElement.scrollTop = endValue;
document.body.scrollTop = endValue;
}
});
}
function scrollToSection(element) {
/* Scroll until the button's next sibling comes into view. */
element.nextElementSibling.scrollIntoView({block: "start", behavior: "smooth"});
}
#section1 {
margin: 1000px 0;
border: 1px solid red
}
<input type="button" onClick="scrollToHalf()" value="Scroll To 50% of Page">
<br>
<input type="button" onClick="scrollToSection(this)" value="Scroll To Section1">
<section id="section1">
This is a section
</section>
You can literally scroll any node object you want, with a simple polyfill like this:
Node.prototype.scroll = window.scroll
it will give you same access to scroll objects, but with any DOM element, you can use it like:
document.querySelector('.scrollable-div').scroll({
top: 500,
left: 0,
behavior: 'smooth'
});
Use this CSS property you switch scroll behavior to be smooth.
html {
scroll-behavior: smooth;
}
This will also scroll smoothly default html navigation by hash <a href="#about"> to <section id="about">, and no js required here.
If you want to add own logic to scrolling consider this example
https://jsfiddle.net/arsenlol/Ls3f2ujq/54/
here I am scrolling not directly to a scroll target element but 90px higher consdering fixed header height.
TL;DR
document.querySelectorAll("nav a").forEach(function (a) {
a.addEventListener("click", function (event) {
event.preventDefault();
const hash = event.target.getAttribute("href");
const scrollTarget = document.querySelector(hash);
// Some additional logic
const headerHeight = 90;
window.scrollTo(0, scrollTarget.offsetTop - headerHeight);
});
});
There are a lot of answers to this question already, but I thought I might share what I use.
The following allows you to smooth scroll to any position on the page, downwards or upwards, within a specified amount of time. I'm not sure if it's compatible with every browser, but I'm pretty sure it is. (Someone correct me if I'm wrong.)
Important Edit: Make sure you don't have html {scroll-behavior: smooth;} in your CSS. Otherwise, this won't work.
function scrollToInTime(element, duration) {
const endPoint = document.querySelector(element).offsetTop,
distance = endPoint - window.pageYOffset,
rate = (distance * 4) / duration, // px/4ms
interval = setInterval(scrollIncrement, 4) //4ms is minimum interval for browser
function scrollIncrement() {
const yOffset = Math.ceil(window.pageYOffset)
if (
(yOffset >= endPoint && rate >= 0) ||
(yOffset <= endPoint && rate <= 0)
) {
clearInterval(interval)
} else {
//keep in mind that scrollBy doesn't work with decimal pixels < 1 like 0.4px, so
//if duration is too big, function won't work. rate must end up being >= 1px
window.scrollBy(0, rate)
}
}
}
Here's a codepen as an example: https://codepen.io/isaac-svi/pen/xxZgPZp?editors=0110

Firefox adds undesired thin line above a logo animated using JavaScript

Well it seems that I'm having some sort of a problem with Firefox, I've added a logo to my website and styled it through this CSS block:
#splash div.logo > a {
background-image: url("../../---.png");
background-size: 280px;
height: 85px;
width: 280px;
}
When I open the web page with Chrome or any other browser other than Firefox it displays it in the right way,unless I zoomed in it will show a thin line,
while opening the web page from Firefox will show a thin line above the image with or without zooming in.
The Logo is animated through this code:
IndexPage: {
Splash: {
init: function() {
var $splash = $('#splash'),
$logo = $splash.find('#logo'),
frame = 1,
frameCount = 46
framesPerSecond = 50;
function animateLogo() {
var lastTime = 0;
var currTime = new Date().getTime();
// var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var timeToCall = 25;
if (typeof requestAnimationFrame == "undefined")
requestAnimationFrame = function (callback, element) {
return setTimeout(function () { callback(currTime + timeToCall); }, timeToCall);
};
if (frame <= frameCount) {
setTimeout(function() {
requestAnimationFrame(animateLogo, $logo);
$logo.css('background-position', '0 -' + (frame * 85) + 'px');
frame += 1;
}, timeToCall);
// lastTime = currTime + timeToCall;
}
}
$('form.search').on({
close: function() { $splash.removeClass('searching'); },
open: function() { $splash.addClass('searching'); }
});
if ($window.width() >= 532) {
$window.scroll(function() {
var top = $window.scrollTop();
$splash.find('div.logo').css('opacity', top > 150 ? 0 : (150 - top) / 150);
});
}
$window.resize(function() {
if ($splash.width() < 768) {
$logo.css('background-position', '0 0');
} else {
$logo.css('background-position', '0 -3910px');
}
});
if ($window.width() >= 768)
animateLogo();
}
}
}
Any Ideas?
It looks like Firefox does some extrapolation of your image before rendering it (for perf I guess). It calculate the pixel to display using the neighbourhood of the one on your image, and some pixels on the top of your image are near black pixel resulting in a black/grey line.
EDIT: You can disable this behavior using image-rendering: optimizequality; in your CSS.
Snippet to test this:
var frame = 1,
frameCount = 46;
function animateLogo() {
$logo=$('.logo');
var lastTime = 0;
var currTime = new Date().getTime();
var timeToCall = 25;
if (typeof requestAnimationFrame == "undefined") {
requestAnimationFrame = function (callback, element) {
return setTimeout(function () {
callback(currTime + timeToCall);
}, timeToCall);
}
}
if (frame <= frameCount) {
setTimeout(function() {
requestAnimationFrame(animateLogo, $logo);
$logo.css('background-position', '0 -' + (frame * 85) + 'px');
frame += 1;
}, timeToCall);
}
}
.logo {
background-image: url('data:image/png;base64,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CAgICAgICAgICAgICAgICAgICAgICAgICAgIiDiIN841BAQEBAQEBMQrZlq6yX0TdyAgICAgICAqQbQFD4OAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiIJoICAgICAgnLEhIMaF+BcEBASEQywEBAQEBAQEBAQEBATEDhANBAQEBAQEBATEuBCW4hAQEBAQEBCBEMfHv9aPiD0QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBCvQbx9OggICAgICAiI0ine3pPASycICAgICAiIOhCXZQssCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiASIn5SAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMiKCD4QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEPEQPzQ9BAQEBAQEBETRzEo39izwyulLKeI8MEIJJZRQQgklRlDiquBRk+glChFKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEs0kQ4mJEkFKvHd0cnRSQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgklmupnlgGhhBJKKKHEjku8y1DinRJKODo5TyihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoosVHiR6ePUCIBQgkllFBCCSWSl3hXvKnzuCsnCAgICAgIiEoQFwUP+wwBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAZEN8eH4uKkeEXsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiI7YwLQQEBAQEBATEd+Zz6WZ2gZdOP2dAKKGEEkooocQYSpQtsIKXKHjUeyWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEKJUZeYZygxz1DipKDE6enfYpdom9rn5wwIJZRQQgkllBhDiZMMJU4ylJhnKDHPUKLJUKJRQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZSIU2Ir0x24RP0IJZRQQgkllMhe4mvpRraBl04QEBAQEBAQdSD6gkcdQUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQGRAXGdAlGxefMRlBsR1BkTB9kFAQCREBB8ICAgICIgRIK4hgiCuICC2h+ghICAgHGIhsiOsYl0UQUBAQEBAQEBAHAgxT4C4ahIgXvrBhn+uBXGSAPHis6kWRJ8e0UBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBUhtjazCEgICAgICAgnp1p6QZGXmBBQEBAQEBAVIJoCx4GAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQExRkQDAbFfROyBgIB408kOAgICAgICAgICAgLClR0EBAQEBAQEBIS74hAQEBAQEBAQEBAQEBAQe0L8kgHReTpBQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA7BmxxTmDgICAgICAgHhmZqWbF/k7kEBAQEBAQEBUgih41AQCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmLEiOADAQEBAQEBAbE/xKcMiBYCAgICAgICAmJciLnrCQgICAgICAgICAgICAgICAgIiLyIHgICAgICAgICYlwIS3EICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiF0gtjpXGRDXSiihhBJKKKHE9qd4404CL50gICAgICAg6kBcFjxqCgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBARER8eH4uKkeEXwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIJIitj7nEBAQEBAQEBAbMy3dsIvAK6dixGUGhBJKKKGEEkpUXGJe/X2dG8RJEUIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEKJvZU4Pv61/hKxp7BEeIQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihxIEQO5geAgICAgICAuLRfCndrLPASycICAgICAiIOhBXBY/6CAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQGRBfH+9PSkekTwgYCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIBIixggILaHuLZjQ0BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQBwasaNpISAgICAgICDW5mPpJvWBV05HpYjIq0QllFBCCSWUGEOJkjXOl+glyhBKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSoUv85b//qb9E7DnKgFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQImWJJkOJRgkllFBCCSWUUEIJJZRQQgkllFBiWaLNUKJVQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBiBCV2Nt0eS9SPUEIJJZRQQonsJb6WblDkBRYEBAQEBAREHYi+/ptTEBAQEBAQEBAQEBAQELUPBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBMS+EFdKKKEEBAQEBAQEBAQEBAQEhGvsaIgBAgICAgLiJUSrBAQEBASEy1MICAgICAgICAgICAgI19gQEBAQENUifP0EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAREBYhdTg8BAQEBAQEBcTuT4s0JvHKCgICAgICAqATRFTxsBgEBAQGxK0TsgYCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgFhD9BAQ9gkICAgIiP0gLpSAgICAgICAgICAgICAODyihYCAgICAgICAgICAgICAgICAgICAgICAgICAgIDIgvBiPAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBATEC4gdTwsBAQEBAQEBcTPT0k2J/FPKICAgICAgICpBtE3tAwEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQHxOsTO5woCAgICAgICoinaiC740gkCAgICAgKiDsRl9TdsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBeh9jLzCEgICAgICBGjph8/9134VdOEBAQEBAQEJUgzqq/YXODOM+AUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEKJEZbwdIqC6DIg+gyI6wyIAQICIt/RCQICIiEixQLQlZ0SSiihhBJKKKGEEkocBNFCQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQGwgOggICAgICAgIiHEhzjMgfIayEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJLxJ7mIgPiUgkllFBCCSWUeOt8+c57bmtYOkFAQEBAQEDUgbiq/oYNBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBER4RA8BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAbFnhFeKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIL6D2N9cQ0BAQEBAQIwX8e7Fd9rWsXKCgICAgICAqATRVX/D5gZxkQGhhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhBJKKKGEEkrsC7HX6SAgICAgICBGijh6/t211SydICAgICAgICpB1LOxEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEPERRxkQ//R0goCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuEOcQ0BAODpBQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEDkRex7ICAgICAgIEaJ2N9Ha4cDAQEBAQEBUQeir/6GDQQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBMQhEYMSEBAQEBDZER0EBAQEBAQEBAQExCEQLQQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAREToRPUIGAgICAgICAgKgV8VPdiB4CYtuIBgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiLJTyrf/7QQEBAQEBAQo0NMnnwfla2cICAgICAgICpB1P9tACEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgqkDMlYCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIgzjI9BAQEBAQEBAjQ0w333x9SycICAgICAiIShAn1d+xgYCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNgCooWAgMiHOMuAOM+A6CAgIB4gLiAgICBc2UFAQEBAQEBAQEBsBdG6ngiC6JUIgji3Y0M4T0BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEC8GnGoaSEgICAgICDGhHj0duv8Hm4QEBAQEBAQdSDq/0arN4jLDAgllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgkllFBCCSWUUEIJJZRQQgklnkZcZ0AMEBAQzhNKKKGEEkoooYQSSiihhBKpSvQQEBD5EM4TSiihhBJKKKGEEkoooYQSSiihRC6E+04Q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ICAgICAgICAgICAgICAgICB2gggzHQQEBAQEBERyhAUgBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQExE4QYaaDgICAgICASI6wAISAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDYCSLMdBAQEBAQEBDJERaAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEDtBhJkOAgICAgICIjnCAhACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJiJ4gw00FAQEBAQEAkR1gAQkBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQOwEEWY6CAgICAgIiOQIC0AICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiInSDCTAcBAQEBAQGRHGEBCAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAbETRJjpICAgICAgIDIjpsPQVr92goCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4n6F//JgWAuJViMX39ekzIG43v3bE4g/VI7oMiAHi8Iib/82ePH9Xhmie/O5ptSFmGRDTx/tDjYgJRBjE8AJideyaPvW4KIjFL99qzG7/elFmunYqaZf/KpLiOcT09jC1+OUOMV1b565+Gxlxt3MsgtwhZssz+vK7goZH3J/87veJyWqZO60WMV0tc2e1IBZPpNsn1S1isa4a7oCLXT8+4m6X7u4Rw+1fDPeH2lno88QCMbn9aK8j7h92u9NPQp+x1xHtErF2uJoEOrq+jLh9Yg3NCtEtfz+J9tMenlrF3n/M7z7k07WTxbe9JDpisRO8hJhUgBhWiJuP+XT1FFoeUStA3F5j3x18hn62fAqtEM0CEXfHvl9WrK3ymk1EXwGieQ7R3yOaaK9pvHAHcLZcbU/X8twh+tCIdoWYLu/f3CKW06/xYiLW74pPVtdxm4hQihden3geMfmhn1Gw+1XsQ0TzNKIZYl9jF5W4vUDqakA82rEf7ASz0DcKmgeH2GcRC0UliP5ZxDOvAoRDPDxjbzx7qkDcrJCGtQXgxrNnVgPiZh3+1Cp27V92VSCeuJ5YzaQGxKMru41nTxWIm7944vK0NkT/4G7Hxi5QA+LxfaeNV/NqQDy+jXm/HGzvbv3VcHSarZ5Dy9uYt8fbG0RXy3li4674cPcsaxf/1XHG3nh9YrEeXCzPF/+bVrAA3Hy5a3p/FT4Zgr/IskJ0jxCTx4j41xNPvHp6/yLX5Ad/EODeEE+8jj1d3Ziq5Bp7+cdvvy5XHLMHr2NHvNtRMqv9INZP1fYJ7xAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBABEWGmhYCAgICAgEiG+D/PDx7oyy0cAgAAAABJRU5ErkJggg==');
background-size: 280px;
height: 85px;
width: 280px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="logo"></div>
<button onclick="frame=0;$('.logo').css('image-rendering','auto');animateLogo()">Without CSS property (default)</button>
<button onclick="frame=0;$('.logo').css('image-rendering','optimizeQuality');animateLogo()">With CSS property</button>
Old answer:
You can separate sprites on your image by a few transparent pixels (or of the color of what is behind your logo) so the effect would not be visible anymore.
Well, if all else fails, you could always attempt to place a div over the thin line. Also try adding a border attribute to your code and set it to 0px solid whatever your background-color is. If all of these don't work, then try adding another border over the red line.
Try loading the image as is in the browser and check if the line is still placed. Also, in Firefox, right-click, choose inspect and see where it points to. For example, the line might be coming from div or some other html element.
i think creating an empty 'content' and using a background to show the image: works nicely in Chrome, Firefox, Safari and IE8+9
.googlePic:before {
content: '';
background: url('../../img/googlePlusIcon.PNG');
margin-top: -6.5%;
padding-right: 53px;
float:right;
height: 19px;
}
you could try if this would fix the issue
I think it just renders the size of image or block incorrectly, I played on your website with the CSS and and it seems that if you change background size to
background-size: 279.8px auto;
it solves the issue.
UPDATE:
As an additional solution, you might wrap the logo in a div, give the div hidden overflow, and then lift the block with your image up to 1px. It will hide the line as well.
Try like this:
#match div.logo > a {
background-image: url("../../---.png");
background-size: 280px;
height: 85px;
width: 280px;
outline: 0;
}

Smooth scroll without the use of jQuery

I'm coding up a page where I only want to use raw JavaScript code for UI without any interference of plugins or frameworks.
And now I'm struggling with finding a way to scroll over the page smoothly without jQuery.
Native browser smooth scrolling in JavaScript is like this:
// scroll to specific values,
// same as window.scroll() method.
// for scrolling a particular distance, use window.scrollBy().
window.scroll({
top: 2500,
left: 0,
behavior: 'smooth'
});
// scroll certain amounts from current position
window.scrollBy({
top: 100, // negative value acceptable
left: 0,
behavior: 'smooth'
});
// scroll to a certain element
document.querySelector('.hello').scrollIntoView({
behavior: 'smooth'
});
Try this smooth scrolling demo, or an algorithm like:
Get the current top location using self.pageYOffset
Get the position of element till where you want to scroll to: element.offsetTop
Do a for loop to reach there, which will be quite fast or use a timer to do smooth scroll till that position using window.scrollTo
See also the other popular answer to this question.
Andrew Johnson's original code:
function currentYPosition() {
// Firefox, Chrome, Opera, Safari
if (self.pageYOffset) return self.pageYOffset;
// Internet Explorer 6 - standards mode
if (document.documentElement && document.documentElement.scrollTop)
return document.documentElement.scrollTop;
// Internet Explorer 6, 7 and 8
if (document.body.scrollTop) return document.body.scrollTop;
return 0;
}
function elmYPosition(eID) {
var elm = document.getElementById(eID);
var y = elm.offsetTop;
var node = elm;
while (node.offsetParent && node.offsetParent != document.body) {
node = node.offsetParent;
y += node.offsetTop;
} return y;
}
function smoothScroll(eID) {
var startY = currentYPosition();
var stopY = elmYPosition(eID);
var distance = stopY > startY ? stopY - startY : startY - stopY;
if (distance < 100) {
scrollTo(0, stopY); return;
}
var speed = Math.round(distance / 100);
if (speed >= 20) speed = 20;
var step = Math.round(distance / 25);
var leapY = stopY > startY ? startY + step : startY - step;
var timer = 0;
if (stopY > startY) {
for ( var i=startY; i<stopY; i+=step ) {
setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
leapY += step; if (leapY > stopY) leapY = stopY; timer++;
} return;
}
for ( var i=startY; i>stopY; i-=step ) {
setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
leapY -= step; if (leapY < stopY) leapY = stopY; timer++;
}
}
Related links:
https://www.sitepoint.com/smooth-scrolling-vanilla-javascript/
https://github.com/zengabor/zenscroll/blob/dist/zenscroll.js
https://github.com/cferdinandi/smooth-scroll/blob/master/src/js/smooth-scroll.js
https://github.com/alicelieutier/smoothScroll/blob/master/smoothscroll.js
Algorithm
Scrolling an element requires changing its scrollTop value over time. For a given point in time, calculate a new scrollTop value. To animate smoothly, interpolate using a smooth-step algorithm.
Calculate scrollTop as follows:
var point = smooth_step(start_time, end_time, now);
var scrollTop = Math.round(start_top + (distance * point));
Where:
start_time is the time the animation started;
end_time is when the animation will end (start_time + duration);
start_top is the scrollTop value at the beginning; and
distance is the difference between the desired end value and the start value (target - start_top).
A robust solution should detect when animating is interrupted, and more. Read my post about Smooth Scrolling without jQuery for details.
Demo
See the JSFiddle.
Implementation
The code:
/**
Smoothly scroll element to the given target (element.scrollTop)
for the given duration
Returns a promise that's fulfilled when done, or rejected if
interrupted
*/
var smooth_scroll_to = function(element, target, duration) {
target = Math.round(target);
duration = Math.round(duration);
if (duration < 0) {
return Promise.reject("bad duration");
}
if (duration === 0) {
element.scrollTop = target;
return Promise.resolve();
}
var start_time = Date.now();
var end_time = start_time + duration;
var start_top = element.scrollTop;
var distance = target - start_top;
// based on http://en.wikipedia.org/wiki/Smoothstep
var smooth_step = function(start, end, point) {
if(point <= start) { return 0; }
if(point >= end) { return 1; }
var x = (point - start) / (end - start); // interpolation
return x*x*(3 - 2*x);
}
return new Promise(function(resolve, reject) {
// This is to keep track of where the element's scrollTop is
// supposed to be, based on what we're doing
var previous_top = element.scrollTop;
// This is like a think function from a game loop
var scroll_frame = function() {
if(element.scrollTop != previous_top) {
reject("interrupted");
return;
}
// set the scrollTop for this frame
var now = Date.now();
var point = smooth_step(start_time, end_time, now);
var frameTop = Math.round(start_top + (distance * point));
element.scrollTop = frameTop;
// check if we're done!
if(now >= end_time) {
resolve();
return;
}
// If we were supposed to scroll but didn't, then we
// probably hit the limit, so consider it done; not
// interrupted.
if(element.scrollTop === previous_top
&& element.scrollTop !== frameTop) {
resolve();
return;
}
previous_top = element.scrollTop;
// schedule next frame for execution
setTimeout(scroll_frame, 0);
}
// boostrap the animation process
setTimeout(scroll_frame, 0);
});
}
You can use the new Scroll Behaviour CSS Property.
for example, add the below line to your CSS.
html{
scroll-behavior:smooth;
}
and this will result in a native smooth scrolling feature.
see demo here
All modern browsers support the scroll-behavior property.
Read More about Scroll behavior
I've made an example without jQuery here : http://codepen.io/sorinnn/pen/ovzdq
/**
by Nemes Ioan Sorin - not an jQuery big fan
therefore this script is for those who love the old clean coding style
#id = the id of the element who need to bring into view
Note : this demo scrolls about 12.700 pixels from Link1 to Link3
*/
(function()
{
window.setTimeout = window.setTimeout; //
})();
var smoothScr = {
iterr : 30, // set timeout miliseconds ..decreased with 1ms for each iteration
tm : null, //timeout local variable
stopShow: function()
{
clearTimeout(this.tm); // stopp the timeout
this.iterr = 30; // reset milisec iterator to original value
},
getRealTop : function (el) // helper function instead of jQuery
{
var elm = el;
var realTop = 0;
do
{
realTop += elm.offsetTop;
elm = elm.offsetParent;
}
while(elm);
return realTop;
},
getPageScroll : function() // helper function instead of jQuery
{
var pgYoff = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
return pgYoff;
},
anim : function (id) // the main func
{
this.stopShow(); // for click on another button or link
var eOff, pOff, tOff, scrVal, pos, dir, step;
eOff = document.getElementById(id).offsetTop; // element offsetTop
tOff = this.getRealTop(document.getElementById(id).parentNode); // terminus point
pOff = this.getPageScroll(); // page offsetTop
if (pOff === null || isNaN(pOff) || pOff === 'undefined') pOff = 0;
scrVal = eOff - pOff; // actual scroll value;
if (scrVal > tOff)
{
pos = (eOff - tOff - pOff);
dir = 1;
}
if (scrVal < tOff)
{
pos = (pOff + tOff) - eOff;
dir = -1;
}
if(scrVal !== tOff)
{
step = ~~((pos / 4) +1) * dir;
if(this.iterr > 1) this.iterr -= 1;
else this.itter = 0; // decrease the timeout timer value but not below 0
window.scrollBy(0, step);
this.tm = window.setTimeout(function()
{
smoothScr.anim(id);
}, this.iterr);
}
if(scrVal === tOff)
{
this.stopShow(); // reset function values
return;
}
}
}
Modern browsers has support for CSS "scroll-behavior: smooth" property. So, we even don't need any Javascript at all for this. Just add this for the "html" element, and use usual anchors and links.
scroll-behavior MDN docs
I recently set out to solve this problem in a situation where jQuery wasn't an option, so I'm logging my solution here just for posterity.
var scroll = (function() {
var elementPosition = function(a) {
return function() {
return a.getBoundingClientRect().top;
};
};
var scrolling = function( elementID ) {
var el = document.getElementById( elementID ),
elPos = elementPosition( el ),
duration = 400,
increment = Math.round( Math.abs( elPos() )/40 ),
time = Math.round( duration/increment ),
prev = 0,
E;
function scroller() {
E = elPos();
if (E === prev) {
return;
} else {
prev = E;
}
increment = (E > -20 && E < 20) ? ((E > - 5 && E < 5) ? 1 : 5) : increment;
if (E > 1 || E < -1) {
if (E < 0) {
window.scrollBy( 0,-increment );
} else {
window.scrollBy( 0,increment );
}
setTimeout(scroller, time);
} else {
el.scrollTo( 0,0 );
}
}
scroller();
};
return {
To: scrolling
}
})();
/* usage */
scroll.To('elementID');
The scroll() function uses the Revealing Module Pattern to pass the target element's id to its scrolling() function, via scroll.To('id'), which sets the values used by the scroller() function.
Breakdown
In scrolling():
el : the target DOM object
elPos : returns a function via elememtPosition() which gives the position of the target element relative to the top of the page each time it's called.
duration : transition time in milliseconds.
increment : divides the starting position of the target element into 40 steps.
time : sets the timing of each step.
prev : the target element's previous position in scroller().
E : holds the target element's position in scroller().
The actual work is done by the scroller() function which continues to call itself (via setTimeout()) until the target element is at the top of the page or the page can scroll no more.
Each time scroller() is called it checks the current position of the target element (held in variable E) and if that is > 1 OR < -1 and if the page is still scrollable shifts the window by increment pixels - up or down depending if E is a positive or negative value. When E is neither > 1 OR < -1, or E === prev the function stops. I added the DOMElement.scrollTo() method on completion just to make sure the target element was bang on the top of the window (not that you'd notice it being out by a fraction of a pixel!).
The if statement on line 2 of scroller() checks to see if the page is scrolling (in cases where the target might be towards the bottom of the page and the page can scroll no further) by checking E against its previous position (prev).
The ternary condition below it reduce the increment value as E approaches zero. This stops the page overshooting one way and then bouncing back to overshoot the other, and then bouncing back to overshoot the other again, ping-pong style, to infinity and beyond.
If your page is more that c.4000px high you might want to increase the values in the ternary expression's first condition (here at +/-20) and/or the divisor which sets the increment value (here at 40).
Playing about with duration, the divisor which sets increment, and the values in the ternary condition of scroller() should allow you to tailor the function to suit your page.
JSFiddle
N.B.Tested in up-to-date versions of Firefox and Chrome on Lubuntu, and Firefox, Chrome and IE on Windows8.
I've made something like this.
I have no idea if its working in IE8.
Tested in IE9, Mozilla, Chrome, Edge.
function scroll(toElement, speed) {
var windowObject = window;
var windowPos = windowObject.pageYOffset;
var pointer = toElement.getAttribute('href').slice(1);
var elem = document.getElementById(pointer);
var elemOffset = elem.offsetTop;
var counter = setInterval(function() {
windowPos;
if (windowPos > elemOffset) { // from bottom to top
windowObject.scrollTo(0, windowPos);
windowPos -= speed;
if (windowPos <= elemOffset) { // scrolling until elemOffset is higher than scrollbar position, cancel interval and set scrollbar to element position
clearInterval(counter);
windowObject.scrollTo(0, elemOffset);
}
} else { // from top to bottom
windowObject.scrollTo(0, windowPos);
windowPos += speed;
if (windowPos >= elemOffset) { // scroll until scrollbar is lower than element, cancel interval and set scrollbar to element position
clearInterval(counter);
windowObject.scrollTo(0, elemOffset);
}
}
}, 1);
}
//call example
var navPointer = document.getElementsByClassName('nav__anchor');
for (i = 0; i < navPointer.length; i++) {
navPointer[i].addEventListener('click', function(e) {
scroll(this, 18);
e.preventDefault();
});
}
Description
pointer—get element and chceck if it has attribute "href" if yes,
get rid of "#"
elem—pointer variable without "#"
elemOffset—offset of "scroll to" element from the top of the page
You can use
document.querySelector('your-element').scrollIntoView({behavior: 'smooth'});
If you want to scroll top the top of the page, you can just place an empty element in the top, and smooth scroll to that one.
With using the following smooth scrolling is working fine:
html {
scroll-behavior: smooth;
}
<script>
var set = 0;
function animatescroll(x, y) {
if (set == 0) {
var val72 = 0;
var val73 = 0;
var setin = 0;
set = 1;
var interval = setInterval(function() {
if (setin == 0) {
val72++;
val73 += x / 1000;
if (val72 == 1000) {
val73 = 0;
interval = clearInterval(interval);
}
document.getElementById(y).scrollTop = val73;
}
}, 1);
}
}
</script>
x = scrollTop
y = id of the div that is used to scroll
Note:
For making the body to scroll give the body an ID.
Here is my solution. Works in most browsers
document.getElementById("scrollHere").scrollIntoView({behavior: "smooth"});
Docs
document.getElementById("end").scrollIntoView({behavior: "smooth"});
body {margin: 0px; display: block; height: 100%; background-image: linear-gradient(red, yellow);}
.start {display: block; margin: 100px 10px 1000px 0px;}
.end {display: block; margin: 0px 0px 100px 0px;}
<div class="start">Start</div>
<div class="end" id="end">End</div>
There are many different methods for smooth scrolling in JavaScript. The most common ones are listed below.
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. setTimeout can be used to a similar effect when requestAnimationFrame is not supported. (To scroll to a specific element with the function below, just set the 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:
/*
#param time: the exact amount of time the scrolling will take (in milliseconds)
#param pos: the y-position to scroll to (in pixels)
*/
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);
}
});
}
<button onClick="scrollToSmoothly(document.querySelector('div').offsetTop, 300)">
Scroll To Div (300ms)
</button>
<button onClick="scrollToSmoothly(document.querySelector('div').offsetTop, 200)">
Scroll To Div (200ms)
</button>
<button onClick="scrollToSmoothly(document.querySelector('div').offsetTop, 100)">
Scroll To Div (100ms)
</button>
<button onClick="scrollToSmoothly(document.querySelector('div').offsetTop, 50)">
Scroll To Div (50ms)
</button>
<button onClick="scrollToSmoothly(document.querySelector('div').offsetTop, 1000)">
Scroll To Div (1000ms)
</button>
<div style="margin: 500px 0px;">
DIV<p/>
<button onClick="scrollToSmoothly(0, 500)">
Back To Top
</button>
<button onClick="scrollToSmoothly(document.body.scrollHeight)">
Scroll To Bottom
</button>
</div>
<div style="margin: 500px 0px;">
</div>
<button style="margin-top: 100px;" onClick="scrollToSmoothly(500, 3000)">
Scroll To y-position 500px (3000ms)
</button>
For more complex cases, the SmoothScroll.js library can be used, which handles smooth scrolling both vertically and horizontally, scrolling inside other container elements, different easing behaviors, scrolling relatively from the current position, and more.
var easings = document.getElementById("easings");
for(var key in smoothScroll.easing){
if(smoothScroll.easing.hasOwnProperty(key)){
var option = document.createElement('option');
option.text = option.value = key;
easings.add(option);
}
}
document.getElementById('to-bottom').addEventListener('click', function(e){
smoothScroll({yPos: 'end', easing: easings.value, duration: 2000});
});
document.getElementById('to-top').addEventListener('click', function(e){
smoothScroll({yPos: 'start', easing: easings.value, duration: 2000});
});
<script src="https://cdn.jsdelivr.net/gh/LieutenantPeacock/SmoothScroll#1.2.0/src/smoothscroll.min.js" integrity="sha384-UdJHYJK9eDBy7vML0TvJGlCpvrJhCuOPGTc7tHbA+jHEgCgjWpPbmMvmd/2bzdXU" crossorigin="anonymous"></script>
<!-- Taken from one of the library examples -->
Easing: <select id="easings"></select>
<button id="to-bottom">Scroll To Bottom</button>
<br>
<button id="to-top" style="margin-top: 5000px;">Scroll To Top</button>
Alternatively, you can pass an options object to window.scroll which scrolls to a specific x and y position and window.scrollBy which scrolls a certain amount from the current position:
// Scroll to specific values
// scrollTo is the same
window.scroll({
top: 2500,
left: 0,
behavior: 'smooth'
});
// Scroll certain amounts from current position
window.scrollBy({
top: 100, // could be negative value
left: 0,
behavior: 'smooth'
});
Demo:
<button onClick="scrollToDiv()">Scroll To Element</button>
<div style="margin: 500px 0px;">Div</div>
<script>
function scrollToDiv(){
var elem = document.querySelector("div");
window.scroll({
top: elem.offsetTop,
left: 0,
behavior: 'smooth'
});
}
</script>
If you only need to scroll to an element, not a specific position in the document, you can use Element.scrollIntoView with behavior set to smooth.
document.getElementById("elemID").scrollIntoView({
behavior: 'smooth'
});
Demo:
<button onClick="scrollToDiv()">Scroll To Element</button>
<div id="myDiv" style="margin: 500px 0px;">Div</div>
<script>
function scrollToDiv(){
document.getElementById("myDiv").scrollIntoView({
behavior: 'smooth'
});
}
</script>
Modern browsers support the scroll-behavior CSS property, which can be used to make scrolling in the document smooth (without the need for JavaScript). Anchor tags can be used for this by giving the anchor tag a href of # plus the id of the element to scroll to). You can also set the scroll-behavior property for a specific container like a div to make its contents scroll smoothly.
Demo:
html, body{
scroll-behavior: smooth;
}
Scroll To Element
<div id="elem" style="margin: 500px 0px;">Div</div>
Here's my variation:
let MenuItem = function ( _menuItem ) {
// I had a sticky header, so its height had to be taken into account when scrolling
let _header = document.querySelector('.site-header');
let _scrollToBlock = function( e, menuItem ) {
let id = menuItem.getAttribute('href'), // the href attribute stores the id of the block to which the scroll will be
headerHeight = _header.offsetHeight; // determine the height of the header
id = id.replace(/#/, ''); // remove the # sign from the id block
let elem = document.getElementById( id ), // define the element to which we will scroll
top = elem.getBoundingClientRect().top + window.scrollY - headerHeight; // determine the height of the scroll
window.scroll({
top: top,
left: 0,
behavior: 'smooth'
});
},
_addEvents = function() {
_menuItem.addEventListener('click', function (e){
e.preventDefault(); // Disable redirect on click
_scrollToBlock(e, _menuItem);
});
},
_init = function() {
_addEvents();
};
_init();
};
// Initialize the class MenuItem to all links with class .menu__item
document.querySelectorAll('.menu__item').forEach( function(item) {
new MenuItem(item);
} );
Here's the code that worked for me.
`$('a[href*="#"]')
.not('[href="#"]')
.not('[href="#0"]')
.click(function(event) {
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) {
event.preventDefault();
$('html, body').animate({
scrollTop: target.offset().top
}, 1000, function() {
var $target = $(target);
$target.focus();
if ($target.is(":focus")) {
return false;
} else {
$target.attr('tabindex','-1');
$target.focus();
};
});
}
}
});
`

Categories