Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Media Queries inside a React Styled Components Keyframe?

I can get media queries to work properly inside a regular styled-components component however when I attempted to use it in a keyframe (via import from styled-components) it does not seem to work at all.

Attempting to get a div to animate to a specific position, but have that end position change when the window is < 800px, I've attempted this:

import styled, { keyframes } from 'styled-components';

// ... further down ...

const slideAnim = keyframes`
  100% {
    top: 20px;
    left: 30px;
  }

  @media (max-width: 800px) {
    top: 70px;
    left: 50px;
    }

`;

I have also tried putting the media query in the 100% block:

const slideAnim = keyframes`
  100% {
    top: 20px;
    left: 30px;

    @media (max-width: 800px) {
       top: 70px;
       left: 50px;
    }
  }
`;

I made a helpful interactive demonstration of what I am trying to achieve (problem code is at line 24): https://codesandbox.io/embed/fragrant-star-m71ct

Feel free to change the breakpoint variable from 800 if you need to.

Any help is appreciated!

like image 240
damon Avatar asked Aug 19 '19 22:08

damon


People also ask

Can I use media query with styled-components?

To apply the media query in a styled component just add it to the styling.

Can you use keyframes in styled-components?

CSS animations with keyframes can be easily done with styled-components and the helper utility keyframes . The code is cleaner, not scattered around the application and more performant than other CSS solutions.

Is styled-components deprecated?

As of styled-components v4 the withComponent API is now a candidate for deprecation. In all likelihood, you probably want to use the new "as" prop to simply switch what element/component being rendered since the withComponent API is destructive toward styles if the lowest-wrapped component is a StyledComponent.

What is usemediaquery component in react?

The useMediaQuery Component is a CSS media query hook for React. Using this functionality, we can write our own CSS media query for which this function looks for a match, and it renders if the query matches. Material UI for React has this component available for us, and it is very easy to integrate.

Can I use media queries in a keyframe?

I can get media queries to work properly inside a regular styled-components component however when I attempted to use it in a keyframe (via import from styled-components) it does not seem to work at all. Attempting to get a div to animate to a specific position, but have that end position change when the window is < 800px, I've attempted this:

How to set media queries inline in react-responsive?

If you have a special cases, when you need to get media query result inside you react app (for example, you want to show some component at mobile version), you can use helpers like react-responsive or react-media-hook. You cannot set media queries inline. You will need to create a separate CSS stylesheet and then import the stylesheet.

How do media queries with styled components work?

Media queries with styled components work the same as in CSS! If you want a more involved example with defining different device sizes, continue below. We'll start from a simple webpage that is not responsive and improve it wth media queries! Checkout the code on Code Sandbox. So how to make it responsive using styled components?


2 Answers

You could take a different approach, where your keyframes animation is instead defined as a function like this:

const slideAnim = (top, left) => keyframes`
  100% {
    top: ${ top };
    left: ${ left };
  }  
`;

The function accepts input parameters that dictate the destination coordinates of top and left for that animation's final keyframe.

In your stlyed component (ie Box1), you'd then invoke slideAnim() with specific coordinates to each breakpoint, to achieve different animation behavior per breakpoint:

/*
Declare responsive styling in the Box1 component, where destination
coordinates are specified for the animate on a per-breakpoint-basis
*/
const Box1 = styled.div`
  width: 20px;
  height: 20px;
  background-color: blue;
  position: absolute;
  left: -100px;
  top: 80px;

  &.slide {

    animation: ${slideAnim('20px', '30px')} 0.4s ease-in-out forwards;

    @media (max-width: ${breakpoint}px) {
      animation: ${slideAnim('70px', '50px')} 0.4s ease-in-out forwards;
    }    
  }
`;

In summary, the idea is to shift the responsive styling into your styled component (ie Box1), while defining a reusable function that contains the common/shared keyframes for each responsive breakpoint.

Here's a working example - hope that helps!

like image 56
Dacre Denny Avatar answered Sep 30 '22 02:09

Dacre Denny


A more developed approach to use media queries with styled-components

firstly we define the screen size for each device:

const size = {
  mobile: "320px",
  tablet: "768px",
  laptop: "1024px",
  desktop: "2560px",
}

then we use css imported from styled-components to address media queries in relevant constants for each device

export const mobile = (inner) => css`
  @media (max-width: ${size.mobile}) {
    ${inner};
  }
`;
export const tablet= (inner) => css`
  @media (max-width: ${size.tablet}) {
    ${inner};
  }
`;
export const desktop= (inner) => css`
  @media (max-width: ${size.desktop}) {
    ${inner};
  }
`;
export const laptop= (inner) => css`
  @media (max-width: ${size.laptop}) {
    ${inner};
  }
`;

now lets say you are creating a styled div and you want to use media queries it. and based on the accepted answer to use keyframes

const slideAnim = (top, left) => keyframes`
  100% {
    top: ${ top };
    left: ${ left };
  }  
`;
const StyledDiv= styled.div`

 /* ...css */

    animation: ${slideAnim('20px', '30px')} 0.4s ease-in-out forwards;

   ${mobile(css`
     width:300px;
     animation: ${slideAnim('10px', '20px')} 0.1s ease-in-out forwards;
      /* ...css */
   `)};

   ${tablet(css`
     width:500px;
      /* ...css */
   `)};

    /*... and so on */
`;
like image 1
Safi Habhab Avatar answered Sep 30 '22 03:09

Safi Habhab