Vanilla extract 통합
Vanilla extract 통합
Vanilla extract는 빌드 시점에 정적 CSS 파일을 생성하는 TypeScript CSS 전처리기예요. 스타일을 TypeScript로 작성하는 것을 선호한다면 CSS Modules의 훌륭한 대안이에요.
출처: 문서
본문
Vanilla extract vs CSS Modules
Vanilla extract와 CSS Modules은 같은 일을 하지만 문법이 달라요. Vanilla extract와 CSS Modules의 공통 기능:
-
스타일이 빌드 시점에 생성돼요 – 런타임과 성능 오버헤드가 없어요
-
클래스 이름이 스타일 파일로 스코프돼요
Vanilla extract와 CSS Modules의 차이점:
-
Vanilla extract 스타일은 타입 안전(type-safe)해요
-
Vanilla extract 스타일에서 색상 함수를 포함한 어떤 JavaScript/TypeScript 코드든 사용할 수 있어요
-
Vanilla extract에서는
light-dark함수와hover믹스인 같은 postcss-preset-mantine 기능에 접근할 수 없어요. 이 때문에 Mantine 문서의 모든 데모를 복사-붙여넣기해서 Vanilla extract와 함께 쓸 수는 없어요. -
Vanilla extract는 빌드 도구/프레임워크에서 사용할 수 없는 추가 구성과 설정이 필요해요. Next.js와 Vite 같은 가장 인기 있는 도구는 Vanilla extract 플러그인을 가지지만, 더 틈새적인 것을 사용한다면 직접 구성해야 할 수도 있어요.
같은 프로젝트에서 Vanilla extract와 CSS Modules을 둘 다 사용할 수 있다는 점에 주의하세요; 문제가 발생하지 않아요: 성능은 같고 번들 크기도 영향받지 않아요.
설치
설치 안내를 따라 Vanilla extract를 설치해요. 그런 다음 @mantine/vanilla-extract 패키지를 설치해요; 이 패키지는 Mantine theme을 CSS variables로 변환하는 themeToVars 함수를 내보내요:
yarn add @mantine/vanilla-extract
템플릿
시작하려면 다음 템플릿 중 하나를 사용하거나 자신의 설정을 위한 참고 자료로 삼을 수 있어요. 모든 템플릿은 최소한의 설정만 포함한다는 점에 주의하세요.
| 템플릿 | 설명 | 링크 |
|---|---|---|
| next-vanilla-extract-template | Vanilla extract 예시가 있는 Next.js 템플릿 | Use template |
| vite-vanilla-extract-template | Vanilla extract 예시가 있는 Vite 템플릿 | Use template |
Theming
Vanilla extract는 주어진 theme 객체를 CSS variables로 변환하고 :root 또는 다른 selector에 할당하는 createTheme 함수를 제공해요. Mantine theme 토큰을 생성하는 데 Vanilla extract의 createTheme를 사용하지 마세요 – 모든 Mantine theme 속성은 이미 CSS variables로 노출돼 있어요. 대신 @mantine/vanilla-extract 패키지의 themeToVars 함수를 사용해 Mantine theme에서 CSS variables 객체를 만들어요:
// theme.ts
import { createTheme } from '@mantine/core';
// Do not forget to pass theme to MantineProvider
export const theme = createTheme({
fontFamily: 'serif',
primaryColor: 'cyan',
});
// theme.css.ts
import { theme } from './theme';
import { themeToVars } from '@mantine/vanilla-extract';
// CSS variables object, can be access in *.css.ts files
export const vars = themeToVars(theme);
스타일링
*.css.ts 파일에서 vars 객체를 import 해 Mantine CSS variables에 접근해요:
// Demo.css.ts
import { style } from '@vanilla-extract/css';
import { vars } from './theme';
export const demo = style({
fontSize: vars.fontSizes.xl,
backgroundColor: vars.colors.red[5],
color: vars.colors.white,
});
rem과 em
px를 rem 또는 em으로 변환하려면 @mantine/core 패키지의 rem과 em 함수를 사용해요:
// Demo.css.ts
import { style } from '@vanilla-extract/css';
import { rem } from '@mantine/core';
export const demo = style({
fontSize: rem(16),
'@media': {
[`(min-width: ${em(768)})`]: {
fontSize: rem(18),
},
},
});
light와 dark selectors
vars 객체에는 light 또는 dark 색상 체계에서만 스타일을 적용하는 데 사용할 수 있는 lightSelector와 darkSelector 속성이 있어요:
// Demo.css.ts
import { style } from '@vanilla-extract/css';
import { vars } from './theme';
export const demo = style({
fontSize: vars.fontSizes.xl,
selectors: {
[vars.lightSelector]: {
backgroundColor: vars.colors.red[5],
color: vars.colors.white,
},
[vars.darkSelector]: {
backgroundColor: vars.colors.blue[5],
color: vars.colors.white,
},
},
});
보통 둘 중 하나만 사용하는 것이 더 편리해요: light 색상 체계의 스타일을 적용한 다음 vars.darkSelector(또는 그 반대)로 dark 색상 체계에서 재정의해요:
// Demo.css.ts
import { style } from '@vanilla-extract/css';
import { vars } from './theme';
export const demo = style({
fontSize: vars.fontSizes.xl,
backgroundColor: vars.colors.red[5],
color: vars.colors.white,
selectors: {
[vars.darkSelector]: {
backgroundColor: vars.colors.blue[5],
color: vars.colors.white,
},
},
});
largerThan과 smallerThan
vars 객체에는 @media에서 min-width와 max-width의 축약형으로 사용할 수 있는 largerThan과 smallerThan 속성이 있어요:
// Demo.css.ts
import { style } from '@vanilla-extract/css';
import { vars } from './theme';
export const demo = style({
fontSize: vars.fontSizes.sm,
'@media': {
// equivalent to `(min-width: 640px)` converted to em
// -> `(min-width: 40em)`
[vars.largerThan(640)]: {
fontSize: vars.fontSizes.md,
},
// equivalent to `(max-width: 640px)` converted to em
// -> `(max-width: 40em)`
[vars.smallerThan(640)]: {
fontSize: vars.fontSizes.xs,
},
// You can reference `theme.breakpoints` values
[vars.largerThan('sm')]: {
fontSize: vars.fontSizes.md,
},
},
});
rtl selector
vars.rtlSelector를 사용해 rtl 방향에서만 스타일을 적용해요:
// Demo.css.ts
import { style } from '@vanilla-extract/css';
import { vars } from './theme';
export const demo = style({
paddingRight: vars.spacing.md,
selectors: {
[vars.rtlSelector]: {
paddingLeft: vars.spacing.md,
paddingRight: 0,
},
},
});