在情感中合并单个CSS属性

Merge a single CSS property in Emotion

我正在尝试在 Emotion 中创建可重复使用的动画,但 运行 遇到了一些问题。我已经为 fadeUp 效果定义了一个动画,效果很好。

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}
  }
`;

但是当我尝试将 fadeUp 动画应用于已经定义了过渡的元素时,它被否决了。例如下面的按钮。 transition 将被 button 否决。

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

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

有没有办法只合并一个属性?类似于:

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

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

不太熟悉 Emotion 库,也许有一个 API 公开了样式值访问,就像您尝试使用 ${fadeUp.transition} 一样。但如果没有这样的 API 我也不会感到惊讶,因为它会增加库的复杂性。然而,希望并没有落空,在不了解 API 的情况下,我们仍然可以使用 javascript 支持的语言功能来解决这个问题。下面是一个例子:

import React, { useState } from 'react';
import styled from '@emotion/styled';
import { css } from '@emotion/react';

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

// Notice that the annoymous function is invoked immediately to get back an object
// with properties of `css` and `transition`, so that we can access them later
export const fadeUp = (() => {
  // By defining the transition value here, we can update the transition value in one
  // place instead of updating in multiple places, including the downstream consumers
  // of the returned object
  const transition = 'opacity 0.5s ease-in-out, transform 0.5s ease-in-out';

  return {
    css: css`
      opacity: 0;
      transform: translateY(25px);
      transition: ${transition};

      &.active {
        ${animatedFadeUp}
      }
    `,
    transition,
  };
})();

// Note that we need to access the `css` property explicitly here
// like this - ${fadeUp.css}
const Button = styled.button`
  ${fadeUp.css}
  background: green;
  transition: ${fadeUp.transition}, background-color 0.5s ease-in-out;

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

function App() {
  const [className, setClassName] = useState('');

  return (
    <div className="App">
      <Button className={className}>This my button component.</Button>

      <button onClick={() => setClassName(className ? '' : 'active')}>
        Toggle
      </button>
    </div>
  );
}

export default App;

简而言之,我们创建一个对象来保存 csstransition 的信息,以便我们以后使用它。这种方法的缺点是我们需要记住,当使用 fadeUp 时,我们必须通过显式访问 fadeUp.css 来区别对待它,这与其他 emotion 创建的 css 不同。 =18=]

您可以将其作为 CSS 对象使用,而不是将其作为 CSS 标记的模板文字或使用样式化的组件进行传递。通过这样使用,可以更灵活、更容易地引用它们的属性。

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

所以你的代码会变成

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>
)