Styled Components 官方文件

前言

整理 styled-components 的一些使用方法。根據 styled components官方文件進行紀錄。

Getting Start

可以根據styled後方的標籤,可以使用不同的 html tag。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;

const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;


render(
<Wrapper>
<Title>
{/*直接在h1段落帶入文字*/}
Hello World!
</Title>
</Wrapper>
);

Adapting based on props

使用三元運算子進行條件判斷顏色,如果有傳入 primary 就更改顏色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const Button = styled.button`
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};

font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;

render(
<div>
<Button>Normal</Button>
{/* 傳入primary */}
<Button primary>Primary</Button>
</div>
);

Extending Styles

類似 sass 的 mixin 用法。

建立好基本的元件後,再以這個元件為基礎,再使用styled()進行覆寫。最後直接使用該 component

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;

// A new component based on Button, but with some override styles
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;

render(
<div>
<Button>Normal Button</Button>
<TomatoButton>Tomato Button</TomatoButton>
</div>
);

進階用法

使用 as 方法,可以自定義元件選染的狀態。

像是以下,希望它變成超連結的 tag,然後跳轉到#頁面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const Button = styled.button`
display: inline-block;
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
display: block;
`;

const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;

render(
<div>
<Button>Normal Button</Button>
{/* 跳轉到 # 頁面 */}
<Button as="a" href="#">Link with Button styles</Button>
<TomatoButton as="a" href="#">Link with Tomato Button styles</TomatoButton>
</div>
);

也可以使用帶入函式的方式,在渲染畫面前就會呈現文字 Reverse 的樣子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const Button = styled.button`
display: inline-block;
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
display: block;
`;

const ReversedButton = props => <Button {...props} children={props.children.split('').reverse()} />

render(
<div>
<Button>Normal Button</Button>
{/* 使用as方法,調用函式 */}
<Button as={ReversedButton}>Custom Button with Normal Button styles</Button>
</div>
);

Styling any component

建立 Link 的一個 tag,再根據不同的使用情況,調整樣式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 建立Link 的 tagged template
const Link = ({ className, children }) => (
<a className={className}>
{children}
</a>
);

// 調整樣式
const StyledLink = styled(Link)`
color: palevioletred;
font-weight: bold;
`;

render(
<div>
<Link>Unstyled, boring Link</Link>
<br />
<StyledLink>Styled, exciting Link</StyledLink>
</div>
);

Passed prop

如果 props 有帶入顏色,就使用帶入的顏色。沒有的話,就預設為palevioletred

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Input = styled.input`
padding: 0.5em;
margin: 0.5em;
color: ${props => props.inputColor || "palevioletred"};
background: papayawhip;
border: none;
border-radius: 3px;
`;

render(
<div>
{/* Input可以帶入預設值 */}
<Input defaultValue="@probablyup" type="text" />
<Input defaultValue="@brown" type="text" inputColor="brown" />
</div>
);

Pseudoelements, pseudoselectors, and nesting

& + && ~ &差異在於使用+的話,為下一個(next)元素的意思,第一個元素不會有,需要兩個才會有作用。

使用~的話,所有同層的元素都會有,第一個元素不會有。

可以使用&新增 class,以下兩種寫法:

  1. &.something,寫在 Thing 裡面。
  2. .something-else &,寫在 Thing 外面。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const Thing = styled.div.attrs((/* props */) => ({ tabIndex: 0 }))`
color: blue;

&:hover {
// <Thing> when hovered
color: red;
}

& ~ & {
// <Thing> as a sibling of <Thing>, but maybe not directly next to it
background: tomato;
}

& + & {
// <Thing> next to <Thing>
background: lime;
}

&.something {
// <Thing> tagged with an additional CSS class ".something"
background: orange;
}

.something-else & {
// <Thing> inside another element labeled ".something-else"
border: 1px solid;
}
`

render(
<React.Fragment>
<Thing>Hello world!</Thing>
<Thing>How ya doing?</Thing>
<Thing className="something">The sun is shining...</Thing>
<div>Pretty nice day today.</div>
<Thing>Don't you think?</Thing>
<div className="something-else">
<Thing>Splendid.</Thing>
</div>
</React.Fragment>
)

Attaching additional props

使用attrs可以為 components 加上預設值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const Input = styled.input.attrs(props => ({
/* 預設的值 */
type: "text",
/* 預設為1em */
size: props.size || "1em",
}))`
color: palevioletred;
font-size: 1em;
border: 2px solid palevioletred;
border-radius: 3px;

/* 使用props傳入的值 */
margin: ${props => props.size};
padding: ${props => props.size};
`;

render(
<div>
<Input placeholder="A small text input" />
<br />
<Input placeholder="A bigger text input" size="4em" />
</div>
);

Overriding .attrs

Password 的地方,藉由type:"password",覆蓋前面設定的type:"text"。一樣使用到 attrs。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const Input = styled.input.attrs(props => ({
type: "text",
size: props.size || "1em",
}))`
border: 2px solid palevioletred;
margin: ${props => props.size};
padding: ${props => props.size};
`;

const PasswordInput = styled(Input).attrs({
type: "password",
})`
border: 2px solid blue;
`;

render(
<div>
<Input placeholder="A bigger text input" size="2em" />
<br />
<PasswordInput placeholder="A bigger password input" size="2em" />
</div>
);

Animation

動畫的部分也可以使用 styled-components。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Create the keyframes
const rotate = keyframes`
from {
transform: rotate(0deg);
}

to {
transform: rotate(360deg);
}
`;

const Rotate = styled.div`
display: inline-block;
animation: ${rotate} 2s linear infinite;
padding: 2rem 1rem;
font-size: 1.2rem;
`;

render(
<Rotate>&lt; 💅🏾 &gt;</Rotate>
);

Styled Components 官方文件
https://phoebeho.com/React/20210906/2538295329/
作者
Phoebe
發布於
2021年9月6日
許可協議