Skip to content

Commit 498f9e0

Browse files
committed
add reduce motion for vanilla #136
1 parent 8980acb commit 498f9e0

File tree

2 files changed

+47
-11
lines changed

2 files changed

+47
-11
lines changed

src/vanilla/index.js

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ export default class SimpleParallax {
1515

1616
// check if the browser support simpleParallax
1717
if (!isSupportedBrowser()) return;
18+
19+
// Check if user prefers reduced motion
20+
this.prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
21+
22+
// Set up listener for changes to reduced motion preference
23+
this.reducedMotionMediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
24+
this.handleReducedMotionChange = this.handleReducedMotionChange.bind(this);
25+
this.reducedMotionMediaQuery.addEventListener('change', this.handleReducedMotionChange);
26+
27+
// If reduced motion is preferred, don't initialize parallax effects
28+
if (this.prefersReducedMotion) return;
1829

1930
this.elements = convertToArray(elements);
2031
this.defaults = {
@@ -45,20 +56,33 @@ export default class SimpleParallax {
4556

4657
this.init();
4758
}
59+
60+
// Handle changes to reduced motion preference
61+
handleReducedMotionChange(event) {
62+
this.prefersReducedMotion = event.matches;
63+
64+
if (this.prefersReducedMotion) {
65+
// If user now prefers reduced motion, remove all parallax effects
66+
this.destroy();
67+
} else {
68+
// If user no longer prefers reduced motion, reinitialize
69+
this.init();
70+
}
71+
}
4872

4973
init() {
74+
// Don't initialize if reduced motion is preferred
75+
if (this.prefersReducedMotion) return;
76+
5077
viewport.setViewportAll(this.customContainer);
5178

5279
instances = [
5380
...this.elements.map(
54-
(element) => new ParallaxInstance(element, this.settings)
81+
(element) => new ParallaxInstance(element, this.settings, this.prefersReducedMotion)
5582
),
5683
...instances
5784
];
5885

59-
// update the instance length
60-
// instancesLength = instances.length;
61-
6286
// only if this is the first simpleParallax init
6387
if (!isInit) {
6488
// init the frame
@@ -109,7 +133,7 @@ export default class SimpleParallax {
109133
}
110134

111135
// proceed the element
112-
proceedElement(instance) {
136+
proceedElement(instance) {
113137
let isVisible = false;
114138

115139
// if this is a custom container
@@ -150,11 +174,16 @@ export default class SimpleParallax {
150174
}
151175

152176
destroy() {
177+
// Remove reduced motion event listener
178+
if (this.reducedMotionMediaQuery) {
179+
this.reducedMotionMediaQuery.removeEventListener('change', this.handleReducedMotionChange);
180+
}
181+
153182
const instancesToDestroy = [];
154183

155184
// remove all instances that need to be destroyed from the instances array
156185
instances = instances.filter((instance) => {
157-
if (this.elements.includes(instance.element)) {
186+
if (this.elements && this.elements.includes(instance.element)) {
158187
// push instance that need to be destroyed into instancesToDestroy
159188
instancesToDestroy.push(instance);
160189
return false;
@@ -166,7 +195,7 @@ export default class SimpleParallax {
166195
// unset style
167196
instance.unSetStyle();
168197

169-
if (this.settings.overflow === false) {
198+
if (this.settings && this.settings.overflow === false) {
170199
// if overflow option is set to false
171200
// unwrap the element from .simpleParallax wrapper container
172201
instance.unWrapElement();

src/vanilla/instances/parallax.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ import isImageLoaded from '../helpers/isImageLoaded';
33
import { viewport } from '../helpers/viewport';
44

55
class ParallaxInstance {
6-
constructor(element, options) {
6+
constructor(element, options, prefersReducedMotion = false) {
77
// set the element & settings
88
this.element = element;
99
this.elementContainer = element;
1010
this.settings = options;
1111
this.isVisible = true;
1212
this.isInit = false;
1313
this.oldTranslateValue = -1;
14+
this.prefersReducedMotion = prefersReducedMotion;
1415

1516
this.init = this.init.bind(this);
1617

@@ -20,6 +21,9 @@ class ParallaxInstance {
2021
? this.element.closest(this.settings.customWrapper)
2122
: null;
2223

24+
// Don't initialize if reduced motion is preferred
25+
if (this.prefersReducedMotion) return;
26+
2327
// check if images has not been loaded yet
2428
if (isImageLoaded(element)) {
2529
this.init();
@@ -34,6 +38,9 @@ class ParallaxInstance {
3438
}
3539

3640
init(asyncInit) {
41+
// Don't initialize if reduced motion is preferred
42+
if (this.prefersReducedMotion) return;
43+
3744
// for some reason, <picture> are init an infinite time on windows OS
3845
if (this.isInit) return;
3946

@@ -136,7 +143,7 @@ class ParallaxInstance {
136143
this.element.style.willChange = 'transform';
137144
}
138145

139-
// apply the transition effet
146+
// apply the transition effect
140147
setTransitionCSS() {
141148
// add transition option
142149
this.element.style.transition = `transform ${this.settings.delay}s ${this.settings.transition}`;
@@ -195,7 +202,7 @@ class ParallaxInstance {
195202

196203
// Intersection Observer Callback to set the element at visible state or not
197204
intersectionObserverCallback(entries) {
198-
entries.forEach((entry) => {
205+
entries.forEach((entry) => {
199206
if (entry.isIntersecting) {
200207
this.isVisible = true;
201208
} else {
@@ -207,7 +214,7 @@ class ParallaxInstance {
207214
// check if the current element is visible in the Viewport
208215
// for browser that not support Intersection Observer API
209216
checkIfVisible() {
210-
return (
217+
return (
211218
this.elementBottom > viewport.positions.top &&
212219
this.elementTop < viewport.positions.bottom
213220
);

0 commit comments

Comments
 (0)