Javascript 파일 내에서 CSS를 사용할 수 있게 해주는 대표적인 CSS-in-JS 라이브러리로 React 프레임워크를 주요 대상으로 한 라이브러리이다.
웹팩에서 빌드할 때 하나의 파일로 합쳐지면 className이 전역에서 작동하여 중복된 className이 충돌할 수 있다.
-> 스타일을 컴포넌트 내부에 정의하면 className을 자동으로 생성해주어 전역에서 중복될 일이 없다.
install styled-components
프로젝트에서 사용할 공통 스타일을 정의한다.
const deviceSizes = {
mobileS: "320px",
mobileM: "375px",
mobileL: "450px",
tablet: "768px",
tabletL: "1024px",
};
const device = {
mobileS: `only screen and (max-width: ${deviceSizes.mobileS})`,
mobileM: `only screen and (max-width: ${deviceSizes.mobileM})`,
mobileL: `only screen and (max-width: ${deviceSizes.mobileL})`,
tablet: `only screen and (max-width: ${deviceSizes.tablet})`,
tabletL: `only screen and (max-width: ${deviceSizes.tabletL})`,
};
const colors = {
main: "#6415b7",
};
export const theme = {
device,
colors,
deviceSizes,
};
normalize와 common 스타일을 정의한다.
import { createGlobalStyle } from "styled-components";
import { normalize } from "styled-normalize";
export const GlobalStyle = createGlobalStyle`
${normalize}
@mixin flex($direction: 'row', $align: 'center', $justify: 'center') {
display: flex;
flex-direction: $direction;
align-items: $align;
justify-content: $justify;
}
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}
a {
color: inherit;
text-decoration: none;
}
input, button, select {
background-color: transparent;
border: none;
outline: none;
}
* {
box-sizing: border-box;
}
`;
import { ThemeProvider } from "styled-components";
import { GlobalStyle } from "../styles/globalStyle";
import { theme } from "../styles/theme";
import HeaderContainer from "../components/header";
function MyApp({ Component }) {
return (
<ThemeProvider theme={theme}>
<GlobalStyle />
<HeaderContainer />
<Component />
</ThemeProvider>
);
}
export default MyApp;
import styled from 'styled-components';
const Component = () => {
return (
<StyledComponent />
)
};
export default Component;
const StyledComponent = styled.div`
color: ${({ theme }) => theme.colors.main} /* "#6415b7" */
`;
import styled from 'styled-components';
const Component = () => {
return (
<StyledComponent active={false}/>
)
};
export default Component;
const StyledComponent = styled.div`
color: ${(props) => (props.active ? props.theme.colors.main : "white")} // "white"
`;
기존에 정의한 컴포넌트의 스타일을 가져와, 중복되는 속성은 override 되어 적용된다.
import styled from 'styled-components';
const Component = () => {
return (
<Button1 />
<Button2 />
)
};
export default Component;
const Button1 = styled.button`
color: ${({ theme }) => theme.colors.main};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid ${({ theme }) => theme.colors.main};
border-radius: 3px;
`;
const Button2 = styled(Button1)`
color: white;
border-color: white
`;
import styled from 'styled-components';
const Component = () => {
return (
<Button />
<Button />
<Button />
)
};
export default Component;
const Button = styled.button`
color: blue;
&:hover { color: red; }
& ~ & { color: yellow; } // 건너서 있을때 -> <Button> <div> <Button>
& + & { color: green; } // 바로 옆에 있을때
&& { color: blue; } // 전역 스타일 무시 }
`;
import styled from 'styled-components';
const Component = () => {
return (
<MixinFlex />
)
};
export default Component;
const flexcenter = css`
display: flex;
justify-content: center;
align-items: center;
`;
const MixinFlex = styled.div`
${flexcenter}
border: 0.0625rem solid rgb(100, 21, 183);
`;