JoshWComeau

FadeIn

Filed under
Snippets
on
in
May 8th, 2020.
May 2020.
// FadeIn.js
import React from 'react';
import styled, { keyframes } from 'styled-components';

const fadeIn = keyframes`
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
`;

const FadeIn = ({
  duration = 300,
  delay = 0,
  children,
  ...delegated
}) => {
  return (
    <Wrapper
      {...delegated}
      style={{
        ...(delegated.style || {}),
        animationDuration: duration + 'ms',
        animationDelay: delay + 'ms',
      }}
    >
      {children}
    </Wrapper>
  );
};

const Wrapper = styled.div`
  @media (prefers-reduced-motion: no-preference) {
    animation-name: ${fadeIn};
    animation-fill-mode: backwards;
  }
`;

export default FadeIn

Link to this headingContext

Often, we aren't able to render all the content on a page in the initial paint:

  • We might be fetching that data from an API.
  • As seen in The Perils of Rehydration, we can't render user-specific content when server-side rendering with something like Gatsby.
  • We might toggle between different UI elements depending on user state (eg. different calendar views).

It can be jarring for users when things snap into existence; if that happened in real life, it would be terrifying! Our brains are used to things transitioning.

<FadeIn> is a utility component to quickly add a fade-in animation for an element (or group of elements).

Link to this headingDemo

Click the button to re-load my 3D avatar:

Link to this headingUsage

// Wrap whatever elements you want in a `<FadeIn>` wrapper:
<FadeIn>
  <SomeBitOfUI />
</FadeIn>

// Render conditionally to fade on every re-enter
{someBoolean && (
  <FadeIn>
    <ThingToShow />
  </FadeIn>
)}

// Customize `duration` and `delay`
<FadeIn delay={250} duration={450}>
  <p>Slightly later and longer animation</p>
</FadeIn>

Link to this headingExplanation

  • In this example we're using styled-components(opens in new tab), though the same approach will work regardless of your styling preferences. With vanilla CSS, you'd use a @keyframes animation.
  • We wrap our animation inside a prefers-reduced-motion media query. This is to be mindful of folks with vestibular disorders. Much more context available in the Accessible Animations with React tutorial.
  • animation-fill-mode: backwards ensures that our content is invisible before the animation begins, if a non-zero delay is passed. If we had a 500ms delay, for example, our content would be totally visible for that first half-second before fading in. animation-fill-mode: backwards applies the initial condition (opacity: 0) backwards in time ⏳
  • We delegate all unrecognized props. This is done to make our life a little bit easier if, say, we want to pass an ID to the wrapper for testing, or wrap this element in a styled-component.

Last updated on

May 8th, 2020

# of hits