Framer motion layout animation fails to account for page scrolling during transitions in NextJs routes

Currently, I am working on a fascinating NextJS project that showcases a series of interactive blocks. As the user navigates through the app, these blocks dynamically adjust their size and position on the screen.

To achieve this effect, I'm leveraging the power of framer-motion's layout feature. Everything works seamlessly except for one scenario: when users have scrolled down the page, it seems like framer-motion disregards the scroll position and animates the blocks from their original top-of-page location.

If you're curious to see this behavior in action, check out this interactive demo on codesandbox:

  1. Try selecting the first block without scrolling - notice how it animates flawlessly.
  2. Now, scroll all the way down and select the last block. You'll observe that instead of animating from its current viewport position, the block appears to animate from beneath the screen.

Is there a workaround to account for the scroll distance so that the animations are tied to the viewport's coordinates rather than the page's top? Your insight would be greatly appreciated!

For visual reference, take a look at this example:

Answer №1

It seems like the issue arises from changing routes, resulting in a smaller viewport for the new route. Although not ideal, one potential solution could involve saving the body height of the card list page and using it as the minimum height for the card detail page. This height adjustment can be removed once the layout animation is complete:

To implement this, begin by encapsulating the <Link> component within a custom wrapper called <CardRedirector>:

          <CardRedirector>
            <Link href={`/${card.id}`} scroll={false}>
              <p>{card.title}</p>
              <Block id={card.id} />
            </Link>
          </CardRedirector>

Within the <CardRedirector>, incorporate the use client hook to establish a click listener that saves the current body height as the minimum body height when the link is clicked:

"use client";

export const CardRedirector = ({ children }) => {
  const onCardClick = () => {
    const currentBodyHeight = document.body.scrollHeight;
    document.body.style.minHeight = `${currentBodyHeight}px`;
  };

  return <button onClick={onCardClick} style={{
    background: 'none',
    color: 'inherit',
    border: 'none',
    padding: '0',
    font: 'inherit',
    cursor: 'pointer',
    outline: 'inherit',
  }}>{children}</button>;
};

export default CardRedirector;

Next, on the card detail page, wrap the <Block> component with <BlockContainer> to leverage the use client hook and attach an event listener onLayoutAnimationComplete to remove the min-height property upon completion of the animation:

"use client";

import Block from "./block";

export const BlockContainer = ({ id }) => (
  <Block
    id={id}
    fixed="true"
    onLayoutAnimationComplete={() => {
      document.body.style.minHeight = "0";
    }}
  />
);

export default BlockContainer;

Finally, update the card detail page code as follows:

export const BlogPostPage = async ({ params }) => {
  const id = Number(params.slug);

  if (!id) return notFound();

  return (
    <>
      <BlockContainer id={id} />
      <Link href="/" scroll={false}>
        Back
      </Link>
    </>
  );
};

For the modified sandbox version, visit the following link:

https://codesandbox.io/p/devbox/next-js-with-framer-motion-example-forked-m7d5ss?layout=.......

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

There is no response provided by the function

Here is the code for inserting data into the database. However, it seems to be going into the else section as the response is empty. I have checked by alerting the response, but it remains empty. // Function to add donation via AJAX function ccjkfound ...

When sending strings through an ajax call, spaces are getting converted to "'+'"

In my attempt to utilize AJAX for sending a POST request with multiple strings as parameters, I encountered an issue. The strings I am sending sometimes contain spaces. However, upon receiving the POST on the C# server side, I noticed that the string com ...

Extract several "documents" from one compilation

To easily convert my code into a single module using webpack, I can use the following method: { entry: path.join(__dirname, 'src/index.js'), output: { path: path.join(__dirname, 'dist'), filename: 'bundle.js', ...

"Utilize AJAX to submit the value of the text box input from a jQuery slider when the Submit Button

Whenever I adjust the sliders, the value is shown in an input textbox. However, when I move the slider and check the values echoed from the textboxes on another PHP page, they are always displaying as 0. Even after clicking the submit button, it still echo ...

Creating a Basic jQuery AJAX call

I've been struggling to make a simple jQuery AJAX script work, but unfortunately, I haven't had any success so far. Below is the code I've written in jQuery: $(document).ready(function(){ $('#doAjax').click(function(){ alert ...

Executing Ajax requests to interact with a RESTful API

After developing a back end REST API using Slim Framework and closely following the REST format, I ran into an issue when working on the Front End. It seems that AJAX functions well with parameters but not paths. I am considering outsourcing or creating a ...

Discovering the value of an object through its prototypes

Is it possible to create a function that can locate the value "5" within an object's prototype? What is the proper algorithm to achieve this? var rex = { "Name": "rex", "Age": 16, } te = { "to": 5, } rex.te = Object.create(te); function findValu ...

What is the best way to require users to click one of the toggle buttons in a form?

Is it possible to require the user to click one of the toggle buttons in a React form? I want to display an error if the user tries to submit the form without selecting a button. Even though I tried using "required" in the form, it didn't work as expe ...

testing exceptions with Jest: a step-by-step guide

As a beginner with Jest, I am currently working on a program to delve deeper into JavaScript. While my tests are functioning properly, I'm wondering if it would be better to replace the try/catch blocks with exceptions. I feel like there might be a mo ...

I possess a JSON array object and need to identify and extract the array objects that contain a specific child node

const jsonArray = { "squadName": "Super hero squad", "homeTown": "Metro City", "formed": 2016, "secretBase": "Super tower", "active": true, "members": [ { "name": "Molecule Man", "age": 29, "secretIdent ...

JQuery enables nested sorting functionality

I need to enable the sortable feature specifically for the charts. Index.cshmtml <div id="sortable" class="col-lg-9"> <div class="col-lg-12 col-md-12 padding hidden" id=@($"chartNumber{Model.Charts[ ...

Experiencing a 404 ERROR while attempting to submit an API POST request for a Hubspot form within a Next.js application

Currently, I am in the process of developing a Hubspot email submission form using nextjs and typescript. However, I am encountering a couple of errors that I need help with. The first error pertains to my 'response' constant, which is declared b ...

Loading identical code in two different div elements

I am in the process of designing a comprehensive resource database featuring a side-scrolling container. Once a user clicks on a thumbnail within the container, the contents of a corresponding div will fade in and display specific category content. Each di ...

Creating a multi-tiered cascading menu in a web form: Harnessing the power of

In my form, there is a field called 'Protein Change' that includes a multi-level dropdown. Currently, when a user selects an option from the dropdown (for example, CNV->Deletion), the selection should be shown in the field. However, this function ...

Using Tailwind CSS to center a NexJS <Image /> component within a modal

In an effort to style my MapBoxGL popup content, I am working on aligning the text above the image to the left and centering the image below within the popup. As shown in the image below, this is currently proving to be a challenge as I transition from usi ...

The VueJS component from a third-party source is not located in the node_modules directory

Utilizing vue-cli version 3 for a fresh vuejs project (I've been dedicating ample time to learning vuejs, but this marks my initial attempt at integrating a third-party component). I'm aiming to incorporate a visually appealing grid component. Th ...

Ways to automatically close the external window upon logging out in Angular 12

I have successfully created an external window in my Angular application. Everything is working as expected, but I am facing an issue when trying to automatically close the external window upon user logout. Although I have written the code below and it wo ...

Actions cannot be performed on elements generated by ng-repeat

I am facing a challenge where I need to display a list of languages on a page, allowing users to change their selections based on previous choices. To achieve this functionality, I have written the following code snippet: ... <tbody> & ...

Instructions on how to modify a document's content by its unique identifier using Firebase Modular SDK (V9)

I am trying to figure out how to update an existing document for the same user ID in V9 Firebase whenever they log in, rather than creating a new one each time. Any suggestions on how to achieve this? Current Code setDoc( query(collectionRef), // ...

Creating a stylish navigation bar with custom components using Material UI and React

I've been experimenting with the BottomNavigation component from Material UI, but instead of using labels and text, I want to incorporate custom-made ImageButton components. Here's the code snippet from Material UI: import React from 'rea ...