[React] styled component를 이용한 반응형구현

youngseo·2022년 8월 26일
0

REACT

목록 보기
49/52
post-thumbnail

반응형 설정

ThemeProvider를 이용한 2가지 미디어 쿼리 적용

리액트 스타일컴포넌트에서 ThemeProvider를 이용한 2가지 미디어 쿼리 적용 방법에는 크게 두가지가 있습니다.

  • MediaQuery 속성을 모듈화 하기.
  • MediaQuery 자체를 모듈화 하기.

1. MediaQuery 속성을 모듈화 하기.

첫 번째 방법은 미디어 쿼리 문법 자체를 모듈화 했기 때문에 @media만 없다 뿐이지 사용법 자체는 미디어 쿼리와 동일합니다.

1-1. theme 스타일 작성

styles> theme.js

const deviceSizes = {
  mobile: "375px",
  tablet: "768px",
  laptop: "1024px",
};

const device = {
  mobile: `screen and (max-width: ${deviceSizes.mobile})`,
  tablet: `screen and (max-width: ${deviceSizes.tablet})`,
  laptop: `screen and (max-width: ${deviceSizes.laptop})`,
};

const theme = {
  device,
};

export default theme;

1-2 사용 예시

compoents > 사용할컴포넌트폴더 > style.js

import styled, { ThemeProvider } from "styled-components";
import theme from "./theme";

export const Div = styled.div`
  @media ${({ theme }) => theme.device.tablet} {
    flex-direction: column;
    font-size: ${({ theme }) => theme.fontSizes.paragraph};
  }
  ....
`;

2. MediaQuery 자체를 모듈화 하기.

이 방법의 경우 1번 방법이 조금 발전한 방법으로, MediaQuery 문맥 자체를 직접 만들어 사용하는 방법입니다. 또한 두 번째 방법은 문맥의 시작이 @media로 시작하므로 미디어 쿼리가 시작된다고 누가 보더라도 알 수 있고 직관적입니다.

2-1 media.jstheme.js 파일을 생성

먼저, media.jstheme.js 파일을 생성합니다.

media.js

import { css } from "styled-components";

const sizes = {
  mobile: 320,
  tablet: 768,
  laptop: 1024,
  tesktop: 2560,
};

export default Object.keys(sizes).reduce((acc, label) => {
  acc[label] = (...args) => css`
    @media screen and (max-width: ${sizes[label]}px) {
      ${css(...args)};
    }
  `;
  return acc;
}, {});

Object.keys() 함수로 매개변수로 넘어간 sizes 객체에 있는 enumerable 속성명을 가지고 reduce()의 리듀서 함수로 size에 정의된 값으로 acc 연산으로 각각의 media query의 속성들을 styled-components의 css 속성을 이용해서 만들어냅니다.

그리고 그 속성 값들을 위에서 정의한 sizes 객체에 있는 값들로 media query의 속성을 만드는데 ...args 문법으로 생성된 모든 args를 media query 내에 적용시켜줍니다.

theme.js

import styled from "styled-components";

const colors = {
  black: "#000000",
  grey: "#999999",
};

...

const theme = {
  fontSizes,
  colors,
  common,
};

export default theme;

2-2 ThemeProvider에 적용

import styled, { ThemeProvider } from "styled-components";
import theme from "./theme";
import media from "./media";

const Div = styled.div`
  font-size: ${({ theme }) => theme.fontSizes.subtitle};

  ${({ theme }) => theme.tablet` // theme props의 media 객체 사용하기
    flex-direction: column;
    font-size: ${({ theme }) =>
      theme.fontSizes.paragraph}; // theme props의 theme.js 객체 사용하기
  `};

  width: 100vw;
  height: 100vh;
  background: wheat;
  display: flex;
  align-items: center;
  justify-content: center;
`;

만약 기존에 정의된 theme이 있다면 다음과 같이 theme={ media}theme={{ ...theme, ...media }}>과 같이 theme과 media를 모두 spread 시켜주면 됩니다.

전개 연산으로 theme의 속성과 media 속성을 spread 시켜주면 정의된 theme 속성을 통일성 있게 사용할 수 있고 media로 정의된 Media Query 속성을 사용할 수 있습니다.

미디어 속성이 많아지는 경우 첫 번째 경우는 한 파일에 많은 속성들이 들어가 있어서 헷갈릴 수 있는 요소들이 많은 반면 두 번째경우는 하나의 media.js 파일에서 미디어 속성을 따로 관리하기 때문에 코드의 분리가 가능합니다.

출처

0개의 댓글