Skip to main content
Community Plugin
View plugin on GitHub
See starters using this

gatsby-plugin-transitions enables animated page-transitions. It uses react-spring for smooth, customizable animations.

  • Default animation for every page-transition
  • Define per link animations additionally
  • Two animation-modes: successive (animate out, then animate in) and immediate (in and out at the same time)
  • Restores scroll-position on traversing browser-history

NPM JavaScript Style Guide

🚀 Have a look at the example!

This Project is under development. Please join and contribute!

Install

Install all dependencies via Yarn or NPM.

yarn add gatsby-plugin-transitions gatsby-plugin-layout react-spring react react-dom

Usage

1. Register gatsby-plugin-layout

Register gatsby-plugin-layout in your gatsby-config.js:

module.exports = {
  plugins: ["gatsby-plugin-layout"]
};

2. Disable default scroll-to-top

Copy this into your gatsby-browser.js:

exports.shouldUpdateScroll = () => {
  return false;
};

3. Create default Layout-file

Activate gatsby-plugin-layout. Either do it your own way, or take the default way:

  • Create the folder src/layouts and the file src/layouts/index.js.
  • Here you need to wrap all children into the components TransitionProvider and TransitionViews.
import React from "react";
import { TransitionProvider, TransitionViews } from "gatsby-plugin-transitions";

const Layout = ({ location, children }) => {
  return (
    <TransitionProvider location={location}>
      <TransitionViews>
        {children}
      </TransitionViews>
    </TransitionProvider>
  );
};

export default Layout;

🎉 Voila! You have smooth animated page-transitions! Now customize these!

4. Customize!

import React, { useState } from "react";
import { TransitionProvider, TransitionViews } from "gatsby-plugin-transitions";
// Example Header-Component (see below)
import Header from "./header";

const Layout = ({ location, children }) => {
  return (
    <TransitionProvider
      location={location}
      mode="immediate"
      enter={{
        opacity: 0,
        transform: "translate3d(0,20vh,0) scale3d(1, 1, 1) rotate(0deg)",
        config: {
          mass: 1,
          tension: 210,
          friction: 20,
          clamp: true
        },
        onRest: () => {
          console.log("Hello, World!");
        }
      }}
      usual={{
        opacity: 1,
        transform: "translate3d(0vh,0vh,0) scale3d(1, 1, 1) rotate(0deg)"
      }}
      leave={{
        opacity: 0,
        transform: "translate3d(0vh,0vh,0) scale3d(2, 2, 1) rotate(180deg)",
        config: {
          duration: 1000
        }
      }}
    >
      // This Header is an example for a component, that should remain between routes
      <Header />
      <TransitionViews>
        {children}
      </TransitionViews>
    </TransitionProvider>
  );
};

export default Layout;

TransitionProvider

List of props:

Name Type Default Description
location Object null required. Gatsby’s location-object.
mode String 'successive' Transition-mode: 'successive' or 'immediate'
enter object { opacity: 0, config: 'stiff' } From-values, when the view is entering. Accepts also callbacks and react-spring-config.
usual object { opacity: 1 } Normal state of the view.
leave object { opacity: 0, config: 'stiff' } To-Values, when the view is leaving. Accepts also callbacks and react-spring-config.
style object null Style the views-wrapper (which is a div with class views).

Transition-Mode

  • successive: Wait till previous view has disappeared.
  • immediate: Next view is entering while previous view is disappearing.

Default-Springs

You can enter default-springs for all animation-states. These props accept a regular react-spring-object. Animated are currently only the keys opacity and transform.

enter

From-values, when the view is entering.

  • Props: opacity, transform,
  • Callbacks: onStart, onFrame, onRest
  • Config: react-spring-config-object

usual

Normal animation-state of the view.

  • Props: opacity, transform,
  • Callbacks: none
  • config: none — define with enter and leave!

leave

To-Values, when the view is leaving.

  • Props: opacity, transform,
  • Callbacks: onStart, onFrame, onRest
  • Config: react-spring-config-object

config

The key config can be either a regular react-spring-config-object.

Or pass in the name of a react-spring-default (default, gentle, wobbly, stiff, slow, molasses) as string.

gatsby-plugin-transition works out of the box with Gatsby’s default Link-component. If you want to apply custom animations to certain links, use TransitionLink.

import React from "react";
import { TransitionLink } from "gatsby-plugin-transitions";

const MyComponent = () => (
  <div className="content content--1">
    <h1>gatsby-plugin-transitions</h1>
    <p>Transitions are easy.</p>
    <p>Now go build something great.</p>
    <TransitionLink
      to="/page-2"
      style={{ color: "red" }}
      className="my-custom-link"
      leave={{
        opacity: 0,
        transform: "translate3d(100vh,0vh,0)",
        config: { mass: 1, tension: 180, friction: 12, clamp: true }
      }}
      enter={{
        opacity: 0,
        transform: "translate3d(100vh,0vh,0)",
        config: "stiff",
        onRest: () => {
          console.log("Hello, World!");
        }
      }}
      usual={{
        transform: "translate3d(0vh,0vh,0)",
        opacity: 1
      }}
      mode="immediate"
      y={() => window.scrollY}
    >
      I have a special animation!
      <br />
      And mode 'immediate'!
      <br />
      Go to page 2
    </TransitionLink>
  </div>
);

export default MyComponent;

List of props:

Name Type Default Description
to Object '' required. Pathname of your link-target.
mode String 'successive' Transition-mode: 'successive' or 'immediate'
enter object { opacity: 0, config: 'stiff' } From-values, when the view is entering
usual object { opacity: 1, config: 'stiff' } Normal state of the view.
leave object { opacity: 0, config: 'stiff' } To-Values, when the view is leaving.
y number or function 0 Scroll position of the next view. If function, it must return a number (for example current window.scrollY).
style object null Style the Link.

🔥TransitionLink can only be used in components, that are children of TransitionProvider!

useTransitionStore

A hook, that exposes the plugin’s state-management. It returns an Array with 2 elements:

  1. state of type object
  2. dispatch of type function

Get some useful information from the module’s store! For example get the current location-object:

import React from "react";
import { useTransitionStore } from "gatsby-plugin-transitions";

const MyComponent = () => {
  const [{ currentLocation }] = useTransitionStore();
  return <h1>{currentLocation.pathname}</h1>;
};

export default MyComponent;

🔥useTransitionStore can only be used in components, that are children of TransitionProvider!

To navigate programmatically you need to dispatch the NAVIGATE-action from the TransitionStore. It takes the same props as TransitionLink.

Example: Navigate, when the user scrolls to the bottom of the page:

import React, { useEffect, useState } from "react";
import { useTransitionStore } from "../transitions";

const MyComponent = () => {
  const [, dispatch] = useTransitionStore();
  useEffect(() => {
    function onScroll() {
      if (
        window.innerHeight + window.pageYOffset >=
        document.body.offsetHeight - 2
      ) {
        dispatch({
          type: "NAVIGATE",
          to: "/another-page",
          leave: {
            opacity: 0,
            transform: "translate3d(0, -50vh, 0)",
            config: "stiff"
          },
          y: 500
        });
      }
    }
    window.addEventListener("scroll", onScroll);
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  return (
    <div className="content" style={{ minHeight: "300vh" }}>
      <h1>Scroll down to navigate!</h1>
    </div>
  );
};

export default MyComponent;

🔥 Caution 🔥

Keep animated props consistent!

react-spring needs consistent props and transform-units. So if you for example once animated opacity, always write it, even if it does not get changed!

import React from "react";
import { TransitionLink } from "gatsby-plugin-transitions";

const MyComponent = () => (
  <TransitionLink
    to="/page-2"
    style={{ color: "red" }}
    className="my-custom-link"
    leave={{
      opacity: 0,
      transform: "translate3d(100vh,0vh,0)"
    }}
    enter={{
      opacity: 0,
      transform: "translate3d(100vh,0vh,0)"
    }}
    usual={{
      opacity: 1
      transform: "translate3d(0vh,100vh,0)",
    }}
    mode="immediate"
    y={1000}
  >
    I have a special animation!
  </TransitionLink>
);

export default MyComponent;

Use clamp: true to speed up your animations!

Spring-Animations “wobble”, which takes extra time. To make the animations snappier, define clamp: true in the config-object.

To-Do

  • Testing

Contributing

Every contribution is very much appreciated.

😍 If you like gatsby-plugin-transitions, star it on GitHub!

License

MIT © AndreasFaust