# 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

# 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

# export dafault vs named export

  1. Both can export variable, function and class.
  2. Only one default export per file, but there can be multiple exports.
  3. When importing default exported objects, we can rename it.
  4. 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

# 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

# Passing props in Styled Components

// Adds disabled attribute to the html tag. 
<Button secondary>Disabled</Button>
1
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

# 상속

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
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

# 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

# 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
//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

# 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

# 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
Last Updated: 3/1/2021, 9:19:08 PM