React 에 Styled Component 끼얹기

박정훈·2022년 1월 10일
0

styled-component

목록 보기
1/2

기본 세팅은 역시 공식 홈페이지에 나와 있다.

그래도..! 기록을 남겨 두려고 한다.

Styled-componentes 설치

npm install styled-component

Type definition 설치

npm install @types/styled-components

타입 정의 Styled.d.ts 파일 생성

// styles/styled.d.ts
// theme 의 type을 지정 해 준다.
import "styled-components";
import { Theme } from "./theme";

declare module "styled-components" {
  export interface DefaultTheme extends Theme {
    colors: {
      grey: string;
      lightgrey: string;
      darkGrey: string;
      black: string;
      white: string;
      darkWhite: string;
      indigo: string;
      ...
  }
}

theme 파일 생성

// styles/theme.ts
import media from "./media"; // 뒤에서 추가 해 줄 media

const colors = {
  grey: "#6c757f",
  lightgrey: "#606060",
  darkGrey: "#343638",
  black: "#222222",
  white: "#ffffff",
  darkWhite: "#d5d5d5",
  indigo: "#172d4c",
  ...
};
  
export const myTheme = {
  	colors,
  	media, // media 도 추가
}

export type Theme = typeof myTheme;

global-style 파일 생성

styled-reset 패키지를 설치 하면 global reset 할 수 있다.
npm i styled-reset
물론 선택적인 요소다.

// styles/global-styles.ts
// global style 을 작성 해 주면 된다.
import { createGlobalStyle } from "styled-components";

export const GlobalStyle = createGlobalStyle`
${reset}
* {
    box-sizing: border-box;
    padding: 0;
    margin: 0;
    line-height: 1.5;
}
html {
    font-size: 62.5%;
    color: #222222;
}
ul {
    list-style: none;
    margin: 0;
}
...
`;

// 위 처럼 할 수도 있고 당연하게도 global 에서 theme 에서 뿌린 스타일을 가져다 쓸 수도 있다.
// 물론 global이 themeprovider 안으로 들어와야 한다.
export const GlobalStyle = createGlobalStyle`
    ${reset}
    * {
        box-sizing: border-box;
    }
    html {
        font-size: 62.5%;
    }

    ${({ theme }) => {
      return css`
        body {
          font-family: ${theme.fonts.family};
          font-size: ${theme.fonts.size.small};
          line-height: 1.4;
        }
        h1 {
          font-size: ${theme.fonts.size.large};
          font-weight: ${theme.fonts.weight.bold};
          color: ${theme.colors.black};
          margin: 1.6rem;
        }
	...
	...
      `;
    }}
`;



// index.tsx
// 원하는 최상위 root 에 global style을 얹어준다.
// 또한 위에서 다룬 theme 을 ThemeProvider 를 통해 전역에 뿌린다.
import { GlobalStyle } from "./styles/global-style";

ReactDOM.render(
  <React.StrictMode>
  // theme 아래 넣거나... 위에 넣거나...
    <GlobalStyle />
    <ThemeProvider theme={myTheme}>
      <App />
    </ThemeProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

media query

media query

// styles/media.ts
import { css, CSSProp } from "styled-components";

interface MediaQueryProps {
  tablet: number;
  laptop: number;
  desktop: number;
}

const sizes: MediaQueryProps = {
  tablet: 768,  
  laptop: 992,
  desktop: 2560,
};

type BackQuoteArgs = string[];

const media = {
  tablet: (
    literals: TemplateStringsArray,
    ...args: BackQuoteArgs
  ): CSSProp =>
    css`
      @media only screen and (max-width: ${sizes.tablet_max}px) {
        ${css(literals, ...args)}
      }
    `,
  laptop: (literals: TemplateStringsArray, ...args: BackQuoteArgs): CSSProp =>
    css`
      @media only screen and (max-width: ${sizes.laptop}px) {
        ${css(literals, ...args)}
      }
    `,
  desktop: (literals: TemplateStringsArray, ...args: BackQuoteArgs): CSSProp =>
    css`
      @media only screen and (max-width: ${sizes.desktop}px) {
        ${css(literals, ...args)}
      }
    `,
} as Record<
  keyof typeof sizes,
  (literals: TemplateStringsArray, ...args: BackQuoteArgs) => CSSProp
>;

export default media;

Record는 두개의 generic type 을 받을 수 있다.

type Record<K extends keyof any, T> = {  [P in K]: T; };

프로퍼티 key 값을 K 타입으로, value 를 T 타입으로 만들어 준다.
Record stackoverflow

사용하기

1) 기본

import styled, { css } from "styled-components";

const container = styled.div`
  width: 100%;
  ${({ theme }) => {
    return css`
      color: ${theme.colors.darkGrey};
    `;
  }}
`;

2) 하나의 prop

const ContentTitle = styled.a<{ isUnderLine?: boolean }>`
  &:hover {
    text-decoration: ${(props) => (props.isUnderLine ? "underline" : "none")};
  }
`;

3) media query와 다수의 props

interface NavbarDropDownProps {
  readonly isToggle: boolean;
  readonly isHover: boolean;
}

const NavbarDropDown = styled.div<NavbarDropDownProps>`
  ${({ isToggle, isHover, theme }) => theme.media.laptop`
  height: ${ isToggle ? "100%" : "0%" };
  transition: ${ isHover ? "height 0.35s ease-out" : "none" };
  `}
`;
profile
그냥 개인적으로 공부한 글들에 불과

0개의 댓글