$css Prop
Rainbow Sprinkles 기반의 $css prop으로 토큰 기반 스타일링하기
$css prop은 Featuring Design System의 핵심 스타일링 API입니다. Rainbow Sprinkles를 기반으로, 디자인 토큰 값과 임의 CSS 값을 하나의 prop에서 사용할 수 있습니다.
기본 사용법
모든 레이아웃 컴포넌트(Box, Flex, HStack, VStack, Center, Grid, Typo)와 Button 컴포넌트에서 $css prop을 사용할 수 있습니다.
<Box $css={{ padding: '$spacing-400', borderRadius: '$radius-200', backgroundColor: '$background-1', color: '$text-1', }}> Hello World </Box>
토큰 값 vs 임의 값
$css prop은 토큰 참조와 임의 CSS 값을 모두 지원합니다. 토큰 이름을 문자열로 전달하면 자동으로 CSS 변수로 변환됩니다.
<Box $css={{ // 토큰 값 padding: '$spacing-400', borderRadius: '$radius-200', // 임의 CSS 값 width: '100%', maxWidth: '480px', border: '1px solid', borderColor: '$border-default', }}> 토큰 + 임의 값 혼합 </Box>
레이아웃 속성
레이아웃 관련 속성은 반응형 조건(mobile/tablet/desktop/wide)을 지원합니다.
Display & Flex
<Flex $css={{ gap: '$spacing-300', padding: '$spacing-400', borderRadius: '$radius-200', border: '1px solid', borderColor: '$border-default', }}> <Box $css={{ flex: '1', padding: '$spacing-300', bgColor: '$primary-10', borderRadius: '$radius-100', textAlign: 'center', }}>flex: 1</Box> <Box $css={{ flex: '2', padding: '$spacing-300', bgColor: '$primary-20', borderRadius: '$radius-100', textAlign: 'center', }}>flex: 2</Box> <Box $css={{ flex: '1', padding: '$spacing-300', bgColor: '$primary-10', borderRadius: '$radius-100', textAlign: 'center', }}>flex: 1</Box> </Flex>
Spacing
<HStack $css={{ gap: '$spacing-300' }}> <Box $css={{ padding: '$spacing-200', bgColor: '$primary-10', borderRadius: '$radius-100', }}>spacing-200</Box> <Box $css={{ padding: '$spacing-400', bgColor: '$primary-20', borderRadius: '$radius-100', }}>spacing-400</Box> <Box $css={{ padding: '$spacing-600', bgColor: '$primary-30', borderRadius: '$radius-100', }}>spacing-600</Box> </HStack>
Sizing
<Box $css={{
width: '100%',
height: '48px',
minWidth: '200px',
maxWidth: '640px',
minHeight: '100vh',
size: '40px', // width + height 동시 설정
}} />Border & Radius
<HStack $css={{ gap: '$spacing-300' }}> <Box $css={{ size: '64px', bgColor: '$primary-20', borderRadius: '$radius-100', display: 'flex', alignItems: 'center', justifyContent: 'center', }}>100</Box> <Box $css={{ size: '64px', bgColor: '$primary-30', borderRadius: '$radius-200', display: 'flex', alignItems: 'center', justifyContent: 'center', }}>200</Box> <Box $css={{ size: '64px', bgColor: '$primary-40', borderRadius: '$radius-full', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white', }}>full</Box> </HStack>
Grid
<Grid $css={{ gridTemplateColumns: 'repeat(3, 1fr)', gap: '$spacing-300', }}> {[1,2,3,4,5,6].map(i => ( <Box key={i} $css={{ padding: '$spacing-400', bgColor: '$primary-10', borderRadius: '$radius-100', textAlign: 'center', border: '1px solid', borderColor: '$primary-30', }}> {i} </Box> ))} </Grid>
Typography
<Box $css={{
fontSize: '14px',
fontWeight: '600',
fontFamily: 'var(--global-typography-font-sans)',
lineHeight: '1.5',
textAlign: 'center',
textDecoration: 'underline',
textTransform: 'uppercase',
letterSpacing: '-0.02em',
wordBreak: 'break-word',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
overflow: 'hidden',
}} />Position
<Box $css={{
position: 'absolute',
top: '0',
right: '0',
bottom: '0',
left: '0',
inset: '0', // top + right + bottom + left
insetX: '16px', // left + right
insetY: '0', // top + bottom
zIndex: 10,
}} />Visual
<Box $css={{
opacity: 0.8,
overflow: 'hidden',
overflowX: 'auto',
overflowY: 'scroll',
cursor: 'pointer',
pointerEvents: 'none',
userSelect: 'none',
visibility: 'hidden',
objectFit: 'cover',
objectPosition: 'center',
aspectRatio: '16/9',
}} />Transform & Transition
<Box $css={{
transform: 'translateX(-50%)',
transition: 'all 0.2s ease',
animation: 'fadeIn 0.3s ease',
scale: '1.05',
rotate: '45deg',
translate: '10px 20px',
}} />색상 속성
색상 관련 속성은 인터랙티브 조건(hover/active/focus/disabled 등)을 지원합니다.
기본 색상 속성
<HStack $css={{ gap: '$spacing-300' }}> <Box $css={{ padding: '$spacing-400', bgColor: '$background-1', color: '$text-1', borderRadius: '$radius-200', border: '1px solid', borderColor: '$border-default', }}>background-1</Box> <Box $css={{ padding: '$spacing-400', bgColor: '$background-2', color: '$text-2', borderRadius: '$radius-200', }}>background-2</Box> <Box $css={{ padding: '$spacing-400', bgColor: '$primary-60', color: 'white', borderRadius: '$radius-200', }}>primary-60</Box> </HStack>
인터랙티브 조건
색상 속성에 객체를 전달하면 상태별 스타일을 지정할 수 있습니다. 아래 박스에 마우스를 올려보세요.
<Box $css={{ padding: '$spacing-400', borderRadius: '$radius-200', cursor: 'pointer', transition: 'all 0.2s ease', bgColor: { default: '$background-1', hover: '$primary-10', active: '$primary-20', }, color: { default: '$text-1', hover: '$primary-60', }, borderColor: { default: '$border-default', hover: '$primary-60', }, border: '1px solid', elevation: { default: '$elevation-2', hover: '$elevation-8', }, }}> Hover & Click me </Box>
사용 가능한 조건
| 조건 | CSS 선택자 | 설명 |
|---|---|---|
default | — | 기본 상태 |
hover | &:hover | 마우스 호버 |
active | &:active | 클릭 중 |
focus | &:focus-visible | 키보드 포커스 |
disabled | &:disabled | 비활성 상태 |
readOnly | &:read-only | 읽기 전용 |
focusWithin | &:focus-within | 자식 요소 포커스 |
groupHover | [data-group]:hover & | 부모 그룹 호버 |
사용 가능한 토큰 색상
토큰 색상은 이름으로 직접 참조합니다:
글로벌 색상: primary-10primary-100, gray-5gray-90, red-10red-100, blue-10blue-100, green-10green-100, orange-10orange-100, yellow-10yellow-100, purple-10purple-100 등
시맨틱 색상: background-1background-4, border-default, border-1border-4, text-1text-6, support-error-1support-error-4, support-success-1~support-success-4 등
특수 값: transparent, currentColor, inherit
className / style 콜백
$css 외에도 상태 기반 className과 style을 사용할 수 있습니다.
<Button.Root
$css={{ padding: '$spacing-400' }}
className={(state) => state.disabled ? 'opacity-50' : ''}
style={(state) => ({
transform: state.loading ? 'scale(0.98)' : undefined,
})}
>
<Button.Text>Submit</Button.Text>
</Button.Root>다른 스타일링과 함께 사용
$css prop은 기존 className, style과 함께 사용할 수 있습니다. 병합 우선순위는 다음과 같습니다:
$css의 토큰 스타일 (가장 낮음)$css의 className- 내부 컴포넌트 props
- 소비자의 className / style (가장 높음)
<Box
$css={{ padding: '$spacing-400', bgColor: '$background-1' }}
className="my-custom-class"
style={{ border: '2px solid red' }}
>
Content
</Box>