# Styled Components
Utilising tagged template literals (a recent addition to JavaScript) and the power of CSS, styled-components allows you to write actual CSS code to style your components. It also removes the mapping between components and styles – using components as a low-level styling construct could not be easier!
npx create react app .
yarn create react-app my-app
yarn add styled components
# absolute imports
//jsconfig.json
{
"compilerOptions": {
"baseUrl": "src"
},
"include":["src"]
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# Simple Button
import styled from "styled-components";
//Must be captial because all React component starts with a capital letter.
//Backticks are called tagged template literal.
const Button = styled.button`
color: white;
background: #f8049c;
font-weight: bold;
padding: 8px;
border-radius: 4px;
box-shadow: none;
font-size: 1em;
border: none;
width: 100%;
display: block;
white-space: none;
//targeted state
&:disabled {
background: #eee;
color: #666;
}
`;
export { Button };
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
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
# export dafault vs named export
- Both can export variable, function and class.
- Only one default export per file, but there can be multiple exports.
- When importing default exported objects, we can rename it.
- Importing named export, you can rename is using
as
operator.
//Named Export
export {Button}
import {Button} from 'Button'
//Default Export
export default Button
import Button from 'Button'
//Combined
import defaultExport, { namedExport1, namedExport3, etc... } from 'module'
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# Global Style
Make GlobalStyle const at App.js and render it at the top.
//App.js
const GlobalStyle = createGlobalStyle`
body{
background:white;
min-height:100vh;
margin:0;
color:black;
font-family:"Kaushan Script"
}
`;
function App() {
return (
<>
<GlobalStyle />
<h1>App</h1>;<Button>Test</Button>
</>
);
}
export default App;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Passing props in Styled Components
// Adds disabled attribute to the html tag.
<Button secondary>Disabled</Button>
1
2
2
background: ${(props) => (props.secondary ? "black" : "#f8049")};
1
# Bulk styling
import styled, { css } from "styled-components";
const Button = styled.button`
color: white;
background: #f8049c;
font-weight: bold;
${(p) =>
p.large
? css`
padding: 10px;
border-radius: 5px;
font-size: 3em;
`
: css`
padding: 8px;
border-radius: 4px;
font-size: 1em;
`}
box-shadow: none;
}
`;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 상속
const Menu = styled.nav`
display: flex;
position: relative;
width: initial;
border-bottom: none;
margin: auto 0 auto auto;
font-family: "Open Sans";
background: none;
left: initial;
top: initial;
`;
const MenuAlt = styled(Menu)`
border-top: 5px solid black;
`;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# isActive Link
import { Link as ReactRouterDomLink } from "react-router-dom";
const Link = ({ isActive, children, ...props }) => {
return <ReactRouterDomLink {...props}>{children}</ReactRouterDomLink>;
};
const StyledLink = styled(Link)`
padding: 4px 8px;
display: block;
text-align: center;
box-sizing: border-box;
margin: auto 0;
font-weight: ${(p) => (p.isActive ? "bold" : "normal")};
`;
export function Header() {
return (
<HeaderWrapper>
<Menu>
<StyledLink to="/">Home</StyledLink>
<StyledLink to="login" isActive>
Login
</StyledLink>
</Menu>
</HeaderWrapper>
);
}
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
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
# Media queries
const Menu = styled.nav`
display: none;
position: relative;
width: initial;
border-bottom: none;
margin: auto 0 auto auto;
font-family: "Open Sans";
background: none;
left: initial;
top: initial;
@media (min-width: 768px) {
display: flex;
}
`;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Login Form
import React, { useState } from "react";
import { PageLayout, Input } from "components/common";
import styled from "styled-components";
const Form = styled.form`
width: 100%;
max-width: 400px;
background: white;
border: 1px solie #eee;
padding: 16px;
box-sizing: border-box;
color: black;
border-radius: 4px;
`;
export default function Login() {
const [formFields, setFormFields] = useState({ username: "", password: "" });
function handleInputChange(e) {
e.persist();
setFormFields((s) => ({
...s,
[e.target.name]: e.target.value,
}));
}
return (
<PageLayout>
<h1>Login</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Officiis
corporis consequatur illo illum esse rem, doloribus quidem perspiciatis
maxime iure voluptatibus fuga nam voluptatum dolor quas, sed, ab cum
inventore?
</p>
<Form>
<Input
value={formFields.username}
name="username"
placeholder="Username"
type="text"
onChange={handleInputChange}
/>
<Input
value={formFields.password}
name="password"
placeholder="Password"
type="password"
onChange={handleInputChange}
/>
</Form>
</PageLayout>
);
}
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
42
43
44
45
46
47
48
49
50
51
52
53
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
42
43
44
45
46
47
48
49
50
51
52
53
//Input.js
import styled from "styled-components";
const Input = styled.input`
padding: 4px 8px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 1em;
font-family: "Open Sans";
margin-bottom: 8px;
width: 100%;
box-sizing: border-box;
height: 40px;
`;
export { Input };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# attrs
import React, { useState } from "react";
import styled from "styled-components";
import { Input } from "./Input";
const PasswordInputStyled = styled(Input).attrs(() => ({
type: "password",
placeholder: "Password",
}))`
border-top-right-radius: 0;
border-bottom-right-radius: 0;
`;
export function PasswordInput(props) {
const [showPassword, setShowPassword] = useState(false);
return <PasswordInputStyled {...props}></PasswordInputStyled>;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# spinner
import styled, { keyframes } from "styled-components";
const rotation = keyframes`
from{
transform: rotate(0deg);
}
to{
transform: rotate(360deg);
}
`;
const Spinner = styled.div`
height: 30px;
width: 30px;
border: 1px solid #f8049c;
border-radius: 50%;
border-top: none;
border-right: none;
margin: 16px auto;
animation: ${rotation} 1s linear infinite;
`;
export { Spinner };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24