"매 TypeScript 로 type-safe 한 zero-runtime CSS-in-JS". 매 Mark Dalgleish (Seek) 가 2021 년 출시. 매 .css.ts 파일을 build time 에 static CSS 로 추출, 매 token / variant / theme 매 모두 typed. 매 Next.js App Router (RSC) 의 사실상 표준, 매 component library 배포 의 zero-runtime guarantee.
매 핵심
매 핵심 API
style({...}): 매 single CSS class 생성 → unique class name 반환.
globalStyle('selector', {...}): 매 global selector style.
recipe({base, variants}): 매 variant-based component (CVA-like, type-safe).
createTheme(contract, values): 매 token 의 ThemeProvider 대안.
createThemeContract({...}): 매 token shape 정의 (multi-theme).
createVar(): 매 CSS custom property (runtime dynamic).
// reset.css.ts
import{globalStyle}from'@vanilla-extract/css';globalStyle('html, body',{margin: 0,padding: 0,fontFamily:'system-ui, sans-serif',});globalStyle('*',{boxSizing:'border-box',});// 매 import 'one' 으로 reset 적용
// app.tsx: import './reset.css';
Dynamic value via createVar
// progress.css.ts
import{createVar,style}from'@vanilla-extract/css';exportconstprogressVar=createVar();exportconstbar=style({width: progressVar,background:'blue',height: 4,transition:'width 0.3s',});// progress.tsx
import{assignInlineVars}from'@vanilla-extract/dynamic';<divclassName={bar}style={assignInlineVars({[progressVar]:`${percent}%`})}/>// 매 runtime dynamic — CSS variable 로 변환.
Style composition
import{style}from'@vanilla-extract/css';constbase=style({padding: 8,fontSize: 14});constprimary=style([base,{background:'blue',color:'white'}]);// 매 primary class = base class + extra rules.
Next.js App Router setup
// next.config.js
const{createVanillaExtractPlugin}=require('@vanilla-extract/next-plugin');constwithVanillaExtract=createVanillaExtractPlugin();module.exports=withVanillaExtract({// ... existing config
});// app/layout.tsx
import{lightTheme}from'./theme.css';import'./reset.css';exportdefaultfunctionRootLayout({children}){return<htmlclassName={lightTheme}>{children}</html>;}// 매 RSC 호환 — server component 에서 매 className 사용 가능.
언제: Next.js App Router (RSC), type-safe design system, component library 배포, multi-theme (light/dark/brand) 의.
언제 X: 매 simple prototype (Tailwind 매 빠름), 매 highly-dynamic per-pixel value (CSS-in-JS runtime 가 더 적합), 매 already emotion / styled-components codebase 의 incremental migration 어려움.
❌ 안티패턴
Runtime value 직접 사용: 매 style({ width: dynamicWidth }) — dynamicWidth 매 build time 에 evaluable 해야. 매 runtime 매 createVar.
.css.ts 의 conditional logic: 매 if (env.X) 매 build-time evaluated — 매 runtime 분기 X.
Theme class 의 dynamic apply 미숙: 매 theme 변경 시 <html className={isDark ? darkTheme : lightTheme}> — 매 root 단위.
plugin setup 누락: 매 webpack/vite plugin 없으면 .css.ts 매 그냥 TS file 로 처리 — error.
recipe 의 base 의 selector: 매 recipe base 안의 selectors 매 매 supported 하나 매 syntax 주의.
🧪 검증 / 중복
Verified (vanilla-extract.style 공식 문서, GitHub seek-oss/vanilla-extract).
신뢰도 A.
🕓 Changelog
날짜
변경
2026-05-08
Phase 1
2026-05-10
Manual cleanup — vanilla-extract API 전체 (style, recipe, theme contract, sprinkles, createVar) 추가