Product
Introducing Enhanced Alert Actions and Triage Functionality
Socket now supports four distinct alert actions instead of the previous two, and alert triaging allows users to override the actions taken for all individual alerts.
sweet-scroll
Advanced tools
Changelog
4.0.0
container
from body,html
to window
.
body,html
, it may cause unintended behaviors.quickMode
options.onclick
handling.
Readme
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.
FAQs
Modern and the sweet smooth scroll library.
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.
Product
Socket now supports four distinct alert actions instead of the previous two, and alert triaging allows users to override the actions taken for all individual alerts.
Security News
Polyfill.io has been serving malware for months via its CDN, after the project's open source maintainer sold the service to a company based in China.
Security News
OpenSSF is warning open source maintainers to stay vigilant against reputation farming on GitHub, where users artificially inflate their status by manipulating interactions on closed issues and PRs.