์ด ๊ธ์ Styled-components์ ThemeProvider์ ๋ํ ๊ธฐ๋ณธ์ ์ธ ์ ํ ์ง์์ด ํ์ํฉ๋๋ค.
ํน์ ThemeProvider์ ๋ํ ์ ๋ณด๋ฅผ ํ์ธํด๋ณด๊ณ ์ถ๋ค๋ฉด ThemeProvider๋ก ๊ณตํต ์คํ์ผ ์์ฑ ๊ด๋ฆฌํ๊ธฐ๋ฅผ ๋ฐฉ๋ฌธํด์ ๊ฐ๋ณ๊ฒ ์ฝ๊ณ ์๋ณด์ธ์. ๊ทธ๋ผ ๋ ๋์์ด ๋ ๊ฑฐ์์ :)
์ด๋ค ์ข ๋ฅ์ ์ธ์ด๋ ๋๊ตฌ๊ฐ ๋์๋ ์น ํ๋ก ํธ์ ์คํ์ผ๋ง์ ํ๋ ๊ณผ์ ์๋ ๋ง์ ๋ ธ๋ ฅ๊ณผ ํ์ด ๋ค์ด๊ฐ๋ค.
๊ทธ ์ค์์๋ ๋ชจ๋ฐ์ผ๊ณผ ์น์ ์คํ์ผ์ ๋ฐ๋ก ๋๋๋ ๋ฏธ๋์ด ์ฟผ๋ฆฌ ๋ถ๋ถ์์ ๊ต์ฅํ ๋ฐ๋ณต๋๋ ์์
์ ๋ง์ด ํ๊ฒ ๋๋๋ฐ, ์ด ์์
์ ์ฐ๋ฆฌ๋ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ์๊ณ ์๋ค.
๋ฐ๋ก ThemeProvider.
์ค๋์ ์ด ThemeProvider๋ฅผ ํตํด์ ๋ฏธ๋์ด ์ฟผ๋ฆฌ๋ฅผ ์ข ๋ ์ฝ๊ฒ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณผ ๊ฒ์ด๋ค.
๊ทธ ์ ์ ๋ฏธ๋์ด ์ฟผ๋ฆฌ๋ฅผ ๋จผ์ ์์๋ณด์.
๋ฏธ๋์ด ์ฟผ๋ฆฌ๋ CSS3์์ ๋์จ ๊ธฐ์ ๋ก ํน์ ์กฐ๊ฑด์ด true ์ผ ๋๋ง css ์์ฑ์ ์ ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ ๋ฌธ๋ฒ์ด๋ค.
์ฌ๊ธฐ์ ํน์ ์กฐ๊ฑด์ ๋ณดํต ์ฐ๋ฆฌ๋ ํ๋ฉด์ ๋์ด๋ ๋์ด์ ๊ฐ์ด ๋ธ๋ผ์ฐ์ ๊ฐ ์ด๋ค ๊ธฐ๊ธฐ์์ ์คํ๋๊ณ ์๋์ง๋ฅผ ํ์
ํด์ ๊ธฐ๊ธฐ๋ณ๋ก ์๋ก ๋ค๋ฅธ ์คํ์ผ์ ์ ๊ณตํ๋ ๋ฐฉ๋ฒ์ ์ ํํ๋๋ฐ, ์ด๊ฒ์ ๋ฐ๋ก ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ด๋ผ๊ณ ํ๋ค.
@media screen and (max-width: 768px) {
font-size: 3rem;
font-weight: bold;
}
์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๋ค.
๊ทธ๋ผ screen ์์ญ์์ 768px ์ ๊น์ง์ width์์๋ font-size: 3rem
๊ณผ font-weight: bold
์์ฑ์ ์ ์ฉ๋ฐ์ ์ ์๊ฒ ๋๋ ๊ฒ์ด๋ค.
ThemeProvider๋ฅผ ์ด์ฉํ 2๊ฐ์ง ๋ฏธ๋์ด ์ฟผ๋ฆฌ ์ฌ์ฉ๊ธฐ
ThemeProvider๋ฅผ ์ฌ์ฉํด์ ๋ฏธ๋์ด ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๋ํ์ ์ธ ๋ฐฉ๋ฒ์ 2๊ฐ์ง ์ด๋ค.
- MediaQuery ์์ฑ์ ๋ชจ๋ํ ํ๊ธฐ.
- MediaQuery ์์ฒด๋ฅผ ๋ชจ๋ํ ํ๊ธฐ.
์ด๋ค ๋ฐฉ๋ฒ์ ์ ํํ๋ ๊ฐ๊ฐ์ ์ฅ๋จ์ ์ด ์กด์ฌํ๋ค.
๋ฐฉ๋ฒ์ ๋ฐ๋ผ๊ฐ๋ฉฐ ๋ค์์ ๋ฌด์์ด ๋ณธ์ธ์๊ฒ ๋ ๋ง์์ง ๋น๊ตํด๋ณด์.
MediaQuery ์์ฑ์ ๋ชจ๋ํ ํ๊ธฐ.
MediaQuery ์์ฑ์ ๊ฐ์ฒดํ ํ์ฌ ์ฌ์ฉํ๋ ๊ฒ์ ์ง๋ ์๊ฐ์ ๋ดค๋ ํ๋ก์ ํธ์์ ThemeProvider ์ฌ์ฉํ๊ธฐ์ ๋ฐฉ๋ฒ๊ณผ ์ ํํ ๋์ผํ๋ค.
์ฐ์ theme.js
ํ์ผ์ ์์ฑํ๋ค.
theme.js
๊ทธ๋ฆฌ๊ณ 2๊ฐ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
- size ๊ฐ์ฒด : ๊ธฐ๊ธฐ์ ์ฌ์ด์ฆ์ ๊ฐ์ด ๋ค์ด์๋ ๊ฐ์ฒด
- device ๊ฐ์ฒด : media query์ ์์ฑ๊ฐ์ด ๋ค์ด์๋ ๊ฐ์ฒด
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;
์ค์ ๋ก ์ฌ์ฉํ ๋๋ @media
๋ฅผ ๋จผ์ ์ ์ธํด์ฃผ๊ณ ๋ค์ ์์ฑ์ ์ฌ์ฉํ๋ฉด๋๋ค.
@media ${({ theme }) => theme.device.tablet} {
flex-direction: column;
font-size: ${({ theme }) => theme.fontSizes.paragraph};
}
์ด์ ์ฐ๋ฆฌ ํ๋ก์ ํธ์ ์ ์ฉํด๋ณด์.
ThemeProvider์ theme
props๋ก ์ ๋ฌํด์ค๋ค.
import React from "react";
import styled, { ThemeProvider } from "styled-components";
import theme from "./theme";
const Div = styled.div`
@media ${({ theme }) => theme.device.tablet} {
flex-direction: column;
}
width: 100vw;
height: 100vh;
background: wheat;
display: flex;
align-items: center;
justify-content: center;
`;
const Div2 = styled.div`
width: 100px;
height: 100px;
background: white;
margin: 5px;
`;
const App = () => {
return (
<ThemeProvider theme={theme}>
<Div>
<Div2>์ ๋ง๋ก</Div2>
<Div2>๋ฆฌ์กํธ</Div2>
<Div2>์ฌ๋ฐ์ด์</Div2>
<Div2>์ง์ง๋ก</Div2>
</Div>
</ThemeProvider>
);
};
export default App;
MediaQuery ์์ฒด๋ฅผ ๋ชจ๋ํ ํ๊ธฐ.
์ด ๋ฐฉ๋ฒ์ ์์ ๋ฐฉ๋ฒ์์ ์กฐ๊ธ ๋ฐ์ ํ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ํ ์ ์๋ค.
์์์๋ screen and (max-width: ${deviceSizes.mobile})
์ ์์ํ ์์ผ exportํ ๊ฒ์ ์ฌ์ฉํ๋ค.
๊ทธ๋ผ ์ฐ๋ฆฌ๋
@media {}
๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉํ์ง๋ง ์ด๋ฒ์๋ MediaQuery ๋ฌธ๋งฅ ์์ฒด๋ฅผ ์ง์ ๋ง๋ ๋ค.
2๊ฐ์ js ํ์ผ์ ์์ฑํ๋ค.
media.js
: media ์ฟผ๋ฆฌ ์์ฒด๋ฅผ exportํ ํ์ผtheme.js
: ํต์ผํ๋ฅผ ์ํด ์ ์๋ ๋ค๋ฅธ theme ์์ฑ (์ผ๋ฐ์ ์ธ ThemeProvider์ theme props ๊ฐ)
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;
ThemeProvider์ ์ ์ฉํ๊ธฐ
์ด ๋ฐฉ๋ฒ์ Theme ์์ฑ์ ๋ค์ด๊ฐ ํ์ผ์ด 2๊ฐ๊ฐ ๋๋ฏ๋ก 2๊ฐ์ญ ์์ฑ์ ThemeProvider์ props๋ก ๋ฃ์ด์ค์ผํ๋ค.
import React from "react";
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;
`;
const Div2 = styled.div`
width: 100px;
height: 100px;
background: white;
margin: 5px;
`;
const ThemeProviderPrac = () => {
return (
<ThemeProvider theme={{ ...theme, ...media }}>
<Div>
<Div2>์ ๋ง๋ก</Div2>
<Div2>๋ฆฌ์กํธ</Div2>
<Div2>์ฌ๋ฐ์ด์</Div2>
<Div2>์ง์ง๋ก</Div2>
</Div>
</ThemeProvider>
);
};
export default ThemeProviderPrac;
๋ง์ฝ ๊ธฐ์กด์ ์ ์๋ theme์ด ์๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด theme={ media}
์ theme={{ ...theme, ...media }}>
๊ณผ ๊ฐ์ด theme๊ณผ media๋ฅผ ๋ชจ๋ spread ์์ผ์ฃผ๋ฉด ๋๋ค.
์ ๊ฐ ์ฐ์ฐ์ผ๋ก theme์ ์์ฑ๊ณผ media ์์ฑ์ spread ์์ผ์ฃผ๋ฉด ์ ์๋ theme ์์ฑ์ ํต์ผ์ฑ ์๊ฒ ์ฌ์ฉํ ์ ์๊ณ media๋ก ์ ์๋ Media Query ์์ฑ์ ์ฌ์ฉํ ์ ์๋ค.
๋ ๋ฐฉ๋ฒ์ ์ฐจ์ด
๋ ๋ฐฉ๋ฒ์๋ ์ฐจ์ด๊ฐ ํ๋ ์๋ค.
/* ์ฒซ ๋ฒ์งธ medie ์์ฑ์ ๋ชจ๋ํ ํ๊ธฐ */
const Box = styled.div`
@media ${({ theme }) => theme.device.tablet} {
flex-direction: column;
font-size: ${({ theme }) => theme.fontSizes.paragraph};
}
`;
/* ๋ ๋ฒ์งธ ๋ฐฉ๋ฒ media ์ฟผ๋ฆฌ ์์ฒด๋ฅผ ๋ชจ๋ํ ํ๊ธฐ*/
const Box = styled.div`
${({ theme }) => theme.tablet`
flex-direction: column;
font-size: ${({ theme }) => theme.fontSizes.paragraph};
`};
`;
์ฒซ ๋ฒ์งธ ๋ฐฉ๋ฒ์ ๋ฏธ๋์ด ์ฟผ๋ฆฌ ๋ฌธ๋ฒ ์์ฒด๋ฅผ ๋ชจ๋ํ ํ๊ธฐ ๋๋ฌธ์ @media
๋ง ์๋ค ๋ฟ์ด์ง ์ฌ์ฉ๋ฒ ์์ฒด๋ ๋ฏธ๋์ด ์ฟผ๋ฆฌ์ ๋์ผํ๋ค.
๋ ๋ฒ์งธ ๋ฐฉ๋ฒ์ ๋ฌธ๋งฅ์ ์์์ด @media
๋ก ์์ํ๋ฏ๋ก ๋ฏธ๋์ด ์ฟผ๋ฆฌ๊ฐ ์์๋๋ค๊ณ ๋๊ฐ ๋ณด๋๋ผ๋ ์ ์ ์๊ณ ์ง๊ด์ ์ด๋ค.
๋ํ ๋ฏธ๋์ด ์์ฑ์ด ๋ง์์ง๋ ๊ฒฝ์ฐ ์ฒซ ๋ฒ์งธ ๊ฒฝ์ฐ๋ ํ ํ์ผ์ ๋ง์ ์์ฑ๋ค์ด ๋ค์ด๊ฐ ์์ด์ ํท๊ฐ๋ฆด ์ ์๋ ์์๋ค์ด ๋ง์ ๋ฐ๋ฉด ๋ ๋ฒ์งธ๊ฒฝ์ฐ๋ ํ๋์ media.js ํ์ผ์์ ๋ฏธ๋์ด ์์ฑ์ ๋ฐ๋ก ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ ์ฝ๋์ ๋ถ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค.
์ ํ์ ๋ณธ์ธ์๊ฒ ๋ง๋ ๋ฐฉ๋ฒ์ ํ๋ฉด ๋์ง๋ง ํ์๋ผ๋ฉด 2๋ฒ์งธ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๊ฒ ๋ค!
๋๊ธ