리액트 스타일컴포넌트에서 ThemeProvider를 이용한 2가지 미디어 쿼리 적용 방법에는 크게 두가지가 있습니다.
첫 번째 방법은 미디어 쿼리 문법 자체를 모듈화 했기 때문에 @media만 없다 뿐이지 사용법 자체는 미디어 쿼리와 동일합니다.
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;
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};
}
....
`;
이 방법의 경우 1번 방법이 조금 발전한 방법으로, MediaQuery 문맥 자체를 직접 만들어 사용하는 방법입니다. 또한 두 번째 방법은 문맥의 시작이 @media로 시작하므로 미디어 쿼리가 시작된다고 누가 보더라도 알 수 있고 직관적입니다.
media.js
와 theme.js
파일을 생성먼저, media.js
와 theme.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;
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 파일에서 미디어 속성을 따로 관리하기 때문에 코드의 분리가 가능합니다.