[Next.js] vanilla-extract 기본 사용법
Next.js를 공부하면서 스타일시트로 vanilla extract를 즐겨 사용하고 있습니다. 사용할 때마다 매번 찾아보기 귀찮아서 세팅 방법과 간단한 사용법을 정리 해두었습니다.
Install
npm install @vanilla-extract/css
Next.js 사용 시 필요한 추가 플러그인 설치 및 next.config 파일 수정
npm install --save-dev @vanilla-extract/next-plugin
// next.config.ts
import type { NextConfig } from "next";
import { createVanillaExtractPlugin } from "@vanilla-extract/next-plugin";
const withVanillaExtract = createVanillaExtractPlugin();
const nextConfig: NextConfig = {
/* config options here */
};
export default withVanillaExtract(nextConfig);
글로벌 스타일, 테마 적용
import {
createGlobalTheme,
globalFontFace,
globalStyle,
} from "@vanilla-extract/css";
export const vars = createGlobalTheme(":root", {
colors: {
grey: {
50: "hsl(265, 55%, 96%)",
100: "hsl(265, 19%, 88%)",
200: "hsl(265, 7%, 70%)",
300: "hsl(265, 6%, 66%)",
400: "hsl(265, 4%, 57%)",
500: "hsl(265, 3%, 53%)",
600: "hsl(265, 4%, 42%)",
700: "hsl(265, 4%, 31%)",
800: "hsl(276, 5%, 20%)",
900: "hsl(280, 5%, 13%)",
},
primary: {
50: "#c8b3ce",
100: "#a07aaa",
200: "#884c97",
300: "#843897",
400: "#732392",
500: "#5a097a",
600: "#480264",
700: "#3d0264",
},
success: {
100: "#a2f0bc",
500: "#12bd4b",
},
error: {
100: "#f1acc9",
500: "#a10c4a",
},
},
sizes: {
1: "0.25rem",
2: "0.5rem",
3: "0.75rem",
4: "1rem",
5: "1.25rem",
6: "1.5rem",
8: "2rem",
16: "4rem",
20: "5rem",
40: "10rem",
},
});
globalStyle("*", {
boxSizing: "border-box",
});
globalStyle("body", {
margin: 0,
backgroundColor: vars.colors.grey[500],
color: "#252525",
fontFamily: '"BookkMyungjo-Bd"',
});
globalFontFace("BookkMyungjo-Bd", {
src: 'url("https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_2302@1.0/BookkMyungjo-Bd.woff2") format("woff2")',
fontWeight: "700",
fontStyle: "normal",
});
globalStyle("a", {
textDecoration: "none",
});
globalStyle("button", {
fontFamily: "inherit",
cursor: "pointer",
});
프로젝트 루트 컴포넌트에 해당 스타일 파일 import
// _app.tsx
import Layout from "@/components/layout/layout";
import "@/styles/globals.css";
import type { AppProps } from "next/app";
export default function App({ Component, pageProps }: AppProps) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
기본 사용법
1. 스타일 객체 생성 및 export
// button.css.ts
import { style } from "@vanilla-extract/css";
import { vars } from "@/styles/globals.css";
export const button = style({
padding: 10,
color: vars.colors.primary[50],
fontSize: 20,
});
2. 사용할 곳에서 import 및 객체 접근
// button.tsx
import * as styles from "./button.css";
export default function Button() {
return <button className={styles.button}>Button</button>;
}
3. selectors, media query
Selectors
// button.css.ts
import { style } from "@vanilla-extract/css";
import { vars } from "@/styles/globals.css";
export const button = style({
padding: 10,
color: vars.colors.primary[50],
fontSize: 20,
// selectors
":hover": {
backgroundColor: "red",
},
// or
selectors: {
"&:active": {
color: "blue",
},
"nav li > &": {
color: "green",
},
},
});
// button.tsx
import * as styles from "./button.css";
export default function Button() {
return (
<div>
<button className={styles.button}>button 1</button>
<nav>
<li>
<button className={styles.button}>button 2</button>
</li>
</nav>
</div>
);
}
4. Media query
// button.css.ts
import { style } from "@vanilla-extract/css";
import { vars } from "@/styles/globals.css";
export const button = style({
// ...
"@media": {
"(max-width: 768px)": {
fontSize: 10,
},
},
});
5. 스타일 확장
// buttons.css.ts
import { style } from "@vanilla-extract/css";
const baseButton = style({
padding: 10,
});
export const primaryButton = style([
baseButton,
{
color: "red",
backgroundColor: "blue",
},
]);
export const secondaryButton = style([
baseButton,
{
color: "blue",
backgroundColor: "pink",
},
]);
그 외에도 여러 기능들이 많지만 최소한으로 필요한 간단한 사용법만 정리 해두었습니다. 더 학습해보다가 추가 할 것이 있다면 추가 할 예정입니다🫡