Emotion은 Styled-components와 함께 가장 대중적으로 사용되는 CSS-in-JS 방식의 Styling 라이브러리이다.
Next.js + TS환경에서 Emotion을 적용했다.
npm i @emotion/react // React 환경에서 설치
npm i @emotion/styled @emotion/react // styled 컴포넌트 형태로 사용가능
npm install --save-dev @emotion/babel-plugin
{
"presets": [
[
"next/babel",
{
"preset-react": {
"runtime": "automatic",
"importSource": "@emotion/react"
}
}
]
],
"plugins": ["@emotion"]
}
"jsx": "react-jsx",
"jsxImportSource": "@emotion/react"
2가지 css prop 형식과 styled component형식 혼용가능함 => - 코드 재사용, 컴포넌트 재사용 여부에 따라 사용하면 됨.
css() 함수에 넣을때 문자열 or 객체형식으로 넣을 수 있는데, 객체형식이 권장됨.
css() 함수를 호출을 생략하고 css prop에 바로 객체를 넘길 수 있으며, 특히 타입스크립트(TypeScript)를 사용하면 타입 체킹(type checking)을 통해 버그도 줄일 수 있기 때문.
const titleStyle = css({
backgroundColor: "yellow",
fontSize: "30px",
"& .namefsd": {
border: "10px solid black",
maringTop: "100px",
},
"& > div": {
border: "10px solid black",
maringTop: "100px",
backgroundColor: "crimson",
},
});
import { css } from '@emotion/react'
const hotpink = css({
color: 'hotpink'
})
const hotpinkHoverOrFocus = css({
'&:hover,&:focus': hotpink
})
const hotpinkWithBlackBackground = css(
{
backgroundColor: 'black',
color: 'green'
},
hotpink
)
/// 이런식으로도 사용가능
const buttonStyle = css({
border: "10px solid black",
maringTop: "100px",
backgroundColor: "crimson",
});
const titleStyle = css({
backgroundColor: "yellow",
fontSize: "30px",
"& > div": buttonStyle,
});
const titleStyle = css({
fontSize: "30px",
"& > div": buttonStyle, // titleStyle아래 div자식태그들 모두 선택
button: {
backgroundColor: "green",
width: 100,
}, // titleStyle아래 div태그 선택
"div &": {
backgroundColor: "blue",
height: 1000,
}, // titleStyle 부모요소중 가장 가까운 div태그 선택
"#contain &": {
backgroundColor: "black",
},
});
Global 컴포넌트 사용가능, 여기 styles 속성에 전역 스타일을 정의해주면 됨
Global은 컴포넌트는 children을 가질 수 없음, global.style.ts처럼 파일을 정의해줘야함.
//_app.tsx
import globalStyle from "@/styles/global.style";
function App({ Component, pageProps }: AppProps) {
return (
<Provider>
<Global styles={globalStyle} />
<Layout>
<Component {...pageProps} />
</Layout>
</Provider>
);
}
export default App;
//global.style.ts
import { css } from "@emotion/react";
const globalStyle = css`
html,
body {
padding: 0;
margin: 0;
overflow-y: auto;
background-color: pink;
}
a {
color: inherit;
text-decoration: none;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
`;
export default globalStyle;
문자열 방식이던, 객체로 사용하는 방식이던 자주 사용하는 것들을 js 객체에서 뽑아낼 수 있음.
아니면 객체형식에서 style을 정의해놓을수도 있음
const cardCss = {
self: css({
backgroundColor: 'white',
border: '1px solid #eee',
borderRadius: '0.5rem',
padding: '1rem'
}),
title: css({
fontSize: '1.25rem'
})
}
export const colors = {
primary: '#0d6efd',
success: '#198754',
danger: '#dc3545'
}
style prop을 사용해서 동적스타일링을 정의 할 수 있다.
style prop이란? React 컴포넌트에 동적으로 스타일을 적용하기 위한 prop입니다.
이 prop을 사용하면 JavaScript 객체로 정의된 스타일을 컴포넌트에 적용할 수 있습니다. Emotion은 이 스타일 객체를 CSS-in-JS 스타일로 컴파일하고 컴포넌트의 HTML 요소에 스타일을 적용합니다.
JS 코드를 통해 동적으로 스타일링을 적용가능함. (객체형태로 style을 적용하는 방식임.
function generateDynamicStyles(dynamicColor : string) {
return {
backgroundColor: dynamicColor,
padding: "10px",
color: "white",
};
} // prop을 받아서 동적으로 스타일을 만들어냄
export default function TodoList({color}) {
const dynamicStyle = generateDynamicStyles(color);
return (
...
<div style={dynamicStyle}>test</div>
...
)
}
/** @jsxImportSource @emotion/react */
const fontSize = {
small: "14px",
medium: "16px",
large: "18px",
};
function Button({ children, variant = "medium" }) {
return (
<button
css={{
borderRadius: "6px",
fontSize: fontSize[variant],
}}
>
{children}
</button>
);
}
export default Button;
ref) 공식문서 : https://emotion.sh/docs/object-styles