Security News
Cloudflare Adds Security.txt Setup Wizard
Cloudflare has launched a setup wizard allowing users to easily create and manage a security.txt file for vulnerability disclosure on their websites.
sweet-scroll
Advanced tools
ECMAScript2015+ & TypeScript Friendly, dependency-free smooth scroll library.
:lollipop: See Demo
requestAnimationFrame
APISee the Migration Guide
$ npm install sweet-scroll
import SweetScroll from 'sweet-scroll';
<script src="sweet-scroll.min.js"></script>
<script src="https://unpkg.com/sweet-scroll/sweet-scroll.min.js"></script>
<a href="#intro" data-scroll>Go to Introduction</a>
...
<div id="intro">Introduction</div>
You need to initialize an instance after DOMContentLoaded
.
document.addEventListener(
'DOMContentLoaded',
() => {
const scroller = new SweetScroll({
/* some options */
});
},
false,
);
The following options are applied by default. It can be customized as needed.
{
trigger: '[data-scroll]', // Selector for trigger (must be a valid css selector)
header: '[data-scroll-header]', // Selector or Element for fixed header (Selector of must be a valid css selector)
duration: 1000, // Specifies animation duration in integer
easing: 'easeOutQuint', // Specifies the pattern of easing
offset: 0, // Specifies the value to offset the scroll position in pixels
vertical: true, // Enable the vertical scroll
horizontal: false, // Enable the horizontal scroll
cancellable: true, // When fired wheel or touchstart events to stop scrolling
updateURL: false, // Update the URL hash on after scroll (true | false | 'push' | 'replace')
preventDefault: true, // Cancels the container element click event
stopPropagation: true, // Prevents further propagation of the container element click event in the bubbling phase
// Callbacks
before: null,
after: null,
cancel: null,
complete: null,
step: null,
}
Supports the following easing.
linear
easeInQuad
easeOutQuad
easeInOutQuad
easeInCubic
easeOutCubic
easeInOutCubic
easeInQuart
easeOutQuart
easeInOutQuart
easeInQuint
easeOutQuint
(default)easeInOutQuint
easeInSine
easeOutSine
easeInOutSine
easeInExpo
easeOutExpo
easeInOutExpo
easeInCirc
easeOutCirc
easeInOutCirc
Easing functions that are not built in can pass functions directly.
const scroller = new SweetScroll({
easing: advancedEasingFunction,
});
easeInElastic
const easeInElastic = (_, t, b, c, d) => {
let s = 1.70158;
let p = 0;
let a = c;
if (t === 0) return b;
if ((t /= d) === 1) return b + c;
if (!p) p = d * 0.3;
if (a < Math.abs(c)) {
a = c;
s = p / 4;
} else {
s = (p / (2 * Math.PI)) * asin(c / a);
}
return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin(((t * d - s) * (2 * Math.PI)) / p)) + b;
};
easeOutElastic
const easeOutElastic = (_, t, b, c, d) => {
let s = 1.70158;
let p = 0;
let a = c;
if (t === 0) return b;
if ((t /= d) === 1) return b + c;
if (!p) p = d * 0.3;
if (a < Math.abs(c)) {
a = c;
s = p / 4;
} else {
s = (p / (2 * Math.PI)) * asin(c / a);
}
return a * Math.pow(2, -10 * t) * Math.sin(((t * d - s) * (2 * Math.PI)) / p) + c + b;
};
easeInOutElastic
const easeInOutElastic = (_, t, b, c, d) => {
let s = 1.70158;
let p = 0;
let a = c;
if (t === 0) return b;
if ((t /= d / 2) === 2) return b + c;
if (!p) p = d * (0.3 * 1.5);
if (a < Math.abs(c)) {
a = c;
s = p / 4;
} else {
s = (p / (2 * Math.PI)) * Math.asin(c / a);
}
if (t < 1) {
return (
-0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin(((t * d - s) * (2 * Math.PI)) / p)) + b
);
}
return (
a * Math.pow(2, -10 * (t -= 1)) * Math.sin(((t * d - s) * (2 * Math.PI)) / p) * 0.5 + c + b
);
};
easeInBack
const easeInBack = (_, t, b, c, d, s = 1.70158) => c * (t /= d) * t * ((s + 1) * t - s) + b;
easeOutBack
const easeOutBack = (_, t, b, c, d, s = 1.70158) =>
c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
easeInOutBack
const easeInOutBack = (_, t, b, c, d, s = 1.70158) =>
(t /= d / 2) < 1
? (c / 2) * (t * t * (((s *= 1.525) + 1) * t - s)) + b
: (c / 2) * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2) + b;
easeOutBounce
const easeOutBounce = (_, t, b, c, d) => {
if ((t /= d) < 1 / 2.75) {
return c * (7.5625 * t * t) + b;
} else if (t < 2 / 2.75) {
return c * (7.5625 * (t -= 1.5 / 2.75) * t + 0.75) + b;
} else if (t < 2.5 / 2.75) {
return c * (7.5625 * (t -= 2.25 / 2.75) * t + 0.9375) + b;
}
return c * (7.5625 * (t -= 2.625 / 2.75) * t + 0.984375) + b;
};
easeInBounce
const easeOutBounce = (_, t, b, c, d) => {
if ((t /= d) < 1 / 2.75) {
return c * (7.5625 * t * t) + b;
} else if (t < 2 / 2.75) {
return c * (7.5625 * (t -= 1.5 / 2.75) * t + 0.75) + b;
} else if (t < 2.5 / 2.75) {
return c * (7.5625 * (t -= 2.25 / 2.75) * t + 0.9375) + b;
}
return c * (7.5625 * (t -= 2.625 / 2.75) * t + 0.984375) + b;
};
const easeInBounce = (x, t, b, c, d) => c - easeOutBounce(x, d - t, 0, c, d) + b;
easeInOutBounce
const easeOutBounce = (_, t, b, c, d) => {
if ((t /= d) < 1 / 2.75) {
return c * (7.5625 * t * t) + b;
} else if (t < 2 / 2.75) {
return c * (7.5625 * (t -= 1.5 / 2.75) * t + 0.75) + b;
} else if (t < 2.5 / 2.75) {
return c * (7.5625 * (t -= 2.25 / 2.75) * t + 0.9375) + b;
}
return c * (7.5625 * (t -= 2.625 / 2.75) * t + 0.984375) + b;
};
const easeInBounce = (x, t, b, c, d) => c - easeOutBounce(x, d - t, 0, c, d) + b;
const easeInOutBounce = (x, t, b, c, d) =>
t < d / 2
? easeInBounce(x, t * 2, 0, c, d) * 0.5 + b
: easeOutBounce(x, t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
In the following example we have specified in the container for scrolling the #container
.
<div id="container">
<a href="#heading2" data-scroll>Go to Heading2</a>
...
<h2 id="heading2">Heading2</h2>
</div>
// Specified in the CSS Selector
const scroller = new SweetScroll(
{
/* some options */
},
'#container',
);
// Specified in the Element
const scroller = new SweetScroll(
{
/* some options */
},
document.getElementById('container'),
);
Add the data-scroll-header
attribute in order to offset the height of the fixed header.
<header data-scroll-header></header>
Specify the CSS Selector in header
option instead of the data-scroll-header
attribute.
const scroller = new SweetScroll({
header: '#header',
});
You can override the default options by passing the option in JSON
format to the data-scroll-options
.
<a href="#target" data-scroll data-scroll-options='{"easing": "easeOutExpo"}'>Go to Target</a>
Will use the data-scroll attribute instead of href.
<button type="button" data-scroll="+=500">Scroll under 500px</button>
The following, Introduce one of the mounting method.
document.addEventListener(
'DOMContentLoaded',
() => {
const scroller = new SweetScroll();
const hash = window.location.hash;
const needsInitialScroll = document.getElementById(hash.substr(1)) != null;
if (needsInitialScroll) {
window.location.hash = '';
}
window.addEventListener(
'load',
() => {
if (needsInitialScroll) {
scroller.to(hash, { updateURL: 'replace' });
}
},
false,
);
},
false,
);
You can also achieve the same thing in other ways by using the provided API.
Will generate a SweetScroll instance.
Example:
const scroller = new SweetScroll(
{
duration: 1200,
easing: 'easeOutExpo',
},
'#container',
);
Will generate a SweetScroll instance. (factory method)
Example:
const scroller = SweetScroll.create(
{
duration: 1200,
easing: 'easeOutExpo',
},
'#container',
);
Scroll animation to the specified distance
.
distance
to can specify the CSS Selector or scroll position.
Example:
const scroller = new SweetScroll();
// CSS Selector of target element
scroller.to('#footer');
// Object
scroller.to({ top: 1000, left: 20 });
// Array (top:0, left:1000)
scroller.to([0, 1000]);
// Number (Priority to vertical scroll position. by default.)
scroller.to(500);
// String (Relative position)
scroller.to('+=500');
scroller.to('-=200');
Vertical scroll animation to the specified distance
.
Example:
scroller.toTop(0);
Horizontal scroll animation to the specified distance
.
Example:
scroller.toLeft(1500);
Scroll animation to the specified Element
.
Example:
scroller.toElement(document.getElementById('content'));
Will update the SweetScroll instance. Primarily used in the case of option update.
Example:
scroller.update({
trigger: 'a[href^="#"]',
duration: 3000,
});
gotoEnd: {Boolean}
Will stop the current scroll animation.
Example:
scroller.stop(true);
Will destroy the SweetScroll instance. Disable of the method and event handler.
Example:
scroller.destroy();
In before
and after
, you will pass the coordinates and the triggering element in the argument.
In addition, you can stop the scrolling by return a before
in false
.
Example:
const scroller = new SweetScroll({
// Stop scrolling case of trigger element that contains the `is-disabled` class.
before: (offset: Offset, $trigger: Element | null, scroller: SweetScroll): boolean | void => {
console.log('Before!!', offset, scroller);
if ($trigger && $trigger.classList.contains('is-disabled')) {
return false;
}
},
// If the `wheel` or `touchstart` event is called
cancel: (scroller: SweetScroll): void => {
console.log('Cancel!!', scroller);
},
// Scroll animation is complete
after: (offset: Offset, $trigger: Element | null, scroller: SweetScroll): void => {
console.log('After!!', offset, $trigger, scroller);
},
// Scroll animation is complete (`after` or `cancel`)
complete: (isCancel: boolean, scroller: SweetScroll): void => {
console.log('Complete!!', isCancel, scroller);
},
// Each animation frame
step: (time: number, scroller: SweetScroll): void => {
console.log('step', time, scroller);
},
});
Extends Class:
The following is a pattern to override a method in the inheritance destination class.
import SweetScroll, { Offset } from 'sweet-scroll';
class MyScroll extends SweetScroll {
protected onBefore(offset: Offset, $trigger: Element | null): boolean | void {
// Stop scrolling case of trigger element that contains the `is-disabled` class.
console.log('Before!!', offset);
if ($trigger && $trigger.classList.contains('is-disabled')) {
return false;
}
}
protected onCancel(): void {
console.log('Canell!!');
}
protected onAfter(offset: Offset, $trigger: Element | null): void {
console.log('After!!', offset, $trigger);
}
protected onComplete(isCancel: boolean): void {
console.log('Complete!!', isCancel);
}
protected onStep(time: number): void {
console.log('step', time);
}
}
Works in IE10+
, and all modern browsers.
It is necessary to use polyfill or ponyfill of requestAnimationFrame
.
Using raf module.
import raf from 'raf';
import SweetScroll from 'sweet-scroll';
SweetScroll.raf = raf;
SweetScroll.caf = raf.cancel;
See the CHANGELOG.md
git checkout -b my-new-feature
git commit -am 'Add some feature'
git push origin my-new-feature
Bugs, feature requests and comments are more than welcome in the issues.
We will develop using the following npm scripts.
yarn start
Launch the local server and let the demo run. Opening http://localhost:3000 in your browser.
yarn build
Compile TypeScript and create type definitions.
yarn test
Run unit testing with Jest.
4.0.0
container
from body,html
to window
.
body,html
, it may cause unintended behaviors.quickMode
options.onclick
handling.
FAQs
Modern and the sweet smooth scroll library.
The npm package sweet-scroll receives a total of 9,767 weekly downloads. As such, sweet-scroll popularity was classified as popular.
We found that sweet-scroll demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Cloudflare has launched a setup wizard allowing users to easily create and manage a security.txt file for vulnerability disclosure on their websites.
Security News
The Socket Research team breaks down a malicious npm package targeting the legitimate DOMPurify library. It uses obfuscated code to hide that it is exfiltrating browser and crypto wallet data.
Security News
ENISA’s 2024 report highlights the EU’s top cybersecurity threats, including rising DDoS attacks, ransomware, supply chain vulnerabilities, and weaponized AI.