Skip to main content

Skeleton

Provide placeholder graphics at positions where content is loading.

When to Use

  • When network is slow and data loading takes a long time
  • During initial page rendering, need to show loading state
  • When loading list or card content
  • Provide better user experience and avoid page flickering

Examples

Basic Usage

Most basic skeleton usage, default width 100%.

Live Editor
function Demo() {
  return <Skeleton height={16} />;
}
Result
Loading...

Different Sizes

Set skeleton dimensions through width and height properties.

Live Editor
function Demo() {
  return (
    <div>
      <Skeleton height={8} style={{ marginBottom: '8px' }} />
      <Skeleton height={12} style={{ marginBottom: '8px' }} />
      <Skeleton height={16} style={{ marginBottom: '8px' }} />
      <Skeleton height={24} style={{ marginBottom: '8px' }} />
      <Skeleton height={32} />
    </div>
  );
}
Result
Loading...

Circle Skeleton

Create circular skeleton through circle property, commonly used for avatar placeholders.

Live Editor
function Demo() {
  return (
    <Group spacing="md">
      <Skeleton height={32} width={32} circle />
      <Skeleton height={40} width={40} circle />
      <Skeleton height={48} width={48} circle />
      <Skeleton height={64} width={64} circle />
    </Group>
  );
}
Result
Loading...

Border Radius

Set border radius size through radius property.

Live Editor
function Demo() {
  return (
    <div>
      <Skeleton height={16} radius="xs" style={{ marginBottom: '8px' }} />
      <Skeleton height={16} radius="sm" style={{ marginBottom: '8px' }} />
      <Skeleton height={16} radius="md" style={{ marginBottom: '8px' }} />
      <Skeleton height={16} radius="lg" style={{ marginBottom: '8px' }} />
      <Skeleton height={16} radius="xl" />
    </div>
  );
}
Result
Loading...

Disable Animation

Disable animation effect through animate={false}.

Live Editor
function Demo() {
  return (
    <div>
      <Skeleton height={16} animate={true} style={{ marginBottom: '8px' }} />
      <Skeleton height={16} animate={false} />
    </div>
  );
}
Result
Loading...

Text Placeholder

Simulate skeleton for multi-line text.

Live Editor
function Demo() {
  return (
    <div>
      <Skeleton height={12} radius="xl" style={{ marginBottom: '8px' }} />
      <Skeleton height={12} radius="xl" style={{ marginBottom: '8px' }} />
      <Skeleton height={12} radius="xl" style={{ marginBottom: '8px' }} />
      <Skeleton height={12} width="70%" radius="xl" />
    </div>
  );
}
Result
Loading...

Content with Avatar

Common skeleton combination with avatar and text.

Live Editor
function Demo() {
  return (
    <Group spacing="md" style={{ alignItems: 'flex-start' }}>
      <Skeleton height={48} width={48} circle />
      <div style={{ flex: 1 }}>
        <Skeleton height={12} width="40%" radius="xl" style={{ marginBottom: '8px' }} />
        <Skeleton height={12} radius="xl" style={{ marginBottom: '8px' }} />
        <Skeleton height={12} radius="xl" style={{ marginBottom: '8px' }} />
        <Skeleton height={12} width="60%" radius="xl" />
      </div>
    </Group>
  );
}
Result
Loading...

Card Skeleton

Use skeleton in a card.

Live Editor
function Demo() {
  return (
    <div style={{ backgroundColor: '#eff4f9', padding: '20px' }}>
      <Card style={{ width: '350px' }}>
        <Skeleton height={120} radius="sm" style={{ marginBottom: '12px' }} />
        <Skeleton height={16} width="60%" radius="xl" style={{ marginBottom: '8px' }} />
        <Skeleton height={12} radius="xl" style={{ marginBottom: '8px' }} />
        <Skeleton height={12} radius="xl" style={{ marginBottom: '8px' }} />
        <Skeleton height={12} width="80%" radius="xl" />
      </Card>
    </div>
  );
}
Result
Loading...

List Skeleton

Skeleton effect for list items.

Live Editor
function Demo() {
  return (
    <div style={{ backgroundColor: '#eff4f9', padding: '20px' }}>
      <Card style={{ width: '400px' }}>
        {[1, 2, 3].map((item) => (
          <Group
            key={item}
            spacing="md"
            style={{
              padding: '12px 0',
              borderBottom: item < 3 ? '1px solid #d8dee5' : 'none',
              alignItems: 'flex-start',
            }}
          >
            <Skeleton height={40} width={40} circle />
            <div style={{ flex: 1 }}>
              <Skeleton height={12} width="50%" radius="xl" style={{ marginBottom: '8px' }} />
              <Skeleton height={10} width="80%" radius="xl" />
            </div>
            <Skeleton height={24} width={60} radius="sm" />
          </Group>
        ))}
      </Card>
    </div>
  );
}
Result
Loading...

Table Skeleton

Skeleton effect for loading tables.

Live Editor
function Demo() {
  return (
    <div>
      <Skeleton height={40} radius="sm" style={{ marginBottom: '8px' }} />
      {[1, 2, 3, 4].map((item) => (
        <Group
          key={item}
          style={{
            padding: '12px 0',
            borderBottom: '1px solid #d8dee5',
          }}
        >
          <Skeleton height={16} width="15%" radius="sm" />
          <Skeleton height={16} width="25%" radius="sm" />
          <Skeleton height={16} width="20%" radius="sm" />
          <Skeleton height={16} width="15%" radius="sm" />
          <Skeleton height={16} width="10%" radius="sm" />
        </Group>
      ))}
    </div>
  );
}
Result
Loading...

Loading State Toggle

Show skeleton combined with loading state.

Live Editor
function Demo() {
  const [loading, setLoading] = React.useState(true);

  return (
    <div style={{ backgroundColor: '#eff4f9', padding: '20px' }}>
      <Button onClick={() => setLoading(!loading)} style={{ marginBottom: '16px' }}>
        {loading ? 'Show Content' : 'Show Skeleton'}
      </Button>
      <Card style={{ width: '350px' }}>
        {loading ? (
          <Group spacing="md" style={{ alignItems: 'flex-start' }}>
            <Skeleton height={48} width={48} circle />
            <div style={{ flex: 1 }}>
              <Skeleton height={14} width="60%" radius="xl" style={{ marginBottom: '8px' }} />
              <Skeleton height={12} radius="xl" style={{ marginBottom: '8px' }} />
              <Skeleton height={12} width="80%" radius="xl" />
            </div>
          </Group>
        ) : (
          <Group spacing="md" style={{ alignItems: 'flex-start' }}>
            <div
              style={{
                width: '48px',
                height: '48px',
                borderRadius: '50%',
                backgroundColor: '#329dce',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                color: '#fff',
                fontWeight: 600,
              }}
            >
              K
            </div>
            <div style={{ flex: 1 }}>
              <div style={{ fontWeight: 600, marginBottom: '4px' }}>KubeSphere</div>
              <div style={{ fontSize: '12px', color: '#79879c' }}>
                Container platform for cloud native applications, supports multi-cloud and
                multi-cluster management
              </div>
            </div>
          </Group>
        )}
      </Card>
    </div>
  );
}
Result
Loading...

Complex Layout

Skeleton for complex page layouts.

Live Editor
function Demo() {
  return (
    <div style={{ backgroundColor: '#eff4f9', padding: '20px' }}>
      <Card style={{ width: '500px' }}>
        <Group style={{ marginBottom: '16px' }}>
          <Skeleton height={32} width={32} circle />
          <div style={{ flex: 1 }}>
            <Skeleton height={14} width="30%" radius="xl" />
          </div>
          <Skeleton height={24} width={80} radius="sm" />
        </Group>
        <Skeleton height={200} radius="sm" style={{ marginBottom: '12px' }} />
        <Skeleton height={16} width="80%" radius="xl" style={{ marginBottom: '8px' }} />
        <Skeleton height={12} radius="xl" style={{ marginBottom: '8px' }} />
        <Skeleton height={12} radius="xl" style={{ marginBottom: '16px' }} />
        <Group>
          <Skeleton height={32} width={100} radius="sm" />
          <Skeleton height={32} width={100} radius="sm" />
        </Group>
      </Card>
    </div>
  );
}
Result
Loading...

API

Skeleton

PropertyDescriptionTypeDefault
visibleWhether to show skeletonbooleantrue
widthWidthnumber | string'100%'
heightHeightnumber | string'auto'
circleWhether it is circularbooleanfalse
radiusBorder radius size'xs' | 'sm' | 'md' | 'lg' | 'xl' | number'md'
animateWhether to show animationbooleantrue
info

About dimensions:

  • width and height support numbers (unit is px) or strings (like '100%', 'auto')
  • When circle is true, width automatically equals height

About border radius:

  • Preset radius: xs (2px), sm (4px), md (8px), lg (16px), xl (32px)
  • Can also pass numeric values directly
  • Text skeleton recommended to use xl radius

About animation:

  • Shows shimmer animation by default
  • For static placeholders, set animate={false}

About visible:

  • When visible is false, skeleton is not displayed
  • Can be used to control skeleton show/hide

Usage Recommendations

Reasonable Skeleton Layout

Skeleton should closely match the layout of actual content:

// Recommended: Layout similar to actual content
<Group spacing="md">
<Skeleton height={48} width={48} circle />
<div style={{ flex: 1 }}>
<Skeleton height={14} width="40%" radius="xl" style={{ marginBottom: '8px' }} />
<Skeleton height={12} radius="xl" />
</div>
</Group>

// Not recommended: Layout too different from actual content
<Skeleton height={100} />

Text Skeleton

Use skeleton with larger border radius for text:

// Simulate title
<Skeleton height={16} width="60%" radius="xl" style={{ marginBottom: '8px' }} />

// Simulate body text
<Skeleton height={12} radius="xl" style={{ marginBottom: '8px' }} />
<Skeleton height={12} radius="xl" style={{ marginBottom: '8px' }} />
<Skeleton height={12} width="80%" radius="xl" />

Avatar Skeleton

Use circular skeleton for avatars:

// Circular avatar
<Skeleton height={48} width={48} circle />

// Rounded avatar
<Skeleton height={48} width={48} radius="md" />

Button Skeleton

Use smaller border radius for buttons:

<Skeleton height={32} width={100} radius="sm" />

Combined with Loading State

Toggle display based on loading state:

const [loading, setLoading] = React.useState(true);

{loading ? (
<Skeleton height={16} radius="xl" />
) : (
<div>Actual content</div>
)}

List Skeleton

Use arrays to generate multiple skeleton items:

{[1, 2, 3].map((item) => (
<Group key={item} style={{ marginBottom: '12px' }}>
<Skeleton height={40} width={40} circle />
<Skeleton height={12} width="60%" radius="xl" />
</Group>
))}

Avoid Overuse

Skeleton should be used for content with longer loading times; for quickly loaded content, it may not be necessary:

// Recommended: For content requiring network requests
{loading ? <Skeleton height={200} /> : <DataTable data={data} />}

// Not recommended: For local data
{loading ? <Skeleton height={20} /> : <span>{localData}</span>}