Skip to Content
FoundationsFoundationShadows (그림자)

Shadows (그림자)

Foundation의 그림자 시스템은 4단계 Box Shadow를 제공하여 UI 요소에 깊이감과 계층 구조를 표현합니다.

그림자 철학

Foundation의 그림자는 다음 원칙을 따릅니다:

  • Elevation: 그림자로 요소의 높이(elevation) 표현
  • Subtle to Strong: sm부터 xl까지 점진적인 깊이감
  • Consistency: 모든 컴포넌트가 동일한 그림자 토큰 사용
  • Performance: 하드웨어 가속을 고려한 최적화

Shadow Scale

Foundation은 4단계 그림자를 제공합니다.

실제 토큰 값 (core.css)

@theme { /* Shadows */ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1); --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1); --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1); }

사용 가이드

토큰Elevation사용 사례
sm1pxInput, Checkbox, Tag
md4-6pxCard, Dropdown (기본)
lg10-15pxModal, Popover
xl20-25pxModal Backdrop, Toast

사용 방법

CSS Variables로 사용

.card { box-shadow: var(--shadow-md); } .modal { box-shadow: var(--shadow-xl); }

Tailwind Utility Classes로 사용

<div className="shadow-md">Card with medium shadow</div>

컴포넌트별 그림자 가이드

Card

// Default Card <div className="p-md bg-white border shadow-md rounded-lg"> Card with medium shadow </div> // Elevated Card (Hover) <div className="p-md bg-white shadow-md hover:shadow-lg transition-shadow rounded-lg"> Card with hover effect </div>

Button

// Primary Button with subtle shadow <button className="px-md py-sm bg-primary text-white shadow-sm rounded"> Primary Button </button> // Elevated Button <button className="px-md py-sm bg-white border shadow-md hover:shadow-lg rounded"> Elevated Button </button>
export default function Modal() { return ( <> {/* Backdrop */} <div className="fixed inset-0 bg-black bg-opacity-50" /> {/* Modal */} <div className="fixed inset-0 flex items-center justify-center p-md"> <div className="bg-white rounded-lg shadow-xl max-w-md w-full p-lg"> <h2 className="text-2xl font-bold mb-md">Modal Title</h2> <p className="text-gray-600">Modal content</p> </div> </div> </> ); }
export default function Dropdown() { return ( <div className="relative"> <button className="px-md py-sm bg-white border rounded">Open Menu</button> {/* Dropdown Menu */} <div className="absolute top-full left-0 mt-xs bg-white border rounded-lg shadow-lg py-sm min-w-[200px]"> <a href="#" className="block px-md py-sm hover:bg-gray-50"> Menu Item 1 </a> <a href="#" className="block px-md py-sm hover:bg-gray-50"> Menu Item 2 </a> <a href="#" className="block px-md py-sm hover:bg-gray-50"> Menu Item 3 </a> </div> </div> ); }

Hover & Focus States

Card Hover Effect

<div className="p-md bg-white shadow-md hover:shadow-xl transition-shadow duration-200 rounded-lg cursor-pointer"> Hover me for elevated shadow </div>

Button Focus State

<button className="px-md py-sm bg-primary text-white rounded shadow-sm focus:shadow-md focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"> Focus me </button>

실전 예제

Product Card

export default function ProductCard() { return ( <div className="bg-white rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300 overflow-hidden"> <img src="/product.jpg" alt="Product" className="w-full h-48 object-cover" /> <div className="p-md"> <h3 className="text-xl font-semibold mb-sm">Product Name</h3> <p className="text-gray-600 mb-md">Product description</p> <button className="w-full px-md py-sm bg-primary text-white rounded shadow-sm"> Add to Cart </button> </div> </div> ); }

Toast Notification

export default function Toast() { return ( <div className="fixed bottom-md right-md bg-white rounded-lg shadow-xl p-md max-w-sm"> <div className="flex items-start gap-md"> <div className="flex-1"> <h4 className="font-semibold text-gray-900">Success</h4> <p className="text-sm text-gray-600 mt-xs"> Operation completed successfully </p> </div> <button className="text-gray-400 hover:text-gray-600">×</button> </div> </div> ); }

접근성 고려사항

그림자와 대비

그림자만으로는 접근성을 보장할 수 없습니다. Border나 Background Color를 함께 사용하세요.

// ❌ 그림자만 사용 <div className="shadow-md">Content</div> // ✅ Border와 함께 사용 <div className="shadow-md border border-gray-200">Content</div>

Reduced Motion

애니메이션 그림자 효과는 prefers-reduced-motion을 고려하세요.

@media (prefers-reduced-motion: reduce) { * { transition-duration: 0ms !important; } }

다음 단계

Last updated on