Featuring Design System

CSS Usage

CSS 변수를 사용하여 디자인 토큰 활용하기

CSS 파일을 import하면 모든 디자인 토큰이 :root에 CSS 변수로 등록됩니다. JavaScript 없이 순수 CSS만으로 스타일링하세요.

CSS Preset Import

앱 진입점에서 Preset CSS를 import합니다. Preset 하나로 Reset, Normalize, 브랜드 토큰, CSS Layer 순서가 모두 설정됩니다.

Featuring 테마

// _app.tsx, main.tsx, 또는 layout.tsx
import '@featuring-corp/components/preset/featuring';

DataEffect 테마

// _app.tsx, main.tsx, 또는 layout.tsx
import '@featuring-corp/components/preset/dataEffect';

CSS Cascade Layers: Preset은 ft-reset < ft-normalize < ft-components < ft-utilities 레이어 순서를 선언합니다. $css prop의 유틸리티 스타일이 컴포넌트 기본 스타일보다 우선하며, 소비자 CSS는 레이어에 속하지 않으므로 항상 디자인 시스템 스타일보다 우선합니다.

CSS Cascade Layers

레이어 구조

Preset은 네 개의 독립 레이어를 선언합니다.

레이어역할우선순위
ft-resetMeyer reset — 브라우저 기본 스타일 초기화가장 낮음
ft-normalizenormalize + 스크롤바 CSS
ft-components컴포넌트 CSS (vanilla-extract)
ft-utilities$css prop atomic CSS (rainbow-sprinkles)
unlayered소비자 CSS가장 높음

ft- (하이픈)인가?

CSS 스펙상 ft.reset 같은 dot 구분은 ft 부모 레이어 아래 서브레이어로 묶입니다. 부모 레이어는 cascade에서 하나의 위치만 차지하므로, 서브레이어를 외부 레이어(예: Tailwind의 base, utilities)와 개별적으로 인터리빙할 수 없습니다.

ft-reset 같은 하이픈 구분은 독립 레이어라 자유롭게 배치 가능합니다.

Tailwind CSS v4와 함께 사용

Tailwind v4도 CSS Cascade Layers를 사용합니다. 두 시스템을 함께 쓸 때 entry CSS에서 레이어 순서를 직접 선언하세요.

/* reset/normalize는 Tailwind 아래, components/utilities는 Tailwind 위 */
@layer ft-reset, ft-normalize;

@import 'tailwindcss/preflight.css' layer(tw-base);
@import 'tailwindcss/theme.css' layer(tw-theme);
@import 'tailwindcss/utilities.css' layer(tw-utilities);

@layer ft-components, ft-utilities;

@import '@featuring-corp/components/preset/featuring';

이렇게 하면:

  • ft-reset, ft-normalize — Tailwind base보다 낮은 우선순위 (리셋 충돌 방지)
  • ft-components, ft-utilities — Tailwind utilities보다 높은 우선순위 (컴포넌트 스타일 정상 적용)

Preset 내부의 @layer 순서 선언보다 소비자의 선언이 먼저 오면 소비자 순서가 우선합니다. CSS 스펙에서 첫 번째 선언이 순서를 결정합니다.

레이어 순서 선언 없이 사용

Tailwind 없이 단독으로 사용한다면 별도 선언이 필요 없습니다. Preset이 기본 순서를 선언합니다.

// 이것만으로 충분
import '@featuring-corp/components/preset/featuring';

CSS 변수 사용법

기본 예시

.my-card {
	/* 배경색 */
	background-color: var(--semantic-color-background-1);

	/* 테두리 */
	border: 1px solid var(--semantic-color-border-default);
	border-radius: var(--global-radius-200);

	/* 간격 */
	padding: var(--global-spacing-400);
	margin-bottom: var(--global-spacing-200);

	/* 그림자 */
	box-shadow: var(--global-elevation-4);
}

.my-card-title {
	/* 타이포그래피 */
	font-size: var(--semantic-typography-heading-2-font-size);
	font-weight: var(--semantic-typography-heading-2-font-weight);
	line-height: var(--semantic-typography-heading-2-line-height);

	/* 텍스트 색상 */
	color: var(--semantic-color-text-1);
}

.my-card-description {
	font-size: var(--semantic-typography-body-2-font-size);
	color: var(--semantic-color-text-2);
}

버튼 스타일링

.primary-button {
	background-color: var(--global-colors-primary-60);
	color: var(--global-colors-white);
	border: none;
	border-radius: var(--global-radius-100);
	padding: var(--global-spacing-150) var(--global-spacing-300);
	font-size: var(--global-typography-fontSize-300);
	font-weight: var(--global-typography-fontWeight-semiBold);
	cursor: pointer;
	transition: background-color 0.2s;
}

.primary-button:hover {
	background-color: var(--global-colors-primary-70);
}

.primary-button:active {
	background-color: var(--global-colors-primary-80);
}

.primary-button:disabled {
	background-color: var(--semantic-color-toggle-disabled-bg);
	color: var(--semantic-color-toggle-disabled-text);
	cursor: not-allowed;
}

상태 피드백

.success-message {
	background-color: var(--semantic-color-support-success-4);
	border: 1px solid var(--semantic-color-support-success-1);
	color: var(--semantic-color-support-success-1);
	padding: var(--global-spacing-200) var(--global-spacing-300);
	border-radius: var(--global-radius-100);
}

.error-message {
	background-color: var(--semantic-color-support-error-4);
	border: 1px solid var(--semantic-color-support-error-1);
	color: var(--semantic-color-support-error-1);
	padding: var(--global-spacing-200) var(--global-spacing-300);
	border-radius: var(--global-radius-100);
}

.warning-message {
	background-color: var(--global-colors-yellow-10);
	border: 1px solid var(--semantic-color-support-warning-1);
	color: var(--semantic-color-support-warning-1);
	padding: var(--global-spacing-200) var(--global-spacing-300);
	border-radius: var(--global-radius-100);
}

CSS 변수 목록

Colors (색상)

Primary (테마별로 다름)

변수명FeaturingDataEffect
--global-colors-primary-10#ecefff#edf5ff
--global-colors-primary-20#dce2ff#d0e2ff
--global-colors-primary-30#c0c8ff#a6c8ff
--global-colors-primary-40#9aa3ff#4c9aff
--global-colors-primary-50#7273ff#2684ff
--global-colors-primary-60#5e51ff#0065ff
--global-colors-primary-70#5032f9#0052cc
--global-colors-primary-80#3821b2#0747a6
--global-colors-primary-90#31238c#001d6c
--global-colors-primary-100#1f1551#001141

Gray

변수명
--global-colors-gray-5#fafafa
--global-colors-gray-10#f6f6f6
--global-colors-gray-15#f0f0f0
--global-colors-gray-20#ebebeb
--global-colors-gray-30#e0e0e0
--global-colors-gray-40#d2d2d2
--global-colors-gray-50#bbbbbb
--global-colors-gray-60#959595
--global-colors-gray-70#707070
--global-colors-gray-80#424242
--global-colors-gray-90#242424
--global-colors-white#ffffff
--global-colors-black#000000

더 많은 색상 변수는 Colors 문서를 참조하세요.

Spacing (간격)

변수명
--global-spacing-00
--global-spacing-250.0625rem
--global-spacing-500.125rem
--global-spacing-1000.25rem
--global-spacing-1500.375rem
--global-spacing-2000.5rem
--global-spacing-2500.625rem
--global-spacing-3000.75rem
--global-spacing-4001rem
--global-spacing-5001.25rem
--global-spacing-6001.5rem
--global-spacing-8002rem
--global-spacing-10002.5rem
--global-spacing-12003rem
--global-spacing-16004rem
--global-spacing-20005rem

Radius (모서리)

변수명
--global-radius-502px
--global-radius-1004px
--global-radius-2008px
--global-radius-30012px
--global-radius-40016px
--global-radius-full999px

Elevation (그림자)

변수명설명
--global-elevation-2미세한 그림자 (2dp)
--global-elevation-4카드 그림자 (4dp)
--global-elevation-8팝오버 그림자 (8dp)
--global-elevation-16드롭다운 그림자 (16dp)
--global-elevation-28모달 그림자 (28dp)
--global-elevation-64최상위 그림자 (64dp)

Typography (타이포그래피)

Heading

변수명font-sizefont-weightline-height
--semantic-typography-heading-1-*0.75rem5001.125rem
--semantic-typography-heading-2-*0.875rem5001.375rem
--semantic-typography-heading-3-*1rem5001.5rem
--semantic-typography-heading-4-*1.25rem5001.75rem
--semantic-typography-heading-5-*1.5rem5002.125rem
--semantic-typography-heading-6-*2rem5002.5rem
--semantic-typography-heading-7-*2.5rem5003.25rem

Body

변수명font-sizefont-weightline-height
--semantic-typography-body-1-*0.75rem4001.125rem
--semantic-typography-body-2-*0.875rem4001.375rem
--semantic-typography-body-3-*1rem4001.5rem
--semantic-typography-body-4-*1.125rem4001.625rem

Caption

변수명font-sizefont-weightline-height
--semantic-typography-caption-1-*0.6875rem4001rem
--semantic-typography-caption-2-*0.75rem4001.125rem

Semantic Colors (시맨틱 색상)

Background

변수명용도
--semantic-color-background-1기본 배경 (white)
--semantic-color-background-2보조 배경 (gray-5)
--semantic-color-background-3강조 배경 (gray-10)
--semantic-color-background-4최상위 배경 (gray-20)
--semantic-color-background-5다크 배경 (gray-90)

Border

변수명용도
--semantic-color-border-default기본 테두리 (gray-15)
--semantic-color-border-1테두리 1 (gray-30)
--semantic-color-border-2테두리 2 (gray-40)
--semantic-color-border-3테두리 3 (gray-50)
--semantic-color-border-4진한 테두리 (gray-60)

Text

변수명용도
--semantic-color-text-1기본 텍스트 (gray-90)
--semantic-color-text-2보조 텍스트 (gray-80)
--semantic-color-text-3비활성 텍스트 (gray-70)
--semantic-color-text-4플레이스홀더 (gray-60)
--semantic-color-text-5연한 텍스트 (gray-50)
--semantic-color-text-6반전 텍스트 (white)

Support

변수명용도
--semantic-color-support-error-1에러 연한 (red-10)
--semantic-color-support-error-2에러 (red-20)
--semantic-color-support-error-3에러 강조 (red-50)
--semantic-color-support-error-4에러 진한 (red-100)
--semantic-color-support-warning-1경고 연한 (orange-10)
--semantic-color-support-warning-2경고 (orange-20)
--semantic-color-support-warning-3경고 강조 (orange-50)
--semantic-color-support-warning-4경고 진한 (orange-100)
--semantic-color-support-success-1성공 연한 (green-10)
--semantic-color-support-success-2성공 (green-20)
--semantic-color-support-success-3성공 강조 (green-50)
--semantic-color-support-success-4성공 진한 (green-100)
--semantic-color-support-info-1정보 연한 (primary-10)
--semantic-color-support-info-2정보 (primary-20)
--semantic-color-support-info-3정보 강조 (primary-60)
--semantic-color-support-info-4정보 진한 (primary-100)