5

I am new to building websites with Gatsby and thus React JS.

Problem

I want to make a simple animation based on the css transform property using react-spring. As I use styled-components (with theme.js file), I want the animation to be responsive depending on the breakpoint.

The problem is that react-spring will not accept an array, but rather only strings as e.g. "10px".


Responsive styles with react-components

Let's say I have following definition

const MyDiv = styled(animated.div)`
  height: 100px;
  ${width}
`;

and simply call the element like that

<MyDiv width={[50, 70]} />

As I've implemented breakpoints in my theme.js file, this works perfectly (using ThemeProvider from styled-components).

Animation on Button

Let's define the spring animation as follows:

const [showButton, setShowButton] = useState(false);
const clickState = useSpring({
  oi: showButton ? 0 : 1,
});
const divAnimation = {
  transform: clickState.oi.interpolate(oi => `translateX(${oi * 50}px)`),
};

and call it as

<Button onClick={setShowButton(!showButton)}>
  <MyDiv style={{ ...divAnimation }} />
</Button>

Responsive & animation

As indirectly mentioned above, I'd like to have a slightly different animation depending on the window width. So, I came up with some ideas how to implement that but none of that works.

The must be a possibility where the animation divAnimation shifts the div differently. Or not..?


Thanks in advance for your help.

Kind regards

.

.

.

post scriptum: Dependencies of that code

import React, { useState } from 'react';
import styled from 'styled-components';
import { width } from 'styled-system';
import { animated } from 'react-spring';¨
import { Button } from 'rebass';
Legalith
  • 51
  • 3

1 Answers1

1

Use window.matchMedia to call media queries inside JavaScript, then change your spring's input accordingly.

An example implementation as a custom hook:

const useMediaQuery = (minWidth: number) => {
  const [matches, setMatches] = useState(true);

  useEffect(() => {
    const mediaQuery = window.matchMedia(
      `screen and (min-width: ${minWidth}px)`
    );
    const listener = (ev) => {
      setMatches(ev.matches);
    };
    mediaQuery.addEventListener("change", listener);

    return () => {
      mediaQuery.removeEventListener("change", listener);
    };
  }, []);

  return matches;
};
John Smith
  • 3,863
  • 3
  • 24
  • 42