Overview
Avatar: Avatar placeholder, by default uses Avatar medium sizing:width: 48px,height: 48px. Supports thesizeandshapeproperties; see the API reference for their values.Image: Image placeholder, default size:width: 100%,height: 100%.Title: Title placeholder, default size:width: 100%,height: 24px.Paragraph: Content part placeholder, default size:width: 100%,height: 16px,margin-bottom: 10px.Button: Button placeholder, default size:width: 115px,height: 32px.
Note: Default styles can be overridden through
classorstyle(a string). In the Svelte package the placeholder blocks are both static members such asSkeleton.Avatarand the same components as named exports:SkeletonAvatar,SkeletonImage,SkeletonTitle,SkeletonParagraphandSkeletonButton.
Demos
How to import
<script lang="ts">
import { Skeleton, SkeletonAvatar, SkeletonButton, SkeletonImage, SkeletonParagraph, SkeletonTitle } from '@fibrae/semi-ui-svelte';
</script>
<Skeleton loading>
{#snippet placeholder()}
<SkeletonAvatar />
{/snippet}
<p>Content</p>
</Skeleton>
The placeholder snippet is shown while loading, and children is shown once loading ends.
Basic Usage
Code
<script lang="ts">
import { Avatar, Button, Skeleton, SkeletonAvatar, SkeletonButton, SkeletonImage, SkeletonParagraph, SkeletonTitle, Switch } from '@fibrae/semi-ui-svelte';
let loading = $state(true);
</script>
<span style="display: flex; align-items: center">
<Switch aria-labelledby="skeleton-basic-toggle" checked={!loading} onChange={() => (loading = !loading)} />
<span id="skeleton-basic-toggle" style="margin-inline-start: 10px">显示加载内容</span>
</span>
<br />
<Skeleton {loading}>
{#snippet placeholder()}
<SkeletonAvatar />
{/snippet}
<Avatar color="blue" style="margin-bottom: 10px">U</Avatar>
</Skeleton>
<br />
<Skeleton {loading} style="width: 200px; height: 150px">
{#snippet placeholder()}
<SkeletonImage />
{/snippet}
<img alt="avatar" height="150" src="/assets/placeholder/avatar-a.svg" />
</Skeleton>
<br />
<Skeleton {loading} style="width: 80px">
{#snippet placeholder()}
<SkeletonTitle style="margin-bottom: 10px" />
{/snippet}
<h4 style="margin-bottom: 0">Semi UI</h4>
</Skeleton>
<Skeleton {loading} style="width: 240px">
{#snippet placeholder()}
<SkeletonParagraph rows={2} />
{/snippet}
<p style="width: 240px">精心打磨每一个组件的用户体验,从用户的角度考虑每个组件的使用场景。</p>
</Skeleton>
<br />
<Skeleton {loading}>
{#snippet placeholder()}
<SkeletonButton />
{/snippet}
<Button>Button</Button>
</Skeleton>Combinations
Image and caption.
Code
<script lang="ts">
import { Skeleton, SkeletonImage, SkeletonTitle } from '@fibrae/semi-ui-svelte';
</script>
<Skeleton loading>
{#snippet placeholder()}
<div>
<SkeletonImage style="width: 200px; height: 150px" />
<SkeletonTitle style="width: 120px; margin-top: 10px" />
</div>
{/snippet}
<img alt="avatar" height="150" src="/assets/placeholder/avatar-a.svg" />
<h4>Semi UI</h4>
</Skeleton>Statistics.
Code
<script lang="ts">
import { Descriptions, Skeleton, SkeletonParagraph, SkeletonTitle } from '@fibrae/semi-ui-svelte';
const data = [{ key: '实际用户数量', value: '1,480,000' }];
</script>
<Skeleton loading>
{#snippet placeholder()}
<div>
<SkeletonParagraph rows={1} style="width: 80px; margin-bottom: 10px" />
<SkeletonTitle style="width: 120px" />
</div>
{/snippet}
<Descriptions {data} row />
</Skeleton>Avatar and title.
Code
<script lang="ts">
import { Avatar, Skeleton, SkeletonAvatar, SkeletonTitle } from '@fibrae/semi-ui-svelte';
</script>
<Skeleton loading>
{#snippet placeholder()}
<div style="display: flex; align-items: center">
<SkeletonAvatar style="margin-inline-end: 12px" />
<SkeletonTitle style="width: 120px" />
</div>
{/snippet}
<Avatar color="blue" style="margin-inline-end: 12px">UI</Avatar>
<span>Semi UI</span>
</Skeleton>Centered paragraphs and button.
Code
<script lang="ts">
import { Button, Skeleton, SkeletonButton, SkeletonParagraph } from '@fibrae/semi-ui-svelte';
const style = 'display: flex; flex-direction: column; align-items: center; width: 300px; margin-bottom: 10px';
</script>
<Skeleton loading style="text-align: center">
{#snippet placeholder()}
<div {style}>
<SkeletonParagraph rows={3} {style} />
<SkeletonButton />
</div>
{/snippet}
<div style="text-align: center">
<p>Hi, Bytedance dance dance.</p>
<p>Hi, Bytedance dance dance.</p>
<Button>Button</Button>
</div>
</Skeleton>Avatar, headline and paragraph.
Code
<script lang="ts">
import { Avatar, Skeleton, SkeletonAvatar, SkeletonParagraph, SkeletonTitle } from '@fibrae/semi-ui-svelte';
const style = 'display: flex; align-items: flex-start';
</script>
<Skeleton loading>
{#snippet placeholder()}
<div {style}>
<SkeletonAvatar style="margin-inline-end: 12px" />
<div>
<SkeletonTitle style="width: 120px; margin-bottom: 12px; margin-top: 12px" />
<SkeletonParagraph rows={3} style="width: 240px" />
</div>
</div>
{/snippet}
<div {style}>
<Avatar color="blue" style="margin-inline-end: 12px">UI</Avatar>
<div>
<h3>Semi UI</h3>
<p>Hi, Bytedance dance dance.</p>
<p>Hi, Bytedance dance dance.</p>
<p>Hi, Bytedance dance dance.</p>
</div>
</div>
</Skeleton>Table.
Code
<script lang="ts">
import { Skeleton, SkeletonParagraph, SkeletonTitle, Table, type ColumnProps } from '@fibrae/semi-ui-svelte';
const columns: ColumnProps[] = [
{
title: 'Name',
dataIndex: 'name',
},
{
title: 'Age',
dataIndex: 'age',
},
{
title: 'Address',
dataIndex: 'address',
},
];
const dataSource = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
},
{
key: '4',
name: 'Disabled User',
age: 99,
address: 'Sidney No. 1 Lake Park',
},
];
const placeholderColumns: ColumnProps[] = [1, 2, 3].map((key) => ({ dataIndex: `${key}` }));
const placeholderDataSource = [1, 2, 3, 4].map((key) => ({ key }));
</script>
<Skeleton loading>
{#snippet placeholder()}
<div style="position: relative">
<Table columns={placeholderColumns} dataSource={placeholderDataSource} pagination={false} style="background-color: var(--semi-color-bg-1)">
{#snippet headerCell()}
<SkeletonTitle style="width: 0" />
{/snippet}
{#snippet cell({ column })}
<SkeletonParagraph rows={1} style="width: {50 * Number(column.dataIndex)}px" />
{/snippet}
</Table>
<div style="position: absolute; inset: 0"></div>
</div>
{/snippet}
<div>
<Table {columns} {dataSource} pagination={false} />
</div>
</Skeleton>Animated Loading
Use active property to display animated loading effects.
Code
<script lang="ts">
import { Avatar, Skeleton, SkeletonAvatar, SkeletonParagraph, SkeletonTitle } from '@fibrae/semi-ui-svelte';
const style = 'display: flex; align-items: flex-start';
</script>
<Skeleton active loading>
{#snippet placeholder()}
<div {style}>
<SkeletonAvatar style="margin-inline-end: 12px" />
<div>
<SkeletonTitle style="width: 120px; margin-bottom: 12px; margin-top: 12px" />
<SkeletonParagraph rows={3} style="width: 240px" />
</div>
</div>
{/snippet}
<div {style}>
<Avatar color="blue" style="margin-inline-end: 12px">UI</Avatar>
<div>
<h3>Semi UI</h3>
<p>Hi, Bytedance dance dance.</p>
<p>Hi, Bytedance dance dance.</p>
<p>Hi, Bytedance dance dance.</p>
</div>
</div>
</Skeleton>API reference
Skeleton
Props
| Property | Description | Type | Default |
|---|---|---|---|
| active | Whether to show the animated loading effect. | boolean | - |
| children | Content shown once loading ends. | Snippet | - |
| loading | When true, the placeholder is shown. Otherwise the children are shown. | boolean | true |
| placeholder | Elements shown while loading. | Snippet | - |
class, style (a string) and native attributes and events fall through onto the placeholder root element. When loading is false the component renders only the children and has no root element, so these are dropped together with the placeholder. The root's aria-busy="true" cannot be switched off.
Skeleton.Avatar
In Svelte, Skeleton.Avatar below can also be written as the named export SkeletonAvatar, and so on.
Props
| Property | Description | Type | Default |
|---|---|---|---|
| prefixCls | Class name prefix, semi-skeleton by default. | string | - |
| shape | Shape of the avatar placeholder: circle or square. | 'circle' | 'square' | - |
| size | Size of the avatar placeholder. | Type'extra-extra-small' | 'extra-small' | 'small' | 'medium' | 'large' | 'extra-large' | - |
| type | Replaces the type of the block, which also names its class. Unless it is avatar, size and shape have no effect. | string | "avatar" |
class, style (a string) and native attributes and events fall through onto the placeholder block.
Skeleton.Image
Props
| Property | Description | Type | Default |
|---|---|---|---|
| prefixCls | Class name prefix, semi-skeleton by default. | string | - |
| type | Replaces the type of the block, which also names its class. | string | "image" |
Skeleton.Title
Props
| Property | Description | Type | Default |
|---|---|---|---|
| prefixCls | Class name prefix, semi-skeleton by default. | string | - |
| type | Replaces the type of the block, which also names its class. | string | "title" |
Skeleton.Button
Props
| Property | Description | Type | Default |
|---|---|---|---|
| prefixCls | Class name prefix, semi-skeleton by default. | string | - |
| type | Replaces the type of the block, which also names its class. | string | "button" |
SkeletonImage, SkeletonTitle and SkeletonButton have no size or shape; class, style and native attributes and events fall through onto the placeholder block.
Skeleton.Paragraph
Props
| Property | Description | Type | Default |
|---|---|---|---|
| prefixCls | Class name prefix, semi-skeleton by default. | string | "semi-skeleton" |
| rows | Number of rows in the placeholder paragraph. | number | 4 |
class, style (a string) and native attributes and events fall through onto the root ul element.
Accessibility
- While loading, the outer element of Skeleton carries
aria-busy="true", and the placeholder blocks and paragraph carryaria-hidden="true", so screen readers only know that content is loading. Anaria-hiddenpassed by the caller takes precedence on a placeholder block;aria-busycannot be switched off. - Once loading ends, the children are rendered directly and Skeleton adds no outer element.
Content Guidelines
- Unchanged fixed content directly displays fixed content, and variable content is displayed using skeleton screen
Design Tokens
| Sass variable | Value | Usage |
|---|---|---|
| $animation_duration-skeleton-highlight | 1400ms | 骨架屏高亮动画时长 |
| $animation_function-skeleton-highlight | ease | |
| $color-skeleton_default-bg-default | var(--semi-color-fill-0) | 骨架屏背景色 - 默认 |
| $color-skeleton_loading-gradient-bg-active | var(--semi-color-fill-1) | 骨架屏背景色 - 动画开启后 |
| $width-skeleton_avatar_extra_extra_small | 20px | 头像骨架屏尺寸 - 极小 |
| $width-skeleton_avatar_extra_small | 24px | 头像骨架屏尺寸 - 超小 |
| $width-skeleton_avatar_small | 32px | 头像骨架屏尺寸 - 小 |
| $width-skeleton_avatar_medium | 48px | 头像骨架屏尺寸 - 中 |
| $width-skeleton_avatar_large | 72px | 头像骨架屏尺寸 - 大 |
| $width-skeleton_avatar_extra_large | 128px | 头像骨架屏尺寸 - 超大 |
| $width-skeleton_button | 115px | 按钮骨架屏宽度 |
| $height-skeleton_li | 16px | 段落骨架屏高度 |
| $height-skeleton_title | $height-control-small | 标题骨架屏高度 |
| $height-skeleton_button | $height-control-default | 按钮骨架屏高度 |
| $spacing-skeleton_li-marginBottom | 10px | 按钮骨架屏高度 |
| $radius-skeleton_item | var(--semi-border-radius-small) | 骨架屏圆角 |
| $radius-skeleton_li | var(--semi-border-radius-small) | 骨架屏圆角 |