CSS 심화 — Svelte 스타일 시스템의 모든 것
CSS Modules, styled-components, Tailwind... Svelte에서는 이 중 어떤 것도 없어도 충분히 강력한 스타일링이 가능합니다.
개념 정의
Svelte의 스타일 시스템은 컴포넌트 스코프 CSS를 기본 제공 합니다. 추가 라이브러리 없이 스코프 격리, 동적 스타일, CSS 변수 기반 테마까지 처리할 수 있습니다.
스코프 CSS의 동작 원리
<p>이 텍스트만 빨간색</p>
<style>
/* 컴파일러가 .svelte-xyz123 같은 고유 클래스를 자동 추가 */
/* 실제 출력: p.svelte-xyz123 { color: red; } */
p { color: red; }
</style>
:global — 스코프 탈출
<style>
/* 전체 앱에 적용 */
:global(body) {
margin: 0;
font-family: system-ui;
}
/* 이 컴포넌트 안의 .content 하위 전역 스타일 */
.content :global(h1) {
font-size: 2rem;
}
/* :global 블록 — 여러 규칙을 한번에 */
:global {
.markdown h2 { margin-top: 2rem; }
.markdown p { line-height: 1.8; }
.markdown code { background: #f0f0f0; padding: 2px 4px; }
}
</style>
<div class="content">
{@html markdownContent}
</div>
고급 선택자
<style>
/* 중첩 (Svelte가 지원) */
.card {
padding: 1rem;
h2 {
font-size: 1.5rem;
}
&:hover {
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
&.active {
border-color: #ff3e00;
}
}
/* 미사용 CSS 경고 */
/* Svelte는 사용되지 않는 CSS 선택자를 경고합니다 */
/* 이는 CSS 정리에 매우 유용합니다 */
</style>
CSS 변수를 활용한 테마
<script>
let themes = {
light: { bg: '#fff', text: '#333', primary: '#ff3e00', card: '#f5f5f5' },
dark: { bg: '#1a1a2e', text: '#eee', primary: '#e94560', card: '#16213e' },
ocean: { bg: '#0a1628', text: '#e0e0e0', primary: '#00d4ff', card: '#1a2744' },
};
let currentTheme = $state('light');
let theme = $derived(themes[currentTheme]);
</script>
<div
class="app"
style:--bg={theme.bg}
style:--text={theme.text}
style:--primary={theme.primary}
style:--card={theme.card}
>
<select bind:value={currentTheme}>
<option value="light">라이트</option>
<option value="dark">다크</option>
<option value="ocean">오션</option>
</select>
<div class="card">
<h2>테마 카드</h2>
<p>CSS 변수로 테마 전환</p>
<button>액션 버튼</button>
</div>
</div>
<style>
.app {
background: var(--bg);
color: var(--text);
min-height: 100vh;
padding: 2rem;
transition: all 0.3s ease;
}
.card {
background: var(--card);
padding: 1.5rem;
border-radius: 8px;
}
button {
background: var(--primary);
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: 4px;
}
</style>
컴포넌트에 CSS 변수 전달
<!-- Box.svelte -->
<div class="box"><slot /></div>
<style>
.box {
background: var(--box-bg, #f0f0f0);
padding: var(--box-padding, 1rem);
border-radius: var(--box-radius, 8px);
border: 1px solid var(--box-border, transparent);
}
</style>
<!-- 사용 측에서 CSS 변수로 스타일 커스터마이징 -->
<Box --box-bg="#e8f5e9" --box-border="#4caf50" --box-padding="2rem">
<p>커스텀 스타일 박스</p>
</Box>
@media와 반응형
<style>
.grid {
display: grid;
gap: 1rem;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
.grid { grid-template-columns: repeat(3, 1fr); }
}
/* 다크 모드 선호 감지 */
@media (prefers-color-scheme: dark) {
.card { background: #2a2a2a; color: #eee; }
}
/* 모션 감소 선호 */
@media (prefers-reduced-motion: reduce) {
* { animation: none !important; transition: none !important; }
}
</style>
Tailwind CSS 통합
npx sv add tailwindcss
<!-- Tailwind도 함께 사용 가능 -->
<div class="flex items-center gap-4 p-4 bg-white rounded-lg shadow-md">
<img class="w-12 h-12 rounded-full" src={avatar} alt={name} />
<div>
<h3 class="font-bold text-gray-900">{name}</h3>
<p class="text-sm text-gray-500">{email}</p>
</div>
</div>
<style>
/* Svelte 스코프 CSS와 Tailwind를 혼용할 수 있습니다 */
/* 복잡한 애니메이션은 Svelte CSS에서, 유틸리티는 Tailwind에서 */
</style>
면접 포인트
- "Svelte 스코프 CSS의 원리는?": 컴파일러가 컴포넌트별 고유 클래스(해시)를 생성하여 모든 셀렉터와 요소에 추가합니다. 런타임 비용 없이 CSS 격리를 달성합니다.
- "미사용 CSS 감지는 어떻게 동작하나요?": 컴파일러가 마크업을 분석하여 어떤 CSS 선택자가 실제로 매칭되는 요소가 없는지 확인하고 경고합니다. 빌드 시 dead CSS를 제거하는 데 도움됩니다.
정리
Svelte의 CSS 시스템은 "기본이 충분히 강력한" 접근입니다. 스코프 격리, 동적 스타일, CSS 변수 기반 테마, 미사용 CSS 경고 — 이 모든 것이 추가 의존성 없이 제공됩니다. 필요하다면 Tailwind 같은 도구도 자연스럽게 통합할 수 있습니다.
댓글 로딩 중...