[英]React Styled component: how to add css styles based on props?
I've been trying to find the solution to my problem. 我一直在寻找解决我问题的方法。 I have several Heading Tags (H1, H2 etc) each in their own file. 我在自己的文件中有几个标题标签(H1,H2等)。 I would like to add some css when calling them based on a prop. 我想在基于prop调用它们时添加一些CSS。 Some headings have a small border-bottom and some don't. 有些标题底端有一个小边框,有些则没有。 So, in order to refractor my code, I want to add some css based on a prop. 因此,为了修改我的代码,我想添加一个基于prop的CSS。 I can't seem to find a way. 我似乎找不到办法。
Here's an example of Heading H2: 这是标题H2的示例:
import styled from 'styled-components';
import colors from '../../../../colors';
import fonts from '../../../../fonts';
import fontWeights from '../../../../fontWeights';
const HeadingH2 = styled.h2`
color: ${colors.text};
font-family: ${fonts.montSerrat};
font-size: 1.6em;
font-weight: ${fontWeights.light};
letter-spacing: 0.2em;
padding-bottom: 0.7em;
position: relative;
text-transform: uppercase;
text-align: center;
&:after{
content: "";
display: block;
height: 3px;
width: 45px;
background-color: currentColor;
/* position */
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
`;
export default HeadingH2
Example of calling Heading H2: 调用标题H2的示例:
import React from 'react';
import HeadingH2 from '../../common/headings/heading_h2';
import HeadingBaseline from '../../common/headings_baseline';
// Features
import {SectionContainer, FeaturesContainer} from './features.style';
import Feature from './feature';
import feature1 from '../../../img/features/feature1.png';
import feature2 from '../../../img/features/feature2.png';
import feature3 from '../../../img/features/feature3.png';
// Text
import Text from '../../../content';
const Features = () => {
return(
<SectionContainer id={"what"}>
<HeadingH2>
What We Do
</HeadingH2>
<HeadingBaseline>
{Text.headingBaseline}
</HeadingBaseline>
<FeaturesContainer>
<Feature
src={feature1}
headingText={Text.feature1.heading}
paragraph={Text.feature1.paragraph}
/>
<Feature
src={feature2}
headingText={Text.feature2.heading}
paragraph={Text.feature2.paragraph}
/>
<Feature
src={feature3}
headingText={Text.feature3.heading}
paragraph={Text.feature3.paragraph}
/>
</FeaturesContainer>
</SectionContainer>
)
};
export default Features;
I want to extract the following CSS properties 我想提取以下CSS属性
position: relative;
text-transform: uppercase;
text-align: center;
&:after{
content: "";
display: block;
height: 3px;
width: 45px;
background-color: currentColor;
/* position */
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
So, assuming I have the above CSS rule in a separate file, how do I add/import them using props on my styled component HeadingH2. 因此,假设我在单独的文件中具有上述CSS规则,如何在样式化的组件HeadingH2上使用道具添加/导入它们。
Thanks for the help :) 谢谢您的帮助 :)
Something like this works: 像这样的作品:
const HeadingH2 = styled.h2`
position: ${props => props.relative && 'relative'};
padding: ${props => props.paddingBottom ? '0 0 20px 0' : '0'};
}
`;
Then use like this: 然后像这样使用:
<HeadingH2 relative paddingBottom />
Possible answer: 可能的答案:
I add the following CSS rules in a separate file like so. 我将以下CSS规则添加到一个单独的文件中,如下所示。 I create a function which returns a string of text. 我创建了一个返回字符串的函数。 I can import this function and add those rules to any component I wish. 我可以导入此函数,并将这些规则添加到我希望的任何组件中。
export const borderBottom = () => {
return `
position: relative;
text-transform: uppercase;
text-align: center;
&:after{
content: "";
display: block;
height: 3px;
width: 45px;
background-color: currentColor;
/* position */
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
`
}
And use it like so on any heading or component that I wish: 并在希望的任何标题或组件上像这样使用它:
import styled from 'styled-components';
import colors from '../../../../colors';
import fonts from '../../../../fonts';
import fontWeights from '../../../../fontWeights';
import {borderBottom} from '../../../../css';
const HeadingH5 = styled.h5`
color: ${colors.black};
font-family: ${fonts.montSerrat};
font-size: 1em;
font-weight: ${fontWeights.light};
letter-spacing: 0.1em;
padding-bottom: 0.45em;
margin-bottom: 25px;
${borderBottom}
`
;
export default HeadingH5;
This works for me. 这对我有用。 Any other suggestions are welcome. 欢迎其他任何建议。
You can also use css
helper from styled-components
to create a SharedStyles.js
file. 您还可以使用styled-components
css
帮助器来创建SharedStyles.js
文件。
In the demo you can see it in action. 在演示中,您可以看到它的运行情况。 Just using it in a style of an inherited component is not working as expected. 仅以继承的组件样式使用它无法正常工作。 If I'm adding it to StyledBase
then the variables are not correctly added afterwards (hover style override stops working). 如果我将其添加到StyledBase
则此后变量未正确添加(悬停样式覆盖会停止工作)。 That's why I copied ${borderBottom}
to each styled component Heading1
/ Heading2
instead of adding it to StyledBase
. 这就是为什么我将${borderBottom}
复制到每个样式化的组件Heading1
/ Heading2
而不是将其添加到StyledBase
。
I think having a level prop for the heading is a good idea but I would handle it differently by creating a HeadingBase
component and add your styles to a StyledBase
component (also see code in the demo). 我认为为标题准备一个水平道具是个好主意,但我会通过创建HeadingBase
组件并将样式添加到StyledBase
组件中来进行StyledBase
(另请参见演示中的代码)。
The HeadingBase
code looks like this: HeadingBase
代码如下所示:
const HeadingBase = ({ className, children, level = 1 }) =>
React.createElement(`h${level}`, { className }, children);
It's a component that renders h1,h2,... tags based on the prop level
passed (defaults to h1). 它是根据传递的prop level
渲染h1,h2,...标签的组件(默认为h1)。 The h-tag receives className
as props (needed for styled-components) and contains the children passed to the component. h标签将className
作为prop接收(样式化组件需要),并包含传递给该组件的子代。
SharedStyles.js SharedStyles.js
import { css } from "styled-components";
export const borderBottom = css`
&:after{
content: "";
display: block;
height: 3px;
width: 200px;
background-color: ${props => props.color || "black"};
/* position */
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
`;
Then you can import it with import { borderBottom } from "./SharedStyles";
然后,您可以使用import { borderBottom } from "./SharedStyles";
导入它import { borderBottom } from "./SharedStyles";
and add it to your styled-component like following: 并将其添加到样式化组件中,如下所示:
const Heading1= styled.h1`
${borderBottom}
`;
Why not just have a headingLevel
prop? 为什么不只拥有headingLevel
道具? and then pass it into the styled component? 然后将其传递给样式化组件? And just have one StyledHeader
styled component as I'm guessing the code is the mostly the same in all the heading styles files? 而且只有一个StyledHeader
样式的组件,因为我猜代码在所有标题样式文件中都基本相同? Which is a big no no, you want to always try not to repeat your code. 很大,不,您要始终尝试不重复代码。
const Features = () => {
return(
<SectionContainer id={"what"}>
<StyledHeader
headingLevel={headingLevel}
>
What We Do
</StyledHeader>
<HeadingBaseline>
{Text.headingBaseline}
</HeadingBaseline>
<FeaturesContainer>
<Feature
src={feature1}
headingText={Text.feature1.heading}
paragraph={Text.feature1.paragraph}
/>
<Feature
src={feature2}
headingText={Text.feature2.heading}
paragraph={Text.feature2.paragraph}
/>
<Feature
src={feature3}
headingText={Text.feature3.heading}
paragraph={Text.feature3.paragraph}
/>
</FeaturesContainer>
</SectionContainer>
)
};
export default Features;
And in your StyledHeader
file 并在您的StyledHeader
文件中
The below function will take your passed in heading level of h1
, h2
, h3
and will apply a border, if not the above 3 heading level it will be 0 value. 下面的函数将采用您传入的标题级别h1
, h2
, h3
并应用边框,如果不是上面的3个标题级别,它将为0值。 I'd do some checks to ensure the value is lower case eg toLowerCase() 我会做一些检查以确保该值是小写的,例如toLowerCase()
const getBorder = ({ headingLevel } ) => {
const headingLevelMap = {
h1: 0.7,
h2: 0.6,
h3: 0.6,
};
return headingLevelMap[headingLevel] || 0;
}
const HeadingH2 = styled.headingLevel`
color: ${colors.text};
font-family: ${fonts.montSerrat};
font-size: 1.6em;
font-weight: ${fontWeights.light};
letter-spacing: 0.2em;
padding-bottom: 0.7em;
border-bottom: ${getCorrectBorderBottom}em solid black
position: relative;
text-transform: uppercase;
text-align: center;
&:after{
content: "";
display: block;
height: 3px;
width: 45px;
background-color: currentColor;
/* position */
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
`;
I'd also check that if the value of the passed in headingLevel
is not any of the 6 heading levels it should have a default value of whatever you want. 我还要检查,如果传入的headingLevel
值不是6个标题级别中的任何一个,它的默认值应该是您想要的任何值。
The above was just quick pseudo code, but hopefully get the general idea here? 上面只是快速的伪代码,但希望能在这里得到一般的想法? Let me know it comments if not. 如果没有,请通知我。
I'd also recommend that you split your Title
component out into a separate component. 我还建议您将“ Title
组件拆分为单独的组件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.