网站搜索

css - 样式化组件:通过 props 传递的 hover 样式


我有一个 StyledButton,我像这样使用它:

const StyledButton = styled.div<{
  hoverStyle?: CSSProperties
}>`
  color: black;
  background: blue;

  // What can I do here to apply the hoverStyle?
`

<StyledButton
  hoverStyle={{
    backgroundColor: 'red',
    color: 'white',
  }}
>
  My button
</StyledButton>

有办法做到吗?

答案#1

通常我们会在额外的样式属性中提供单个值,但仍然绝对可以提供一组 CSS 规则(CSS 对象)。

首先,你需要使用插值函数根据运行时属性调整样式:

const StyledButton = styled.div<{
  hoverStyle?: CSSProperties
}>`
  color: black;
  background: blue;

  // What can I do here to apply the hoverStyle?
  ${(props) => props.hoverStyle && inlineRules(props.hoverStyle)}
`

在这里,我使用了一个 inlineRules 函数将 CSSObject 转换为规则列表:

function inlineRules(rulesObj: CSSProperties) {
  return Object.entries(rulesObj).map(([property, value]) => `${property}: ${value};`).join('');
}

然后,基于你样式属性的 “hoverStyle” 名称,这些规则似乎应该仅在 :hover 时应用,而不是直接与你的 <div> 的根样式合并。在这种情况下,你需要将它们放入嵌套块中,你可以使用 & 符号来引用自身样式:

& 单个与号指代组件的所有实例;它用于应用广泛的覆盖

  &:hover {
    ${(props) => props.hoverStyle && inlineRules(props.hoverStyle)}
  }

CodeSandbox 上的实时演示:https://codesandbox.io/s/sleepy-brook-h515v7?file=/src/App.tsx

注意:styled-components 中的 CSS 规则实际上使用普通的“kebab-case”表示法,而 CSSProperties 则定义为 camelCase(在你的例子中是“background-color”与“backgroundColor”)。在上面的演示中,我使用了模板字面量转换类型,将它们转换为 kebab-case,这是基于 TypeScript 从实际的 camelCase 键生成 kebab-case 类型的方式。