Styled components

Donggu(oo)·2023년 5월 20일
0

Styled components

목록 보기
1/2
post-thumbnail

1. 사용 환경 세팅


1) Styled Component 라이브러리 설치

  • npm install styled-components 명령어를 이용해 Styled Component 라이브러리를 설치한다.

명령어

npm install styled-components@latest

타입스크립트 사용 시 추가 install

npm i -D @types/styled-components

  • 라이브러리가 잘 설치되었다면, package.json 파일의 dependencies 항목에 styled-components라는 라이브러리가 등록된 것을 확인할 수 있다.

  • Styled Components는 package.json에 다음 코드를 추가하도록 권장하고 있다. 아래의 코드를 추가하면 여러 버전의 Styled Components가 설치되어 발생하는 문제를 줄여준다.
  "resolutions": {
    "styled-components": "^5"
  },

2) import

  • Styled Components를 사용할 파일로 불러와준다.
import styled from 'styled-components'

2. Styled Components 문법


1) 컴포넌트 만들기(HTML 엘리먼트 스타일링)

  • 컴포넌트를 선언한 후 styled.태그 종류를 할당하고, 백틱(``) 안에 기존에 CSS를 작성하던 문법과 똑같이 스타일 속성을 작성해준다.

  • 위와 같이 만든 컴포넌트를 React 컴포넌트를 사용하듯 리턴문 안에 작성해주면 스타일이 적용된 컴포넌트가 렌더링된다.

기본 문법

const 컴포넌트 이름 = styled.태그 종류`
    CSS 속성1: 속성값;
    CSS 속성2: 속성값;
`;
import styled from "styled-components";

//Styled Components로 컴포넌트를 만들고
const BlueButton = styled.button`
  background-color: blue;
  color: white;
`;

export default function App() {
  // React 컴포넌트를 사용하듯이 사용한다.
  return <BlueButton>Blue Button</BlueButton>;
}

2) 컴포넌트 재활용(React 컴포넌트 스타일링)

  • 이미 만들어진 컴포넌트를 재활용해서 새로운 컴포넌트를 만들려면, 컴포넌트를 선언하고 styled()에 재활용할 컴포넌트를 전달해준 다음, 추가하고 싶은 스타일 속성을 작성해준다.

  • 기존에 만들어둔 컴포넌트의 CSS 속성을 그대로 사용하면서 추가하고 싶은 CSS 속성이 있을 경우 재활용하여 사용한다.

기본 문법

const 컴포넌트 이름 = styled(재활용할 컴포넌트)`
    추가할 CSS 속성1: 속성값;
    추가할 CSS 속성2: 속성값;
`;
import styled from "styled-components";

const BlueButton = styled.button`
  background-color: blue;
  color: white;
`;

//만들어진 컴포넌트를 재활용해 컴포넌트를 만들 수 있습니다.
const BigBlueButton = styled(BlueButton)`
  padding: 10px;
  margin-top: 10px;
`;

//재활용한 컴포넌트를 재활용할 수도 있습니다.
const BigRedButton = styled(BigBlueButton)`
  background-color: red;
`;

export default function App() {
  return (
    <>
      <BlueButton>Blue Button</BlueButton>
      <br />
      <BigBlueButton>Big Blue Button</BigBlueButton>
      <br />
      <BigRedButton>Big Red Button</BigRedButton>
    </>
  );
}

3) Styled Component에 이벤트 적용

  • 기본 스타일을 작성하고 이어서 &:로 연결해준다.
import styled from 'styled-components';

const Practice = styled.button`
  padding: 1rem;
  font-size: 2rem;
  background: powderblue;
  border-radius: 1rem;
  transition: 0.5s;
  // 위에 기본 스타일 작성 후 hover 상태에서의 스타일 작성
    &:hover {
    background: cornflowerblue;
    color: white;
    transition: 0.5s;
  }
`;

export default function App() {
  return <Practice>Practice!</Practice>;
}

3. Props 활용


1) Props로 조건부 렌더링

  • Styled Component로 만든 컴포넌트도 React 컴포넌트처럼 props를 내려줄 수 있으며, 내려준 props 값에 따라서 컴포넌트를 렌더링하는 것도 가능허다.

  • Styled Components는 탬플릿 리터럴 문법(${ })을 사용하여 JavaScript 코드를 사용할 수 있다. props를 받아오려면 props를 인자로 받는 함수를 만들어 사용한다.

기본 문법

const 컴포넌트 이름 = styled.태그 종류`
    CSS 속성: ${(props) => 함수 코드}
`;
  • 아래 예제는 삼항연산자를 활용해 <BlueButton> 컴포넌트에 skyblue라는 props가 있는지 확인하고, 있으면 배경색을 skyblue로 지정하고, 없을 경우 white로 지정해준다.

  • Button1의 경우 skyblue라는 props가 있어 배경색이 skyblue로 지정됐고, Button2의 경우는 props가 없어서 배경색이 white로 지정됐다.

import styled from "styled-components";
import GlobalStyle from "./GlobalStyle";
//받아온 prop에 따라 조건부 렌더링이 가능하다.
const BlueButton = styled.button`
  background: ${(props) => (props.skyblue ? "skyblue" : "white")};
`;

export default function App() {
  return (
    <>
      <GlobalStyle />
      <BlueButton skyblue>Button1</BlueButton>
      <BlueButton>Button2</BlueButton>
    </>
  );
}

const MarkerFilteringBtn = styled.button<{ active: boolean }>`
  color: ${({ active }) => (active ? color.white : color.gray[9])};
  border: 1px solid ${({ active }) => (active ? color.main[5] : color.gray[3])};
  background-color: ${({ active }) => (active ? color.main[1] : color.white)};
`;

2) Props 값으로 렌더링

  • 조건부 렌더링과 비슷하게 props 값을 통째로 활용해서 컴포넌트 렌더링에 활용할 수도 있다.

기본 문법

const 컴포넌트 이름 = styled.태그 종류`
    CSS 속성: ${(props) => 함수 코드}
`;
  • 아래 예제는 위의 예제와 똑같이 삼항 연산자를 사용하고 있지만, 이번에는 props.color가 없다면 white를, props.color가 있다면 props.color의 값을 그대로 가져와서 스타일 속성 값으로 리턴해주고 있다. 그 결과 color라는 이름으로 받은 props의 값으로 배경색이 지정된 것을 확인할 수 있다.
import styled from "styled-components";
import GlobalStyle from "./GlobalStyle";

//받아온 prop 값을 그대로 이용해 렌더링할 수도 있다.
const Button1 = styled.button`
  background: ${(props) => (props.color ? props.color : "white")};
`;

export default function App() {
  return (
    <>
      <GlobalStyle />
      <Button1>Button1</Button1>
      <Button1 color="orange">Button1</Button1>
      <Button1 color="tomato">Button1</Button1>
    </>
  );
}

  • 그리고 꼭 삼항연산자만 사용해야 하는 것은 아니며, JavaScript 코드라면 다 사용가능 하다. 아래는 || 연산자를 사용한 예제이다.
import styled from "styled-components";
import GlobalStyle from "./GlobalStyle";

//다음과 같은 형식으로도 활용할 수 있다.
const Button2 = styled.button`
  background: ${(props) => props.color || "white"};
`;

export default function App() {
  return (
    <>
      <GlobalStyle />
      <Button2>Button2</Button2>
      <Button2 color="pink">Button2</Button2>
      <Button2 color="turquoise">Button2</Button2>
    </>
  );
}

4. 전역 스타일 설정


1) GlobalStyle

1-1. import

  • 최상위 컴포넌트에 createGlobalStyle을 불러온다.
// App.js
import { createGlobalStyle } from "styled-components";

1-2. 전역 스타일 설정

  • createGlobalStyle을 사용해 CSS 파일에서 작성하듯 스타일을 작성한다.
// GlobalStyle.js
import { createGlobalStyle } from "styled-components";

const GlobalStyle = createGlobalStyle`
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    display: flex;
    justify-content: center;
    height: 100vh;
    background-color: ${(props) => props.theme.backgroundColor};;
}
`;

export default GlobalStyle;

1-3. 적용

  • 만든 <GlobalStyle> 컴포넌트로 최상위 컴포넌트를 감싸주면 전역에 <GlobalStyle> 컴포넌트의 스타일이 적용된다.
// App.js
import styled from "styled-components";
import GlobalStyle from "./GlobalStyle";

function App() {

  return (
        <div className="App">
          <GlobalStyle />  // GlobalStyle 적용
          <Routes>
            <Route path='/' element={<AllTodoList />} />
          </Routes>
        </div>
  );
}

export default App;

2) ThemeProvider

  • ThemeProvider는 Context Api 를 사용해서 모든 리액트 컴포넌트에 theme 스타일 속성을 전달하는 역할을 수행한다.

2-1. import

  • 최상위 컴포넌트에 ThemeProvider를 불러온다.
// App.js
import { ThemeProvider } from 'styled-components';

2-2. 전역 스타일 설정

  • 자식 컴포넌트들에게 props로 넘겨줄 스타일을 작성한다.
// theme.js
export const lightTheme = {
    backgroundColor: `white`,
    title: `#46554a`,
    button: `black`,
    text: 'black',
    pagenationFocus: `#e3e5e9`,
    popUpBackgroundColor: `white`,
    sideListHover: `lightgray`,
    modalInputBack: `white`
}

export const darkTheme = {
    backgroundColor: `#171a1b`,
    title: '#e3e5e9',
    button: '#e3e5e9',
    text: '#e3e5e9',
    pagenationFocus: 'black',
    popUpBackgroundColor: '#232527',
    sideListHover: `#393b3d`,
    modalInputBack: `#393b3d`
}

2-3. 적용

  • <ThemeProvider>로 최상위 컴포넌트를 감싸준다. 이때, theme={}으로 값을 지정해준다.
// App.js
import { ThemeProvider } from 'styled-components';

function App() {
  const [isChange, setIsChange] = useState(false);

  const changeMode = () => {
    setIsChange(!isChange);
  }

  return (
    <ThemeProvider theme={isChange ? darkTheme : lightTheme}>
      <div className="App">
        <Routes>
          <Route path='/' element={<AllTodoList />} />
        </Routes>
      </div>
    </ThemeProvider>
  );
}

export default App;
  • 자식 컴포넌트들에는 props로 스타일 값을 전달해준다.
// Header.js
export const HeaderContainer = styled.div`
    display: flex;
    background-color: ${(props) => props.theme.backgroundColor};

    > .title {
        margin-bottom: 20px;
        font-size: 35px;
        color: ${(props) => props.theme.title};
        font-weight: bolder;
        flex: 10;
    }
`;

5. 파일 분리


  • 동일한 스타일을 다른 파일(컴포넌트)에서 사용해야 된다면 styled-component가 있는 파일에서 스타일들을 export 한 뒤 동일한 스타일을 적용할 파일에서 import 해서 사용할 수 있다.
// 다른 파일에서 사용할 스타일 export
export const ListCountDropDown = styled.div`
    text-align: right;

    > .dropDown {
        border: none;
        &:focus {
            outline: none;
        }
    }
`;
  • export한 스타일을 사용할 파일에선 import * as '변경할 이름' from '스타일이 있는 파일 경로' 해당 형식으로 import 해온다.

  • 적용할 때는 변경한 이름.적용할 스타일 컴포넌트 이름 형식으로 적용한다.

// 다른 파일의 스타일을 불러와서 사용할 파일에서는
// import styled from 'styled-components'; 는 import 할 필요 없다.
import * as Main from "./Main";

<Main.AddModalContentArea>
    <input className="addModalContentInput" type='text' placeholder="할 일을 입력해주세요" onChange={handleChangeTodoText} />
</Main.AddModalContentArea>

0개의 댓글