Appearance
Skeleton
- 데이터 로딩 중에 UI 레이아웃을 미리 표시하는 플레이스홀더 컴포넌트
- 실제 콘텐츠가 로드되기 전에 화면 구조를 유지하여 사용자 경험 향상
- 펄스 애니메이션으로 로딩 상태를 시각적으로 표시
- 라인별 스켈레톤 효과로 텍스트가 여러 줄일 때 각 줄마다 스켈레톤 표시
Props
Prop | Type | Default | Description |
---|---|---|---|
loading | boolean | true | 스켈레톤 로딩 상태 활성화 여부 |
radius | string|number | '8px' | 스켈레톤 테두리 반경 |
width | string|number | - | 인라인 모드에서 너비 (자식 있는 경우 무시) |
minWidth | string|number | - | 최소 너비 |
maxWidth | string|number | - | 최대 너비 |
height | string|number | - | 높이 |
minHeight | string|number | - | 최소 높이 (기본값: '1em', height가 지정된 경우 무시) |
maxHeight | string|number | - | 최대 높이 |
Basic
vue
<script setup lang="ts">
import { Skeleton } from '@jennifersoft/vue-components-v2';
</script>
<template>
<Skeleton width="120px" height="24px" />
</template>
Toggle Loading
loading
prop으로 로딩 상태를 제어할 수 있습니다
로딩 중지 시 이 내용이 표시됩니다.
vue
<script setup lang="ts">
import { ref } from 'vue';
import { Skeleton } from '@jennifersoft/vue-components-v2';
const loading = ref(true);
const toggleLoading = () => {
loading.value = !loading.value;
};
</script>
<template>
<div class="space-y-4">
<Btn
:type="loading ? 'primary-filled' : 'outlined'"
:text="loading ? '로딩 중지' : '로딩 시작'"
@click="toggleLoading"
/>
<div>
<Skeleton :loading="loading" width="120px" height="24px" />
</div>
</div>
</template>
Inline Mode (No Children)
- 자식 요소 없이 사용하면 인라인 모드로 작동합니다
width
,height
,radius
등의 속성으로 스타일을 직접 제어할 수 있습니다
vue
<template>
<div class="space-y-4">
<div class="flex items-center space-x-4">
<Skeleton width="60px" height="60px" radius="50%" />
<div class="flex gap-2">
<Skeleton width="120px" height="20px" />
<Skeleton width="80px" height="16px" />
</div>
</div>
</div>
</template>
With Children
- 자식 요소가 있을 경우, 로딩 상태에서는 자식 요소를 숨기고 스켈레톤 효과를 표시합니다
- 로딩이 완료되면 자동으로 실제 콘텐츠가 표시됩니다
- 자식 요소의 DOM 구조와 레이아웃을 유지합니다
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque felis tellus, efficitur id convallis a, viverra eget libero. Nam magna erat, fringilla sed commodo sed, aliquet nec magna.
vue
<script setup lang="ts">
import { ref } from 'vue';
import { Skeleton } from '@jennifersoft/vue-components-v2';
const loading = ref(true);
const toggleLoading = () => {
loading.value = !loading.value;
};
</script>
<template>
<div class="space-y-4">
<button @click="toggleLoading" class="px-3 py-1 border rounded">
{{ loading ? '로딩 중지' : '로딩 시작' }}
</button>
<div>
<Skeleton :loading="loading">
<div class="p-4 border rounded bg-gray-50">
<h3 class="text-lg font-bold">실제 콘텐츠</h3>
<p>로딩이 완료되면 이 내용이 표시됩니다.</p>
</div>
</Skeleton>
</div>
</div>
</template>
Card Example
- 카드 레이아웃에 적용한 예시입니다
카드 제목
카드 설명 텍스트입니다. 로딩이 완료되면 표시됩니다.
vue
<script setup lang="ts">
import { ref } from 'vue';
import { Skeleton } from '@jennifersoft/vue-components-v2';
const loading = ref(true);
const toggleLoading = () => {
loading.value = !loading.value;
};
</script>
<template>
<div class="space-y-4">
<button @click="toggleLoading" class="px-3 py-1 border rounded">
{{ loading ? '로딩 중지' : '로딩 시작' }}
</button>
<div class="flex space-x-4">
<div class="w-64 p-4 border rounded">
<Skeleton :loading="loading">
<div class="aspect-video bg-blue-100 mb-4 rounded"></div>
</Skeleton>
<div class="space-y-2 text-sm">
<Skeleton :loading="loading">
<h3 class="text-lg font-bold">카드 제목</h3>
</Skeleton>
<Skeleton :loading="loading">
<p class="text-sm">
카드 설명 텍스트입니다. 로딩이 완료되면 표시됩니다.
</p>
</Skeleton>
</div>
</div>
</div>
</div>
</template>
동작 방식
Skeleton 컴포넌트는 두 가지 주요 모드로 동작합니다:
인라인 텍스트 모드
- 텍스트 콘텐츠를 감쌀 때 적용됩니다 (예:
<p>
,<span>
등의 텍스트) - 라인별 스켈레톤 효과: 텍스트가 여러 줄일 경우 각 줄마다 개별 스켈레톤이 표시됩니다
line-height: 0
,box-decoration-break: clone
속성을 통해 라인별 효과 구현- 원래 텍스트의 줄바꿈, 폰트 크기, 간격이 그대로 유지됩니다
엘리먼트 래핑 모드
- 요소나 컴포넌트를 감쌀 때 적용됩니다 (예:
<div>
,<img>
등) - 원본 DOM 구조를 유지하면서 스켈레톤 효과만 적용합니다
- 로딩 중에는 자식 요소의 가시성만 숨기고(visibility: hidden) 레이아웃은 유지
inert
속성과aria-busy
속성으로 접근성 보장 및 인터랙션 차단
둘 다 다음과 같은 공통 기능을 제공합니다:
- 로딩 상태에서 원본 콘텐츠와 동일한 크기와 모양 유지
- 펄스 애니메이션으로 로딩 중임을 시각적으로 표시
- 사용자 상호작용 차단 (pointer-events: none)
Custom Radius
radius
prop으로 테두리 반경을 조절할 수 있습니다
vue
<template>
<div class="flex space-x-4">
<Skeleton width="80px" height="80px" radius="4px" />
<Skeleton width="80px" height="80px" radius="8px" />
<Skeleton width="80px" height="80px" radius="16px" />
<Skeleton width="80px" height="80px" radius="40px" />
</div>
</template>