Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
November 28, 2020 02:18 pm GMT

Collapsing Page Effect

Fun with the Logout Animation

The other day I was working on my startup, and wanted to spice things up
a bit so I created a collapsing page animation for the logout functionality.
Nothing fancy, some CSS transition animation. But when I posted it on Twitter,
it got viral, especially after it was retweeted by Smashing Magazine.

Collapsing page effect animation

I was totally mind-blown by the engagement, and all the positive feedback
(this was my first viral content). Many of the people asked me to share the code,
but instead of just publishing it on github (which I did, and you can access it as
a NPM package here - available both for React or plain JavaScript) I decided to write a brief article about it.

The Not-So-Complicated Code

As a start, I wanted body's all child elements to collapse, and also all div's.
I didn't want to put animation on all elements (eg. headers, links, buttons etc)
because I felt it would make the animation too fractured.

const elements = document.querySelectorAll('body > *, body div');
Enter fullscreen mode Exit fullscreen mode

To make sure that the page doesn't get scrolled, I set the position to fixed.
I also disabled pointer events, so no clicks or other events get triggered
during the animation:

document.body.style.overflow = 'hidden';document.body.style.pointerEvents = 'none';
Enter fullscreen mode Exit fullscreen mode

Finally, before dealing with the actual, I had to measure the total height
of the page (to know, how much should the items "fall" to ensure that all items
will be out of the screen at the end):

const body = document.body;const html = document.documentElement;const height = Math.max(  body.scrollHeight,  body.offsetHeight,  html.clientHeight,  html.scrollHeight,  html.offsetHeight,);
Enter fullscreen mode Exit fullscreen mode

So the animation is actually super simple: just loop through the selected
elements and generate some semi-random values, then add them as CSS attributes:

[...elements].forEach(element => {  const delay = Math.random() * 3000); // wait between 0 and 3 seconds  const speed = Math.random() * 3000 + 2000; // speed between 2 and 5 seconds  const rotate = Math.random() * 30 - 15; // rotate with max 15 degrees to either direction  const moveX = Math.random() * 160 - 80; // move with 80px to either direction  element.style.transition = `transform ${speed}ms ease-out`;  element.style.transitionDelay = `${delay}ms`;  element.style.transform = `translateY(${height * 1.5}px) translateX(${moveX}px) rotate(${rotate}deg)`;});
Enter fullscreen mode Exit fullscreen mode

This loop just goes through every element and assigns random values for them.

All of the elements will be transitioned downward with the height of the screen,
therefore even the ones at the top of your page will end up out of the screen at the end.

Finally, I wanted to keep one item that stayed on the screen behind the collapsing page:

There are a few important things with it:

  • it should be a child of the body, so it's parent element is not collapsing
  • it should have fixed position
  • to achieve the effect that it's in the background behind everything else, you can adjust the z-index

And then just ignore it and it's children elements in the forEach loop:

// Identify the logout screen that should stay in placeconst logoutEl = document.querySelector('#logout-screen');// Function that tells if an element is a// descendant (children, grandchildren etc) of another elementconst isDescendant = (parent, child) => {  let node = child.parentNode;  while (node !== null) {    if (node === parent) {      return true;    }    node = node.parentNode;  }  return false;};// And the updated forEach loop:[...elements].forEach(element => {  if (element === logoutEl || isDescendant(logoutEl, element)) {    element.style.pointerEvents = 'all'; // this element should detect clicks    return; // don't continue adding the animation  }  // ... add the animation for the other items});
Enter fullscreen mode Exit fullscreen mode

This is the basic logic, it's quite simple and all animations are handled by CSS transitions.

Here's the final code:

function collapsePage() {  const elements = document.querySelectorAll('body > *, body div');  const logoutEl = document.querySelector('#logout-screen');  const body = document.body;  const html = document.documentElement;  const height = Math.max(    body.scrollHeight,    body.offsetHeight,    html.clientHeight,    html.scrollHeight,    html.offsetHeight,  );  document.body.style.overflow = 'hidden';  document.body.style.pointerEvents = 'none';  const isDescendant = (parent, child) => {    let node = child.parentNode;    while (node !== null) {      if (node === parent) {        return true;      }      node = node.parentNode;    }    return false;  };  [...elements].forEach(element => {    if (element === logoutEl || isDescendant(logoutEl, element)) {      element.style.pointerEvents = 'all';      return;    }    element.style.pointerEvents = 'none';    const delay = Math.random() * 3000; // wait between 0 and 3 seconds    const speed = Math.random() * 3000 + 2000; // speed between 2 and 5 seconds    const rotate = Math.random() * 30 - 15; // rotate with max 10 degrees    const moveX = Math.random() * 160 - 80; // move with 50px to either direction    element.style.transition = `transform ${speed}ms ease-out`;    element.style.transitionDelay = `${delay}ms`;    element.style.transform = `translateY(${height *      1.5}px) translateX(${moveX}px) rotate(${rotate}deg)`;  });}
Enter fullscreen mode Exit fullscreen mode

Things to Consider

After the animation is done, all your elements will still be available in the DOM,
just transitioned out of the screen. It is not a problem if you will navigate to
another page after, but it might cause unexpected behavior if you use some
libraries that handle the navigation for you (eg. react-router-dom).

To solve this issue, I added a reset function to the component, that is triggered
on unmounting.


You can grab the whole code as an NPM package - it can be used both as a React component or as a standalone JavaScript function.

While this animation can bring some unexpected delight to your users, be careful with it.
Don't overuse, as the animation takes a few seconds each time. I recommend only using it for logouts,
or when the user deletes something in your web-app (eg. a large project, or even the user's profile).


Original Link: https://dev.to/johnnyfekete/collapsing-page-effect-332a

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To