Vanilla Extract

Published at 2025-03-25

Vanilla Extract

날짜: 2025년 3월 25일

Vanilla ExtractTypeScript 기반의 CSS-in-JS 라이브러리로, 정적 CSS를 생성하면서도 타입 안정성을 제공하는 것이 특징입니다.

Vanilla Extract VS Styled-Components

특징Vanilla Extract 🌿Styled-Components 🎨
스타일 적용 방식정적 CSS 파일 생성 (Zero-runtime)런타임에 동적으로 생성
사용 언어TypeScript 기반JavaScript 기반
CSS 변수 지원디자인 토큰 관리 가능ThemeProvider 사용
스타일링 방식클래스를 직접 사용JSX 내에서 styled.div 등 사용

Vanilla Extract에서 스타일링

[button.css.ts]

import { style } from '@vanilla-extract/css';

export const primaryButton = style({
  padding: '10px 20px',
  borderRadius: '5px',
  border: 'none',
  backgroundColor: 'blue',
  color: 'white',
});

[Button.tsx]

import React from 'react';
import { button } from './button.css';

export default function Button() {
  return <button className={primaryButton}>Click Me</button>; // 생성된 클래스를 `className`에 할당
}

직접 props를 전달 받을 수 없는 Vanilla Extract에서 동적 스타일링 하는 방법

  • className을 조건부로 변경
  • css 변수로 props 값을 동적으로 사용

예시

  • 인풋 1에서 입력한 값으로 인풋 2의 width 를 변경해보기

[input.css.ts]

import { style } from '@vanilla-extract/css';

export const input = style({
  padding: '8px',
  border: '1px solid #ccc',
  borderRadius: '4px',
  fontSize: '16px',
  width: 'var(--dynamic-width, 200px)', // 변수 이름 정의
});

[input.tsx]

import React, { useState } from 'react';
import { input } from './input.css';

export default function InputComponent() {
  const [width, setWidth] = useState<number>(200); // 기본값 200px

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    const numericValue = value ? Number(value) : 0; // 숫자만 받도록 처리
    setWidth(numericValue);
  };

  return (
    <div>
      {/* 1번 인풋 - 숫자 입력 */}
      <input
        type="number"
        value={width}
        onChange={handleInputChange}
        placeholder="Enter width"
        style={{ marginBottom: '10px' }}
      />
      <br />
      
      {/* 2번 인풋 - width 값에 따라 동적으로 변경 */}
      <input
        className={input}
        style={{ '--dynamic-width': `${width}px` } as React.CSSProperties} // 설정한 변수로 값 적용
        placeholder="Resizable Input"
      />
    </div>
  );
}

CSS-in-JS?

  • CSS를 JavaScript 코드 안에서 정의하고 컴포넌트와 함께 관리할 수 있다.
  • props나 state 값에 따라 스타일을 실시간으로 변경할 수 있다.

css 파일에서 디자인 토큰 예시:

[.css]

:root {
  --primary-color: #007bff;
  --secondary-color: #6c757d;
  --font-size-small: 12px;
  --font-size-medium: 16px;
  --font-size-large: 24px;
}
.button {
  background-color: var(--primary-color);
  font-size: var(--font-size-medium);
}