Search code examples
javascriptcssreactjsemotion

Merge a single CSS property in Emotion


I'm trying to create reusable animations in Emotion but have run into some issues. I've defined an animation for a fadeUp effect which works fine.

export const animatedFadeUp = css`
  opacity: 1;
  transform: translateY(0);
`;

export const fadeUp = css`
  opacity: 0;
  transform: translateY(var(--spacing-medium));
  transition: opacity 0.5s ease-in-out,
    transform 0.5s ease-in-out;

  html.no-js & {
    ${animatedFadeUp}
  }
`;

But when i try to apply the fadeUp animation to an element that already has the transition defined it gets overruled. For example the button below. The transition will be overruled by the button.

const Button = styled.button`
  ${fadeUp}
  background: orange;
  transition: background-color 0.5s ease-in-out;

  &:hover,
  &:focus {
    background: gold;
  }
`;

Is there a solution to combine only a single property? Something like:

const Button = styled.button`
  ${fadeUp}
  background: orange;
  transition: ${fadeUp.transition},
    background-color 0.5s ease-in-out;

  &:hover,
  &:focus {
    background: gold;
  }
`;

Solution

  • Instead of passing it as a CSS tagged template literals or using styled components, you may use it as CSS object. By using as such, it would be more flexible and easier to refer their properties.

    <p
      css={{
        color: 'red'
     }}
    >Hello World</p>
    

    So your code would become

    export const animatedFadeUp = {
      opacity: 1,
      transform: 'translateY(0)',
    };
    
    export const fadeUp = {
      opacity: 0,
      transform: 'translateY(var(--spacing-medium))',
      transition: `opacity 0.5s ease-in-out,
        transform 0.5s ease-in-out`,
    
      ['html.no-js &']: {
        ...animatedFadeUp
      }
    };
    
    const App = () => (
      <button
        css={{
          ...fadeUp,
          background: 'orange',
          transition: `${fadeUp.transition},
            background-color 0.5s ease-in-out`,
    
          ['&:hover']: {
            background: 'gold',
          },
          ['&:focus']: {
            background: 'gold',
          }
        }}
      >Click Me</button>
    )