ReactJs - Styled Components

컴업·2022년 12월 22일
0
post-custom-banner

CSS를 따로 두고 class 혹은 id를 사용해 style을 적용시켰다면, styled components를 사용해 Components(ex <Box />)자체에 스타일을 지정하는 라이브러리.

설치

npm i styled-components

기본

  • styled Component 생성
    const Box = styled.[html tag]`css`;
import styled from "styled-components";

const Box = styled.div`
  background-color: ${(props) => props.bgColor};
  width: 100px;
  height: 100px;
`;

function App() {
  return (
    <div>
      <Box></Box>
    </div>
  );
}

export default App;

확장

1) Adapting and Extending

  • Component에서 넘겨준 파라미터를 Css에서 사용할 수 있다.
    - <Box bgColor="teal"></Box> (bgColor 라는 파라미터를 넘김.)
  • styled(Component-name) 으로 이미 존재하는 Componenet의 값을 재사용 할 수 잇다.
    - styled(Box)
import styled from "styled-components";

const Father = styled.div`
  display: flex;
`;

const Box = styled.div`
  background-color: ${(props) => props.bgColor};
  width: 100px;
  height: 100px;
`;

const Circle = styled(Box)`
  border-radius: 50%;
`;

function App() {
  return (
    <Father>
      <Box bgColor="teal"></Box>
      <Circle bgColor="tomato"></Circle>
    </Father>
  );
}

export default App;

Box Component에서 bgColor 파라미터를 넘기고 styled.div에서 해당 값을 받아 background color를 설정하였다.

Circle에 대한 css는 새로 생성하지 않고 Box에서 사용했던 styled-component를 그대로 사용했다.

2) 'As'

  • as 속성을 사용하여 Component의 태그 종류를 변경할 수 있다.
    - <Box as="href">Log in</Btn>
    -> button 태그인 Btn을 a 태그로 변경
const Btn = styled.button`
  color: white;
  background-color: tomato;
  border: 0;
  border-radius: 15px;
`;

function App() {
  return (
    <Father>
      <Btn>Log in</Btn>
      <Btn as="a" href="https://www.naver.com">Log in</Btn>
    </Father>
  );
}

3) Attrs

  • html 속성을 styled-component로 지정할 수 있다.
const Input = styled.input.attrs({ required: true, minLength:10 })`
  background-color: tomato;
`;

4) Animation

  • keyframes를 사용해 animation을 생성하고 적용한다.
import styled, { keyframes } from "styled-components";

const Wrapper = styled.div`
  display: flex;
`;

const rotation = keyframes`
  0% {
    transform: rotate(0deg);
    border-radius: 0px;
  } 
  50% {
    transform: rotate(360deg);
    border-radius: 100px;
  }
  100% {
    transform: rotate(0deg);
    border-radius: 0px;
  }
`;

const Box = styled.div`
  height: 200px;
  width: 200px;
  background-color: tomato;
  animation: ${rotation} 2s linear infinite;
`;

function App() {
  return (
    <Wrapper>
      <Box />
    </Wrapper>
  );
}

export default App;

5) pesudo selectors

  • 특정 Component의 자식 태그를 선택할 수 있다.
const Box = styled.div`
  span {
    font-size: 36px;
  };
  span:hover {
    font-size: 50px;
  };
`;

Box Component의 span 자식태그를 선택

OR

const Box = styled.div`
  span {
    font-size: 36px;
    &:hover{
      font-size: 50px;
    }
  }
`;
  • 특정 Component의 자식 Component를 선택할 수 도 있다.
const Box = styled.div`
  ${Emoji} {
    font-size: 36px;
    &:hover{
      font-size: 50px;
    }
  }
`;

Box Component아래 속해있는 Emoji 태그를 선택

Theme

모든 색상을 가지고있는 객체. Dark Mode 등을 만들때 사용한다.

index.js 파일에 ThemeProvider를 import하고, App Component를ThemeProvider로 감싸준다.

이 ThemeProvider에 theme 파라미터를 넣는다.

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

import { ThemeProvider } from "styled-components";

const dartTheme = {
  textColor: "whitesmoke",
  backgroundColor: "#111",
};

const lightTheme = {
  textColor: "#111",
  backgroundColor: "whitesmoke",
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <ThemeProvider theme={dartTheme}>
      <App />
    </ThemeProvider>
  </React.StrictMode>
);
  • ThemProvider에 둘러쌓인 모든 Component에서 아래 코드와 같이 받아서 사용할 수 있다.
const Title = styled.h1`
  color: ${(props) => props.theme.textColor};
`;

const Wrapper = styled.div`
  display: flex;
  background-color: ${(props) => props.theme.backgroundColor};
`;

GlobalStyle

HTML 에서 기본으로 제공하는 CSS(예를 들면 링크에 밑줄이 생기는 것)를 제거하기위해 reset.css를 사용한다.

이처럼 모든 Document에 하나의 style을 적용해야 하는 경우 사용하는 메서드.

import { createGlobalStyle } from "styled-components";
import Router from "./router";

const GlobalStyle = createGlobalStyle`

  //reset css
  /*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */
  blockquote, body, dd, dl, dt, fieldset, figure, h1, h2, h3, h4, h5, h6, hr, html, iframe, legend, li, ol, p, pre, textarea, ul {margin:0;padding:0}
  h1, h2, h3, h4, h5, h6 {font-size:100%;font-weight:400}
  ul {list-style:none}
  button, input, select {margin:0}
  html {box-sizing:border-box}
  *, :after, :before {box-sizing:inherit}
  img, video {height:auto;max-width:100%}
  iframe {border:0}
  table {border-collapse:collapse;border-spacing:0}
  td, th {padding:0}

  // fonts.google.com
  @import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@300;400&display=swap');
  body {
    font-family: 'Source Sans Pro', sans-serif;
  }
`;

function App() {
  return (
    <>
      <Router />;
      <GlobalStyle />
    </>
  );
}

export default App;
profile
좋은 사람, 좋은 개발자 (되는중.. :D)
post-custom-banner

0개의 댓글