Skeleton

A placeholder component showing loading state while content loads

Controls

Toggle loading state and animation type for all demos below.

Loading:
Animation:

Basic Skeletons

Simple skeleton shapes and sizes.

Sizes

xs
sm
md
lg
xl

Shapes

default
circle
square
pill

Code Svelte
1
2<script lang="ts">
3	import { SkeletonPrimitives } from "@kareyes/aether";
4
5	const { Skeleton } = SkeletonPrimitives;
6
7	let isLoading = $state(true);
8	let animation = "pulse";
9</script>
10
11<div class="grid gap-6 md:grid-cols-2">
12	<div class="space-y-4 rounded-lg border p-4">
13		<h3 class="font-semibold">Sizes</h3>
14		<div class="space-y-3">
15			<div class="flex items-center gap-4">
16				<span class="w-12 text-xs text-muted-foreground">xs</span>
17				<Skeleton {animation} size="xs" width="full" visible={isLoading} />
18			</div>
19			<div class="flex items-center gap-4">
20				<span class="w-12 text-xs text-muted-foreground">sm</span>
21				<Skeleton {animation} size="sm" width="full" visible={isLoading} />
22			</div>
23			<div class="flex items-center gap-4">
24				<span class="w-12 text-xs text-muted-foreground">md</span>
25				<Skeleton {animation} size="md" width="full" visible={isLoading} />
26			</div>
27			<div class="flex items-center gap-4">
28				<span class="w-12 text-xs text-muted-foreground">lg</span>
29				<Skeleton {animation} size="lg" width="full" visible={isLoading} />
30			</div>
31			<div class="flex items-center gap-4">
32				<span class="w-12 text-xs text-muted-foreground">xl</span>
33				<Skeleton {animation} size="xl" width="full" visible={isLoading} />
34			</div>
35		</div>
36	</div>
37
38	<div class="space-y-4 rounded-lg border p-4">
39		<h3 class="font-semibold">Shapes</h3>
40		<div class="flex flex-wrap gap-4">
41			<div class="text-center">
42				<Skeleton {animation} shape="default" class="h-16 w-24" visible={isLoading} />
43				<span class="mt-1 block text-xs text-muted-foreground">default</span>
44			</div>
45			<div class="text-center">
46				<Skeleton {animation} shape="circle" class="h-16 w-16" visible={isLoading} />
47				<span class="mt-1 block text-xs text-muted-foreground">circle</span>
48			</div>
49			<div class="text-center">
50				<Skeleton {animation} shape="square" class="h-16 w-24" visible={isLoading} />
51				<span class="mt-1 block text-xs text-muted-foreground">square</span>
52			</div>
53			<div class="text-center">
54				<Skeleton {animation} shape="pill" class="h-8 w-24" visible={isLoading} />
55				<span class="mt-1 block text-xs text-muted-foreground">pill</span>
56			</div>
57		</div>
58	</div>
59</div>

Variants

Different visual styles for skeletons.

default
primary
secondary
accent

Code Svelte
1
2<script lang="ts">
3	import { SkeletonPrimitives } from "@kareyes/aether";
4
5	const { Skeleton } = SkeletonPrimitives;
6
7	let isLoading = $state(true);
8	let animation = "pulse";
9</script>
10
11<div class="grid gap-4 md:grid-cols-4">
12	<div class="space-y-2 rounded-lg border p-4">
13		<Skeleton {animation} variant="default" size="lg" width="full" visible={isLoading} />
14		<span class="text-xs text-muted-foreground">default</span>
15	</div>
16	<div class="space-y-2 rounded-lg border p-4">
17		<Skeleton {animation} variant="primary" size="lg" width="full" visible={isLoading} />
18		<span class="text-xs text-muted-foreground">primary</span>
19	</div>
20	<div class="space-y-2 rounded-lg border p-4">
21		<Skeleton {animation} variant="secondary" size="lg" width="full" visible={isLoading} />
22		<span class="text-xs text-muted-foreground">secondary</span>
23	</div>
24	<div class="space-y-2 rounded-lg border p-4">
25		<Skeleton {animation} variant="accent" size="lg" width="full" visible={isLoading} />
26		<span class="text-xs text-muted-foreground">accent</span>
27	</div>
28</div>

Width Shortcuts

Convenient width presets.

full
half
third
quarter
200px

Code Svelte
1
2<script lang="ts">
3	import { SkeletonPrimitives } from "@kareyes/aether";
4
5	const { Skeleton } = SkeletonPrimitives;
6
7	let isLoading = $state(true);
8	let animation = "pulse";
9</script>
10
11<div class="space-y-3 rounded-lg border p-4">
12	<div class="flex items-center gap-4">
13		<span class="w-16 text-xs text-muted-foreground">full</span>
14		<Skeleton {animation} size="md" width="full" visible={isLoading} />
15	</div>
16	<div class="flex items-center gap-4">
17		<span class="w-16 text-xs text-muted-foreground">half</span>
18		<Skeleton {animation} size="md" width="half" visible={isLoading} />
19	</div>
20	<div class="flex items-center gap-4">
21		<span class="w-16 text-xs text-muted-foreground">third</span>
22		<Skeleton {animation} size="md" width="third" visible={isLoading} />
23	</div>
24	<div class="flex items-center gap-4">
25		<span class="w-16 text-xs text-muted-foreground">quarter</span>
26		<Skeleton {animation} size="md" width="quarter" visible={isLoading} />
27	</div>
28	<div class="flex items-center gap-4">
29		<span class="w-16 text-xs text-muted-foreground">200px</span>
30		<Skeleton {animation} size="md" width="200px" visible={isLoading} />
31	</div>
32</div>

Multiple Skeletons

Render multiple skeletons with stagger animation.

Count = 4

Varied Widths


Code Svelte
1
2<script lang="ts">
3	import { SkeletonPrimitives } from "@kareyes/aether";
4
5	const { Skeleton } = SkeletonPrimitives;
6
7	let isLoading = $state(true);
8	let animation = "pulse";
9</script>
10
11<div class="grid gap-6 md:grid-cols-2">
12	<div class="space-y-4 rounded-lg border p-4">
13		<h3 class="font-semibold">Count = 4</h3>
14		<Skeleton
15			{animation}
16			count={4}
17			size="sm"
18			width="full"
19			delay={100}
20			visible={isLoading}
21		/>
22	</div>
23
24	<div class="space-y-4 rounded-lg border p-4">
25		<h3 class="font-semibold">Varied Widths</h3>
26		<div class="space-y-2">
27			<Skeleton {animation} size="sm" width="90%" delay={0} visible={isLoading} />
28			<Skeleton {animation} size="sm" width="full" delay={50} visible={isLoading} />
29			<Skeleton {animation} size="sm" width="75%" delay={100} visible={isLoading} />
30			<Skeleton {animation} size="sm" width="60%" delay={150} visible={isLoading} />
31		</div>
32	</div>
33</div>

Skeleton Text

Preset for text paragraphs with natural line widths.

Default (3 lines)

5 Lines (Uniform)


Code Svelte
1
2<script lang="ts">
3	import { SkeletonPrimitives } from "@kareyes/aether";
4
5	const { SkeletonText } = SkeletonPrimitives;
6
7	let isLoading = $state(true);
8	let animation = "pulse";
9</script>
10
11<div class="grid gap-6 md:grid-cols-2">
12	<div class="space-y-4 rounded-lg border p-4">
13		<h3 class="font-semibold">Default (3 lines)</h3>
14		{#if isLoading}
15			<SkeletonText {animation} />
16		{:else}
17			<p class="text-sm">
18				This is the actual content that would be displayed after loading.
19				It contains multiple lines of text to demonstrate the skeleton placeholder.
20			</p>
21		{/if}
22	</div>
23
24	<div class="space-y-4 rounded-lg border p-4">
25		<h3 class="font-semibold">5 Lines (Uniform)</h3>
26		{#if isLoading}
27			<SkeletonText {animation} lines={5} varied={false} />
28		{:else}
29			<p class="text-sm">Content loaded successfully!</p>
30		{/if}
31	</div>
32</div>

Skeleton Avatar

Avatar placeholders with optional text.

Avatar Only

With Text

Extra Small

Extra Large


Code Svelte
1
2<script lang="ts">
3	import { SkeletonPrimitives } from "@kareyes/aether";
4
5	const { SkeletonAvatar } = SkeletonPrimitives;
6
7	let isLoading = $state(true);
8	let animation = "pulse";
9</script>
10
11<div class="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
12	<div class="space-y-4 rounded-lg border p-4">
13		<h3 class="text-sm font-semibold">Avatar Only</h3>
14		{#if isLoading}
15			<SkeletonAvatar {animation} size="lg" />
16		{:else}
17			<div class="flex h-12 w-12 items-center justify-center rounded-full bg-primary text-primary-foreground">
18				JD
19			</div>
20		{/if}
21	</div>
22
23	<div class="space-y-4 rounded-lg border p-4">
24		<h3 class="text-sm font-semibold">With Text</h3>
25		{#if isLoading}
26			<SkeletonAvatar {animation} withText />
27		{:else}
28			<div class="flex items-center gap-3">
29				<div class="flex h-10 w-10 items-center justify-center rounded-full bg-primary text-sm text-primary-foreground">
30					JD
31				</div>
32				<div>
33					<p class="font-medium">John Doe</p>
34					<p class="text-sm text-muted-foreground">john@example.com</p>
35				</div>
36			</div>
37		{/if}
38	</div>
39
40	<div class="space-y-4 rounded-lg border p-4">
41		<h3 class="text-sm font-semibold">Extra Small</h3>
42		<SkeletonAvatar {animation} size="xs" withText visible={isLoading} />
43	</div>
44
45	<div class="space-y-4 rounded-lg border p-4">
46		<h3 class="text-sm font-semibold">Extra Large</h3>
47		<SkeletonAvatar {animation} size="xl" withText textLines={3} visible={isLoading} />
48	</div>
49</div>

Skeleton Card

Card layout placeholders with configurable sections.

Full Card

No Image

Minimal


Code Svelte
1
2<script lang="ts">
3	import { SkeletonPrimitives } from "@kareyes/aether";
4
5	const { SkeletonCard } = SkeletonPrimitives;
6
7	let isLoading = $state(true);
8	let animation = "pulse";
9</script>
10
11<div class="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
12	<div>
13		<h3 class="mb-2 text-sm font-semibold">Full Card</h3>
14		{#if isLoading}
15			<SkeletonCard {animation} />
16		{:else}
17			<div class="rounded-lg border bg-card p-4 shadow-sm">
18				<div class="mb-4 flex items-center gap-3">
19					<div class="h-10 w-10 rounded-full bg-primary"></div>
20					<div>
21						<p class="font-medium">Card Title</p>
22						<p class="text-sm text-muted-foreground">Subtitle</p>
23					</div>
24				</div>
25				<p class="text-sm">Card content goes here.</p>
26			</div>
27		{/if}
28	</div>
29
30	<div>
31		<h3 class="mb-2 text-sm font-semibold">No Image</h3>
32		<SkeletonCard
33			{animation}
34			withImage={false}
35			visible={isLoading}
36		/>
37	</div>
38
39	<div>
40		<h3 class="mb-2 text-sm font-semibold">Minimal</h3>
41		<SkeletonCard
42			{animation}
43			withImage={false}
44			withAvatar={false}
45			withFooter={false}
46			bodyLines={4}
47			visible={isLoading}
48		/>
49	</div>
50</div>

Skeleton Table

Table placeholder with configurable rows and columns.

Default Table (5 rows, 4 columns)

Compact Table (3 rows, 2 columns)


Code Svelte
1
2<script lang="ts">
3	import { SkeletonPrimitives } from "@kareyes/aether";
4
5	const { SkeletonTable } = SkeletonPrimitives;
6
7	let isLoading = $state(true);
8	let animation = "pulse";
9</script>
10
11<div class="space-y-6">
12	<div>
13		<h3 class="mb-2 font-semibold">Default Table (5 rows, 4 columns)</h3>
14		{#if isLoading}
15			<SkeletonTable {animation} />
16		{:else}
17			<div class="w-full overflow-hidden rounded-lg border">
18				<table class="w-full">
19					<thead class="bg-muted/50">
20						<tr>
21							<th class="px-4 py-3 text-left text-sm font-medium">Name</th>
22							<th class="px-4 py-3 text-left text-sm font-medium">Email</th>
23							<th class="px-4 py-3 text-left text-sm font-medium">Role</th>
24							<th class="px-4 py-3 text-left text-sm font-medium">Status</th>
25						</tr>
26					</thead>
27					<tbody class="divide-y">
28						{#each Array(5) as _}
29							<tr>
30								<td class="px-4 py-3 text-sm">John Doe</td>
31								<td class="px-4 py-3 text-sm">john@example.com</td>
32								<td class="px-4 py-3 text-sm">Admin</td>
33								<td class="px-4 py-3 text-sm">Active</td>
34							</tr>
35						{/each}
36					</tbody>
37				</table>
38			</div>
39		{/if}
40	</div>
41
42	<div>
43		<h3 class="mb-2 font-semibold">Compact Table (3 rows, 2 columns)</h3>
44		<SkeletonTable
45			{animation}
46			rows={3}
47			columns={2}
48			visible={isLoading}
49		/>
50	</div>
51</div>

Real-world Examples

Common loading patterns in applications.

Social Post

Product List


Code Svelte
1
2<script lang="ts">
3	import { SkeletonPrimitives } from "@kareyes/aether";
4
5	const { Skeleton, SkeletonText, SkeletonAvatar } = SkeletonPrimitives;
6
7	let isLoading = $state(true);
8	let animation = "pulse";
9</script>
10
11<div class="grid gap-6 md:grid-cols-2">
12	<!-- Social Post -->
13	<div class="space-y-4 rounded-lg border p-4">
14		<h3 class="font-semibold">Social Post</h3>
15		{#if isLoading}
16			<div class="space-y-4">
17				<SkeletonAvatar {animation} withText size="md" />
18				<SkeletonText {animation} lines={2} />
19				<Skeleton {animation} class="aspect-video w-full" />
20				<div class="flex gap-4">
21					<Skeleton {animation} shape="pill" size="sm" width="60px" />
22					<Skeleton {animation} shape="pill" size="sm" width="60px" />
23					<Skeleton {animation} shape="pill" size="sm" width="60px" />
24				</div>
25			</div>
26		{:else}
27			<div class="space-y-4">
28				<div class="flex items-center gap-3">
29					<div class="h-10 w-10 rounded-full bg-primary"></div>
30					<div>
31						<p class="font-medium">Jane Smith</p>
32						<p class="text-xs text-muted-foreground">2 hours ago</p>
33					</div>
34				</div>
35				<p class="text-sm">Just finished building this awesome skeleton component!</p>
36				<div class="aspect-video w-full rounded-lg bg-muted"></div>
37				<div class="flex gap-4 text-sm text-muted-foreground">
38					<span>42 likes</span>
39					<span>12 comments</span>
40					<span>Share</span>
41				</div>
42			</div>
43		{/if}
44	</div>
45
46	<!-- Product List -->
47	<div class="space-y-4 rounded-lg border p-4">
48		<h3 class="font-semibold">Product List</h3>
49		{#if isLoading}
50			<div class="space-y-3">
51				{#each Array(3) as _, i}
52					<div class="flex gap-4">
53						<Skeleton {animation} shape="default" class="h-16 w-16 shrink-0" />
54						<div class="flex-1 space-y-2">
55							<Skeleton {animation} size="sm" width="70%" delay={i * 50} />
56							<Skeleton {animation} size="xs" width="50%" delay={i * 50 + 25} />
57							<Skeleton {animation} size="sm" width="30%" delay={i * 50 + 50} />
58						</div>
59					</div>
60				{/each}
61			</div>
62		{:else}
63			<div class="space-y-3">
64				{#each ["Widget Pro", "Gadget Plus", "Device Ultra"] as product}
65					<div class="flex gap-4">
66						<div class="h-16 w-16 shrink-0 rounded-lg bg-muted"></div>
67						<div class="flex-1">
68							<p class="font-medium">{product}</p>
69							<p class="text-xs text-muted-foreground">In stock</p>
70							<p class="text-sm font-semibold">$99.00</p>
71						</div>
72					</div>
73				{/each}
74			</div>
75		{/if}
76	</div>
77</div>