react-scroll-parallax
Advanced tools
Comparing version 2.4.0 to 3.0.0-alpha.0
139
package.json
{ | ||
"name": "react-scroll-parallax", | ||
"version": "2.4.0", | ||
"version": "3.0.0-alpha.0", | ||
"description": "React components to create parallax scroll effects for banners, images or any other DOM elements.", | ||
@@ -10,23 +10,22 @@ "repository": { | ||
"files": [ | ||
"cjs", | ||
"README.md", | ||
"LICENSE" | ||
"dist", | ||
"src" | ||
], | ||
"main": "./cjs/index.js", | ||
"browserslist": [ | ||
"last 2 version", | ||
"> 1%", | ||
"not dead" | ||
], | ||
"main": "dist/index.js", | ||
"typings": "dist/index.d.ts", | ||
"engines": { | ||
"node": ">=10" | ||
}, | ||
"scripts": { | ||
"start": "yarn storybook", | ||
"test": "BABEL_ENV=test jest", | ||
"test:watch": "BABEL_ENV=test jest --watch", | ||
"lint": "eslint ./src ./__tests__", | ||
"prettier": "prettier --config ./.prettierrc --write \"{src,stories,__tests__}/**/*.js\"", | ||
"prepublishOnly": "yarn test && ./publish.sh", | ||
"storybook": "start-storybook -p 3000", | ||
"storybook:build": "build-storybook", | ||
"storybook:export": "build-storybook -c .storybook -o build", | ||
"deploy": "yarn run storybook:export" | ||
"start": "tsdx watch", | ||
"build": "tsdx build", | ||
"test": "tsdx test --passWithNoTests", | ||
"prettier": "prettier ./ --write", | ||
"lint": "tsdx lint", | ||
"prepare": "tsdx build", | ||
"size": "size-limit", | ||
"analyze": "size-limit --why", | ||
"storybook": "start-storybook -p 6006", | ||
"build-storybook": "build-storybook", | ||
"release": "np" | ||
}, | ||
@@ -49,55 +48,63 @@ "jest": { | ||
}, | ||
"keywords": [ | ||
"react", | ||
"scroll", | ||
"parallax", | ||
"banner", | ||
"animation", | ||
"component" | ||
], | ||
"peerDependencies": { | ||
"react": "^16.8.0-0 || >=17.0.1", | ||
"react-dom": "^16.8.0-0 || >=17.0.1" | ||
}, | ||
"author": "J Scott Smith", | ||
"license": "MIT", | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "tsdx lint" | ||
} | ||
}, | ||
"prettier": { | ||
"printWidth": 80, | ||
"tabWidth": 2, | ||
"semi": true, | ||
"singleQuote": true, | ||
"trailingComma": "es5" | ||
}, | ||
"module": "dist/react-scroll-parallax.esm.js", | ||
"size-limit": [ | ||
{ | ||
"path": "dist/react-scroll-parallax.cjs.production.min.js", | ||
"limit": "10 KB" | ||
}, | ||
{ | ||
"path": "dist/react-scroll-parallax.esm.js", | ||
"limit": "10 KB" | ||
} | ||
], | ||
"dependencies": { | ||
"prop-types": "^15.5.10" | ||
"parallax-controller": "0.1.11" | ||
}, | ||
"peerDependencies": { | ||
"react": "^16.3.0-0 || >=17.0.1", | ||
"react-dom": "^16.3.0-0 || >=17.0.1" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.0.0", | ||
"@babel/core": "^7.0.0", | ||
"@babel/plugin-proposal-class-properties": "^7.0.0", | ||
"@babel/plugin-proposal-export-default-from": "^7.0.0", | ||
"@babel/preset-env": "^7.0.0", | ||
"@babel/preset-react": "^7.0.0", | ||
"@storybook/addon-actions": "^6.2.9", | ||
"@storybook/addon-knobs": "^6.2.9", | ||
"@storybook/addon-links": "^6.2.9", | ||
"@storybook/addons": "^6.2.9", | ||
"@storybook/react": "^6.2.9", | ||
"@types/jest": "^24.0.11", | ||
"@types/react": "^17.0.1", | ||
"babel-core": "^7.0.0-bridge.0", | ||
"babel-eslint": "^10.0.1", | ||
"babel-jest": "^23.4.2", | ||
"babel-loader": "^8.0.0", | ||
"codecov": "^3.0.0", | ||
"cross-env": "^3.1.4", | ||
"css-loader": "^2.1.0", | ||
"eslint": "^5.13.0", | ||
"eslint-plugin-babel": "^5.3.0", | ||
"eslint-plugin-jest": "^22.2.2", | ||
"eslint-plugin-react": "^7.12.4", | ||
"express": "^4.14.1", | ||
"jest": "^24.0.1", | ||
"node-sass": "^4.5.0", | ||
"react": "^17.0.1", | ||
"react-dom": "^17.0.1", | ||
"@babel/core": "^7.16.0", | ||
"@size-limit/preset-small-lib": "^6.0.4", | ||
"@storybook/addon-essentials": "^6.3.12", | ||
"@storybook/addon-info": "^5.3.21", | ||
"@storybook/addon-links": "^6.3.12", | ||
"@storybook/addons": "^6.3.12", | ||
"@storybook/preset-scss": "^1.0.3", | ||
"@storybook/react": "^6.3.12", | ||
"@testing-library/react": "^12.1.2", | ||
"@types/jest": "^27.0.3", | ||
"@types/react": "^17.0.35", | ||
"@types/react-dom": "^17.0.11", | ||
"babel-loader": "^8.2.3", | ||
"css-loader": "^5.0.0", | ||
"husky": "^7.0.4", | ||
"np": "^7.6.0", | ||
"react": "^17.0.2", | ||
"react-dom": "^17.0.2", | ||
"react-is": "^17.0.2", | ||
"react-test-renderer": "^17.0.1", | ||
"regenerator-runtime": "^0.10.5", | ||
"sass-loader": "^7.1.0", | ||
"style-loader": "^0.23.1", | ||
"webpack": "^4.29.3" | ||
"sass": "^1.43.4", | ||
"sass-loader": "^10.1.0", | ||
"size-limit": "^6.0.4", | ||
"style-loader": "^2.0.0", | ||
"tsdx": "^0.14.1", | ||
"tslib": "^2.3.1", | ||
"typescript": "^4.4.4" | ||
} | ||
} |
275
README.md
@@ -5,3 +5,3 @@ # React Scroll Parallax | ||
React components to create parallax scroll effects for banners, images or any other DOM elements. Uses a single scroll listener to add vertical or horizontal scrolling based offsets to elements based on their position in the viewport. [Optimized](#optimizations-to-reduce-jank) to _reduce_ jank on scroll and works with universal (server-side rendered) React apps. | ||
React components to create parallax scroll effects for banners, images or any other DOM elements. Uses a single scroll listener via [Parallax Controller](https://github.com/jscottsmith/parallax-controller) to add vertical or horizontal scrolling based offsets to elements based on their position in the viewport. [Optimized](https://github.com/jscottsmith/parallax-controller#optimizations-to-reduce-jank) to _reduce_ jank on scroll and works with universal (server-side rendered) React apps. | ||
@@ -12,6 +12,15 @@ If you're coming from [v1](https://github.com/jscottsmith/react-scroll-parallax/tree/v1), here's a [migration guide](https://github.com/jscottsmith/react-scroll-parallax/blob/master/docs/migration-guide.md). | ||
- [Storybook](https://react-scroll-parallax-next.surge.sh) | ||
- [Demo 1](https://jscottsmith.github.io/react-scroll-parallax-examples/examples/parallax-example/) - [Source](https://github.com/jscottsmith/react-scroll-parallax-examples) | ||
- [Demo 2](https://react-scroll-parallax.netlify.com/) - [Source](https://github.com/jscottsmith/react-parallax-site) | ||
#### V3 Storybook | ||
See the [Storybook](https://react-scroll-parallax-v3.surge.sh) for example usage of each component | ||
- [Storybook](https://react-scroll-parallax-v3.surge.sh) - [Source](/stories) | ||
#### Demos | ||
Some demo websites using Parallax components | ||
- [Demo 1](https://jscottsmith.github.io/react-scroll-parallax-examples/examples/parallax-example/) - [Source](https://github.com/jscottsmith/react-scroll-parallax-examples) | ||
- [Demo 2](https://react-scroll-parallax.netlify.com/) - [Source](https://github.com/jscottsmith/react-parallax-site) | ||
## Install | ||
@@ -31,22 +40,22 @@ | ||
## Overview | ||
## Documentation | ||
- [Usage](#usage) | ||
- [`<Parallax>`](#parallax) | ||
- [Parallax Props](#parallax-props) | ||
- [`<ParallaxBanner>`](#parallaxbanner) | ||
- [Banner Usage](#banner-usage) | ||
- [Banner Props](#banner-props) | ||
- [Banner Layers Prop](#banner-layers-prop) | ||
- [`<ParallaxProvider>`](#parallaxprovider) | ||
- [ParallaxProvider Props](#parallaxprovider-props) | ||
- [Parallax Controller Context](#parallax-controller-context) | ||
- [Available Methods](#available-methods) | ||
- [Browser Support](#browser-support) | ||
- [Optimizations to Reduce Jank](#optimizations-to-reduce-jank) | ||
- [PSA](#psa) | ||
- [Example Usage](#usage) | ||
- [`<Parallax>`](/docs/parallax-component.md) | ||
- [Parallax Props](/docs/parallax-component.md#props) | ||
- [`<ParallaxBanner>`](/docs/parallax-banner-component.md) | ||
- [Banner Usage](/docs/parallax-banner-component.md#banner-usage) | ||
- [Banner Props](/docs/parallax-banner-component.md#banner-props) | ||
- [Banner Layers Prop](/docs/parallax-banner-component.md#banner-layers-prop) | ||
- [`<ParallaxProvider>`](/docs/parallax-provider-component.md) | ||
- [ParallaxProvider Props](/docs/parallax-provider-component.md#parallaxprovider-props) | ||
- [Parallax Controller Context](/docs/parallax-controller-context.md) | ||
- [Available Methods](/docs/parallax-controller-context.md#available-methods) | ||
- [Browser Support](#browser-support) | ||
- [Optimizations to Reduce Jank](#optimizations-to-reduce-jank) | ||
- [PSA](#psa) | ||
## Usage | ||
The [`<ParallaxProvider>`](#parallaxprovider) should wrap the component tree that contains all `<Parallax>` components. This should be a top level component like `<AppContainer>`. For example: | ||
The [`<ParallaxProvider>`](#parallaxprovider) must wrap the component tree that contains all `<Parallax>` components. This should be a top level component like `<App>`. For example: | ||
@@ -56,14 +65,14 @@ ```jsx | ||
class AppContainer extends Component { | ||
render() { | ||
return ( | ||
<ParallaxProvider> | ||
<App /> | ||
</ParallaxProvider> | ||
); | ||
} | ||
function App() { | ||
render() { | ||
return ( | ||
<ParallaxProvider> | ||
<AppRoutes /> | ||
</ParallaxProvider> | ||
); | ||
} | ||
} | ||
``` | ||
Import the `Parallax` component and use it anywhere within the provider like so: | ||
Then import the `Parallax` component and use it anywhere within the provider. Here's an example that will transform the element on the `translateY` axis starting at `-20%` and ending at `20%` (`translateY = [-20, 20]` \*percent is assumed with no provided unit). | ||
@@ -73,196 +82,30 @@ ```jsx | ||
const ParallaxImage = () => ( | ||
<Parallax className="custom-class" y={[-20, 20]} tagOuter="figure"> | ||
<Image src="/image.jpg" /> | ||
</Parallax> | ||
const VerticalParallax = () => ( | ||
<Parallax translateY={[-20, 20]}> | ||
<div className="my-thing" /> | ||
</Parallax> | ||
); | ||
``` | ||
**Warnings:** | ||
Example with transforms on the `translateX` axis starting at `-100px` and ending at `200px` (`translateX = ['-100px', '200px']`). | ||
1. This lib was designed to be used on `relative` or `absolute` positioned elements that scroll naturally with the page. If you use `fixed` positioning on either the element itself or the parent you will encounter issues. More on that in [troubleshooting](#troubleshooting). | ||
2. Scroll state and positions of elements on the page are cached for performance reasons. This means that if the page height changes (most likely from [images loading](#example-usage-of-context)) after `<Parallax />` components are mounted the controller won't properly determine when the elements are in view. To correct this you can call the `parallaxController.update()` method from any child component of the `<ParallaxProvider />` via context and the `withController()` HOC. More details on how here: [Parallax Controller Context](#parallax-controller-context). | ||
## \<Parallax> | ||
The main component for manipulating a DOM element's position based on it's position within the viewport. | ||
### Parallax Props | ||
The following are all props that can be passed to the `<Parallax>` component: | ||
| Name | Type | Default | Description | | ||
| -------------- | :-----------------------------: | :------- | ------------------------------------------------------------------------------------------------------------------ | | ||
| **x** | `Array` of `String` or `Number` | `[0, 0]` | Offsets on x-axis in `%` or `px`. If no unit is passed percent is assumed. Percent is based on the elements width. | | ||
| **y** | `Array` of `String` or `Number` | `[0, 0]` | Offsets on y-axis in `%` or `px`. If no unit is passed percent is assumed. Percent is based on the elements width. | | ||
| **className** | `String` | | Optionally pass additional class names to be added to the outermost parallax element. | | ||
| **disabled** | `Boolean` | `false` | Disables parallax effects on individual elements when `true`. | | ||
| **styleInner** | `Object` | | Optionally pass a style object to be added to the innermost parallax element. | | ||
| **styleOuter** | `Object` | | Optionally pass a style object to be added to the outermost parallax element. | | ||
| **tagInner** | `String` | `div` | Optionally pass an element tag name to be applied to the innermost parallax element. | | ||
| **tagOuter** | `String` | `div` | Optionally pass an element tag name to be applied to the outermost parallax element. | | ||
## \<ParallaxBanner> | ||
Component that utilizes `<Parallax>` components to achieve a parallaxing banner effect. Allows a single or multiple images to be parallaxed at different rates within the banner area. | ||
### Banner Usage | ||
Use the `layers` prop to indicate all images, offset amounts, and scroll rates. Optionally pass additional children to be rendered. Styles of the outermost banner element can also be changed. Here's an example: | ||
```jsx | ||
<ParallaxBanner | ||
className="your-class" | ||
layers={[ | ||
{ | ||
image: 'https://foo.com/foo.jpg', | ||
amount: 0.1, | ||
}, | ||
{ | ||
image: 'https://foo.com/bar.png', | ||
amount: 0.2, | ||
}, | ||
]} | ||
style={{ | ||
height: '500px', | ||
}} | ||
> | ||
<h1>Banner Children</h1> | ||
</ParallaxBanner> | ||
``` | ||
import { Parallax } from 'react-scroll-parallax'; | ||
### Banner Props | ||
The following are all props that can be passed to the `<ParallaxBanner>` component: | ||
| Name | Type | Default | Description | | ||
| ------------- | :-------: | :------ | ------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| **className** | `String` | | Optionally pass additional class names to be added to the outermost parallax banner element. | | ||
| **disabled** | `Boolean` | `false` | Determines if the internal parallax layers will have offsets applied. | | ||
| **layers** | `Array` | | A required `Array` of `Objects` with layer properties: `[{ amount: 0.1, image: 'foo.jpg' }]`. [See layers prop below](#banner-layers-prop) | | ||
| **style** | `Object` | | Optionally pass a style object to be added to the outermost parallax banner element. | | ||
### Banner Layers Prop | ||
The `layers` prop takes an array of objects that will represent each image (or custom children) of the parallax banner. The following properties describe a layer object: | ||
| Name | Type | Default | Description | | ||
| ------------ | :-------: | :------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| **amount** | `Number` | | A value from `-1` to `1` that represents the vertical offset to be applied to the current layer, `0.1` would equal a `10%` offset on the top and bottom. | | ||
| **children** | `Element` | | Custom layer children provided as a React element, for example `<Video />` | | ||
| **expanded** | `Boolean` | `true` | Indicate if the layer should be expanded with negative top/bottom margins so the edges will never be visible. | | ||
| **image** | `String` | | Image source that will be applied as a CSS background image on the layer. | | ||
| **props** | `Object` | | Props to apply to the layer element. Example: `{ props: style: { background: 'red' }}` | | ||
## \<ParallaxProvider> | ||
The `<ParallaxProvider />` component is meant to wrap a top level component in your application and is necessary to provide access though React context API to the parallax controller. This component should only be used once in you app, for instance in an `<AppContainer />` component that won't be mounted/unmounted during route changes. Like so: | ||
```jsx | ||
const AppContainer = () => ( | ||
<ParallaxProvider> | ||
<Router> | ||
<App /> | ||
</Router> | ||
</ParallaxProvider> | ||
const HorizontalParallax = () => ( | ||
<Parallax translateX={['-100px', '200px']}> | ||
<div className="my-thing" /> | ||
</Parallax> | ||
); | ||
``` | ||
### ParallaxProvider Props | ||
## How it works | ||
The following props configure the `<ParallaxProvider>` component: | ||
TODO: **Explain how and when effects are applied** with some illustrations and demos. | ||
| Name | Type | Default | Description | | ||
| ------------------- | :-------: | :--------- | ------------------------------------------------------------------------------------------------------------ | | ||
| **scrollAxis** | `String` | `vertical` | Optionally pass the scroll axis for setting horizontal/vertical scrolling. One of `vertical` or `horizontal` | | ||
| **scrollContainer** | `Element` | `<body>` | Optionally set the container that has overflow and will contain parallax elements. Defaults to the HTML body | | ||
**Warnings:** | ||
### Parallax Controller Context | ||
1. This lib was designed to be used on `relative` or `absolute` positioned elements that scroll naturally with the page. If you use `fixed` positioning on either the element itself or the parent you will encounter issues. More on that in [troubleshooting](#troubleshooting). | ||
2. Scroll state and positions of elements on the page are cached for performance reasons. This means that if the page height changes (most likely from [images loading](#example-usage-of-context)) after `<Parallax />` components are mounted the controller won't properly determine when the elements are in view. To correct this you can call the `parallaxController.update()` method from any child component of the `<ParallaxProvider />` via context and the `withController()` HOC. More details on how here: [Parallax Controller Context](#parallax-controller-context). | ||
Access the controller via [React context](https://facebook.github.io/react/docs/context.html) in any components rendered within a `<ParallaxProvider>` by using the `withController()` HOC: | ||
```jsx | ||
import { withController } from 'react-scroll-parallax'; | ||
class MyComponent extends Component { | ||
static propTypes = { | ||
parallaxController: PropTypes.object, | ||
}; | ||
doSomething() { | ||
const { parallaxController } = this.props; | ||
// do stuff with `parallaxController` | ||
} | ||
} | ||
// Compose your component with the Higher Order Component | ||
export withController(MyComponent); | ||
``` | ||
Also `parallaxController` is accessible using `useController()` [React hook](https://reactjs.org/docs/hooks-intro.html) in components without writing a class or wrapping them in HOC. | ||
```jsx | ||
import { useController } from 'react-scroll-parallax'; | ||
const MyComponent = () => { | ||
const { parallaxController } = useController(); | ||
// do stuff with `parallaxController` | ||
return <div />; | ||
}; | ||
``` | ||
### Available Methods | ||
Access the following methods on `parallaxController` via context: | ||
**`update()`** | ||
Updates all cached attributes for parallax elements then updates their positions. | ||
**`destroy()`** | ||
Removes window scroll and resize listeners then resets all styles applied to parallax elements. | ||
### Example usage of context | ||
The most common use case that would require access to the controller is dealing with images. Since the controller caches attributes for performance they will need to be updated with the correct values once the image loads. Here's an example of how you could do that with an `<Image />` component: | ||
```jsx | ||
import { withController } from 'react-scroll-parallax'; | ||
class Image extends Component { | ||
handleLoad = () => { | ||
// updates cached values after image dimensions have loaded | ||
this.props.parallaxController.update(); | ||
}; | ||
render() { | ||
return <img src={this.props.src} onLoad={this.handleLoad} />; | ||
} | ||
} | ||
export withController(Image); | ||
``` | ||
If your parallax components are stuck and acting weird, this is most likely due to the fact that your page initial scroll was not at the top on load. Here's a possible solution to this problem using `useController()` hook. It can be used in your application top level component or specifically in the part of your application where you are experiencing problems. | ||
```jsx | ||
const ParallaxCache = () => { | ||
const { parallaxController } = useController(); | ||
useLayoutEffect(() => { | ||
const handler = () => parallaxController.update(); | ||
window.addEventListener('load', handler); | ||
return () => window.removeEventListener('load', handler); | ||
}, [parallaxController]); | ||
return null; | ||
}; | ||
// <ParallaxCache /> now can be used anywhere you have problems with cached attributes | ||
``` | ||
## Troubleshooting | ||
@@ -278,6 +121,14 @@ | ||
React Scroll Parallax uses a single [passive scroll listener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Improving_scrolling_performance_with_passive_listeners) (dependent on browser support) with the minimal amount of work done on the scroll event to prevent [jank](http://jankfree.org/) (calculations that cause layout, reflow and paint are cached initially and only updated when layout changes). Request animation frame is then used to decouple the scroll handler and further reduce jank. All offsets are applied with 3D transforms to utilize the GPU and prevent paints. If you have ideas to further optimize scrolling please PR or post an issue. | ||
Considerations to have been taken to reduce jank -- [please read more here](https://github.com/jscottsmith/parallax-controller#optimizations-to-reduce-jank) on how this is done | ||
### **PSA** | ||
Even with these optimizations scroll effects can cause jank. If you use this lib make sure to keep images small and optimized, reduce the number of moving elements in view and on the page in total, and disable scroll effects on mobile devices. That should keep scrolling smooth and users happy. | ||
Even with optimizations _scroll effects can cause jank_. It's also important to keep in mind that scroll effects are usually not critical to a users experience and sometimes can be annoying. | ||
If you use these components make sure you seriously consider the following: | ||
- Keep images small (do not use inappropriately high resolutions) and optimized (use appropriate compression) | ||
- Reduce the number of scroll effects on elements in view and on the page in total | ||
- Disable the use — or limit the amount — of scroll effects for users on mobile devices | ||
Follow the above and you should keep scrolling smooth and users happy. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
130962
27
38
1702
3
129
1
1
+ Addedparallax-controller@0.1.11
+ Addedparallax-controller@0.1.11(transitive)
- Removedprop-types@^15.5.10
- Removedobject-assign@4.1.1(transitive)
- Removedprop-types@15.8.1(transitive)
- Removedreact-is@16.13.1(transitive)