Emotion CSS-in-JS - 如何根据组件道具添加条件CSS?
Emotion CSS-in-JS - how to add conditional CSS based on component props?
我想要一个使用 Emotion 设置样式的组件,它采用最终控制样式的道具。例如,考虑一个 GridCol
组件,它有各种改变填充和宽度的道具(宽度可以在不同的视口宽度之间改变)。
我想像这样使用 API:
<GridCol gutter size="2>
// or alternatively, like this:
<GridCol gutter size={{
m: 2,
l: 4
}}>
这里发生了三件事:
gutter
是一个布尔值属性,它向列添加一些水平填充
size
道具可以是字符串或对象。如果它是一个字符串,我们只需添加几行 CSS 就可以了,但是,如果它是一个对象,我们需要插入一些基于在别处设置的断点对象的媒体查询。
Emotion's docs 不清楚如何处理这种性质的样式,至少我没见过,所以我希望能找到一个通用的解决方案。
对于 gutter
道具,这是微不足道的:
const GridCol = props => styled('div')`
display: block;
box-sizing: border-box;
flex: 1 0 0;
min-width: 0;
padding: ${props.gutter ? `0 10px` : '0'};
`
对于 size
道具,它变得更加复杂,我希望结果 CSS 看起来像这样:
const GridCol = props => styled('div')`
display: block;
box-sizing: border-box;
flex: 1 0 0;
min-width: 0;
padding: ${props.gutter ? `0 10px` : '0'};
/* styles here if `size` is a string */
width: 10%;
/* styles here if `size` is an object */
@media screen and (min-width: 500px) {
width: 20%;
}
@media screen and (min-width: 800px) {
width: 30%;
}
@media screen and (min-width: 1100px) {
width: 40%;
}
`
width
值将由道具的键决定,它对应于 breakpoints
对象中的一个值,这部分并不简单,但我不知道如何动态生成css 需要。
我确定我可以添加更多信息,我已经做了一些尝试,但 none 目前正在工作。我的感觉是我应该创建一个无状态功能组件,为每个条件生成 css,然后在最后加入 CSS..
这是一个很好的问题。首先,避免这种模式。
const GridCol = props => styled('div')`
display: block;
box-sizing: border-box;
flex: 1 0 0;
min-width: 0;
padding: ${props.gutter ? `0 10px` : '0'};
`
在这个例子中,每次渲染都会创建一个新样式的组件,这对性能来说很糟糕。
任何表达式或插值都可以是函数。此函数将接收 2 个参数:props
和 context
const GridCol = styled('div')`
display: block;
box-sizing: border-box;
flex: 1 0 0;
min-width: 0;
padding: ${props => props.gutter ? `0 10px` : '0'};
`
至于您示例中的 size
道具,我将使用以下模式。
import { css } from 'emotion'
const sizePartial = (props) => typeof props.size === 'string' ?
css`width: 10%;` :
css`
@media screen and (min-width: 500px) {
width: 20%;
}
@media screen and (min-width: 800px) {
width: 30%;
}
@media screen and (min-width: 1100px) {
width: 40%;
}
`
然后您可以像在表达式中出现的任何其他函数一样使用部分函数。
const GridCol = styled('div')`
display: block;
box-sizing: border-box;
flex: 1 0 0;
min-width: 0;
padding: ${props => props.gutter ? `0 10px` : '0'};
${sizePartial};
`
这是一个非常强大的模式,可用于在您的项目中编写可重用的动态样式。
如果您对利用此模式的其他库感兴趣,请查看
https://github.com/emotion-js/facepaint and https://github.com/jxnblk/styled-system
如果您正在寻找一种使用 Emotion 的 css
道具实现条件样式的方法,您可以这样做:
import { css } from '@emotion/core';
const styles = ({ isSelected }) => css`
border: solid 1px black;
border-radius: 10px;
padding: 16px;
cursor: pointer;
${isSelected === true &&
`
background-color: #413F42;
color: white;
`}
`;
const ConditionalComponent = () => {
const [isSelected, setIsSelected] = useState(false);
return (
<div css={styles({ isSelected })} onClick={() => setIsSelected(!isSelected)}>
Click here to change styles.
</div>
);
};
Emotion 有个帮手叫cx that provides functionality similar to the popular classnames库。您可以使用它更轻松地编写条件语句:
import { cx, css } from '@emotion/css'
const cls1 = css`
font-size: 20px;
background: green;
`
const foo = true
const bar = false
const SomeComponentWithProp = ({ foo }) => (
<div
className={cx(
{ [cls1]: foo === 'bar' },
)}
/>
);
(改编自链接文档)
我想要一个使用 Emotion 设置样式的组件,它采用最终控制样式的道具。例如,考虑一个 GridCol
组件,它有各种改变填充和宽度的道具(宽度可以在不同的视口宽度之间改变)。
我想像这样使用 API:
<GridCol gutter size="2>
// or alternatively, like this:
<GridCol gutter size={{
m: 2,
l: 4
}}>
这里发生了三件事:
gutter
是一个布尔值属性,它向列添加一些水平填充size
道具可以是字符串或对象。如果它是一个字符串,我们只需添加几行 CSS 就可以了,但是,如果它是一个对象,我们需要插入一些基于在别处设置的断点对象的媒体查询。
Emotion's docs 不清楚如何处理这种性质的样式,至少我没见过,所以我希望能找到一个通用的解决方案。
对于 gutter
道具,这是微不足道的:
const GridCol = props => styled('div')`
display: block;
box-sizing: border-box;
flex: 1 0 0;
min-width: 0;
padding: ${props.gutter ? `0 10px` : '0'};
`
对于 size
道具,它变得更加复杂,我希望结果 CSS 看起来像这样:
const GridCol = props => styled('div')`
display: block;
box-sizing: border-box;
flex: 1 0 0;
min-width: 0;
padding: ${props.gutter ? `0 10px` : '0'};
/* styles here if `size` is a string */
width: 10%;
/* styles here if `size` is an object */
@media screen and (min-width: 500px) {
width: 20%;
}
@media screen and (min-width: 800px) {
width: 30%;
}
@media screen and (min-width: 1100px) {
width: 40%;
}
`
width
值将由道具的键决定,它对应于 breakpoints
对象中的一个值,这部分并不简单,但我不知道如何动态生成css 需要。
我确定我可以添加更多信息,我已经做了一些尝试,但 none 目前正在工作。我的感觉是我应该创建一个无状态功能组件,为每个条件生成 css,然后在最后加入 CSS..
这是一个很好的问题。首先,避免这种模式。
const GridCol = props => styled('div')`
display: block;
box-sizing: border-box;
flex: 1 0 0;
min-width: 0;
padding: ${props.gutter ? `0 10px` : '0'};
`
在这个例子中,每次渲染都会创建一个新样式的组件,这对性能来说很糟糕。
任何表达式或插值都可以是函数。此函数将接收 2 个参数:props
和 context
const GridCol = styled('div')`
display: block;
box-sizing: border-box;
flex: 1 0 0;
min-width: 0;
padding: ${props => props.gutter ? `0 10px` : '0'};
`
至于您示例中的 size
道具,我将使用以下模式。
import { css } from 'emotion'
const sizePartial = (props) => typeof props.size === 'string' ?
css`width: 10%;` :
css`
@media screen and (min-width: 500px) {
width: 20%;
}
@media screen and (min-width: 800px) {
width: 30%;
}
@media screen and (min-width: 1100px) {
width: 40%;
}
`
然后您可以像在表达式中出现的任何其他函数一样使用部分函数。
const GridCol = styled('div')`
display: block;
box-sizing: border-box;
flex: 1 0 0;
min-width: 0;
padding: ${props => props.gutter ? `0 10px` : '0'};
${sizePartial};
`
这是一个非常强大的模式,可用于在您的项目中编写可重用的动态样式。
如果您对利用此模式的其他库感兴趣,请查看 https://github.com/emotion-js/facepaint and https://github.com/jxnblk/styled-system
如果您正在寻找一种使用 Emotion 的 css
道具实现条件样式的方法,您可以这样做:
import { css } from '@emotion/core';
const styles = ({ isSelected }) => css`
border: solid 1px black;
border-radius: 10px;
padding: 16px;
cursor: pointer;
${isSelected === true &&
`
background-color: #413F42;
color: white;
`}
`;
const ConditionalComponent = () => {
const [isSelected, setIsSelected] = useState(false);
return (
<div css={styles({ isSelected })} onClick={() => setIsSelected(!isSelected)}>
Click here to change styles.
</div>
);
};
Emotion 有个帮手叫cx that provides functionality similar to the popular classnames库。您可以使用它更轻松地编写条件语句:
import { cx, css } from '@emotion/css'
const cls1 = css`
font-size: 20px;
background: green;
`
const foo = true
const bar = false
const SomeComponentWithProp = ({ foo }) => (
<div
className={cx(
{ [cls1]: foo === 'bar' },
)}
/>
);
(改编自链接文档)