Skeleton
A Skeleton is a low-fidelity visual placeholder that represents the loading of interface elements before they have displayed on the page. Appearing as a blank version of the page, it mitigates focus on the loading process and improves the user’s perceived load time.
Anatomy

- Shape Skeleton: Represents graphical elements such as avatars, icons, and small Images.
- Header Skeleton: Represent headings and sub-headings.
- Text Skeleton: Represent paragraph and body text.
Usage Guidance
- A Skeleton should provide a close representation of the ultimate page layout and content once loaded.
- Use motion within the Skeleton to reinforce that the page is loading behind the scenes.
- Ideal for pages that require longer initial load times.
- Use for pages where all content loads at the same time.
- Meant to be used specifically on a white background.
When to Use
- Use Skeleton if the visual layout/format of the content being loaded is known ahead of time.
- Use specifically on pages where all or a majority of the page will be taking time to load.
When to Use Something Else
- If the visual layout/format of the content being loaded is unknown; or you need to indicate processing or that change will occur on the page (rather than loading UI elements), consider using a Loading Dots instead.
Examples
Basic Example
Skeleton includes a container Skeleton component and the following subcomponents:
Skeleton.Header, Skeleton.Text, and Skeleton.Shape. Each subcomponent can be used as a
placeholder for a particular type of content.
Here’s an example of how you might compose Skeleton components (along with non-Skeleton components
such as Box and Flex) to create a loading placeholder for a piece of content comprised of an
icon, a heading, and some text.
import React from 'react';
import {Skeleton} from '@workday/canvas-kit-react/skeleton';
import {Box, Flex} from '@workday/canvas-kit-react/layout';
import {borderRadius, space} from '@workday/canvas-kit-react/tokens';
export default () => {
return (
<Skeleton>
<Flex alignItems="center">
<Skeleton.Shape width={space.xl} height={space.xl} borderRadius={borderRadius.circle} />
<Box flex={1} marginLeft="xs">
<Skeleton.Header />
</Box>
</Flex>
<Skeleton.Text />
</Skeleton>
);
};
And here’s an example that simulates how that Skeleton might work in practice.
import React from 'react';
import {keyframes} from '@emotion/react';
import {Card} from '@workday/canvas-kit-react/card';
import {Checkbox} from '@workday/canvas-kit-react/checkbox';
import {FormField} from '@workday/canvas-kit-react/form-field';
import {SecondaryButton} from '@workday/canvas-kit-react/button';
import {SystemIconCircle} from '@workday/canvas-kit-react/icon';
import {TextInput} from '@workday/canvas-kit-react/text-input';
import {Box, Flex} from '@workday/canvas-kit-react/layout';
import {Skeleton} from '@workday/canvas-kit-react/skeleton';
import {borderRadius, space} from '@workday/canvas-kit-react/tokens';
import {patternIcon} from '@workday/canvas-system-icons-web';
import {styled, StyledType} from '@workday/canvas-kit-react/common';
import {Heading} from '@workday/canvas-kit-react/text';
const fadeOut = keyframes`
from {
opacity: 1;
}
to {
opacity: 0;
}
`;
const StyledSimulation = styled(Box)<StyledType>({
pointerEvents: 'none',
});
export default () => {
const [loading, setLoading] = React.useState(true);
const [loadTime, setLoadTime] = React.useState('3000');
const timer = React.useRef(0);
const loadTimeValue = React.useRef(parseFloat(loadTime));
const resetTimeout = () => {
setLoading(true);
window.clearTimeout(timer.current);
timer.current = window.setTimeout(() => {
setLoading(false);
}, loadTimeValue.current);
return () => {
window.clearTimeout(timer.current);
};
};
const onChangeLoading = (event: React.ChangeEvent<HTMLInputElement>) => {
window.clearTimeout(timer.current);
setLoading(event.target.checked);
};
const onChangeLoadTime = (event: React.ChangeEvent<HTMLInputElement>) => {
setLoadTime(event.currentTarget.value);
const value = parseInt(event.currentTarget.value, 10);
if (value) {
loadTimeValue.current = value;
}
};
React.useEffect(resetTimeout, []);
return (
<Box>
<Box marginBottom="l">
<FormField orientation="horizontalStart">
<FormField.Label>Load Time</FormField.Label>
<FormField.Input as={TextInput} onChange={onChangeLoadTime} value={loadTime} />
</FormField>
<FormField orientation="horizontalStart">
<FormField.Label>Loading</FormField.Label>
<FormField.Input as={Checkbox} checked={loading} onChange={onChangeLoading} />
</FormField>
<SecondaryButton onClick={resetTimeout}>Simulate Loading</SecondaryButton>
</Box>
<Card>
<Card.Body>
<Box minHeight={180} position="relative">
{loading ? (
<StyledSimulation
position="absolute"
top={0}
left={0}
width="100%"
animation={!loading ? `${fadeOut} 150ms ease-out forwards` : undefined}
>
<Skeleton>
<Flex alignItems="center">
<Skeleton.Shape
width={space.xl}
height={space.xl}
borderRadius={borderRadius.circle}
/>
<Box flex={1} marginLeft="xs">
<Skeleton.Header />
</Box>
</Flex>
<Skeleton.Text lineCount={3} />
</Skeleton>
</StyledSimulation>
) : (
<Box>
<Flex alignItems="center" display="inline-flex" marginBottom="s">
<SystemIconCircle icon={patternIcon} />
<Heading as="h3" size="small" margin={`0 0 0 ${space.xxs}`}>
Patterns
</Heading>
</Flex>
<p>
Canvas Patterns classify and document reusable solutions built to respond to
common user scenarios. Following these guidelines allows us to design experiences
that feel consistent and natural for users as they move between applications and
ensures that our approach aligns with industry standards.
</p>
</Box>
)}
</Box>
</Card.Body>
</Card>
</Box>
);
};
Press the Simulate Loading button to simulate the loading of the content (customize the loading time using the Load Time field), or check the Loading check box to force the Skeleton to display.
Color
All Skeleton subcomponents accept a backgroundColor prop which can be used to specify the color of
the subcomponent. This is generally only recommended to be used for dark or gray backgrounds to
ensure the Skeleton components are visible.
import React from 'react';
import {Skeleton} from '@workday/canvas-kit-react/skeleton';
import {Box, Flex} from '@workday/canvas-kit-react/layout';
import {borderRadius, colors, space} from '@workday/canvas-kit-react/tokens';
export default () => {
return (
<Skeleton>
<Flex alignItems="center">
<Skeleton.Shape
width={space.xl}
height={space.xl}
borderRadius={borderRadius.circle}
backgroundColor={colors.berrySmoothie100}
/>
<Box flex={1} marginLeft="xs">
<Skeleton.Header backgroundColor={colors.cantaloupe100} />
</Box>
</Flex>
<div>
<Skeleton.Text backgroundColor={colors.fruitPunch100} />
</div>
</Skeleton>
);
};
Text
Skeleton.Text renders a placeholder for text content such as paragraphs. Each placeholder line has
a width of 100% and a fixed height of 21px, with the last line having a width of 60% if there
are multiple lines.
import React from 'react';
import {Skeleton} from '@workday/canvas-kit-react/skeleton';
export default () => {
return (
<Skeleton>
<Skeleton.Text />
</Skeleton>
);
};
Header
Skeleton.Header renders a placeholder for header content such as headings.
import React from 'react';
import {Skeleton} from '@workday/canvas-kit-react/skeleton';
export default () => {
return (
<Skeleton>
<Skeleton.Header />
</Skeleton>
);
};
Shape
Skeleton.Shape renders a placeholder for graphic elements such as icons, avatars and small images.
Set the height, width, and borderRadius props of the Skeleton.Shape to create various
rectangular and circular shapes.
import React from 'react';
import {Skeleton} from '@workday/canvas-kit-react/skeleton';
import {borderRadius, space} from '@workday/canvas-kit-react/tokens';
export default () => {
return (
<Skeleton>
<Skeleton.Shape width={space.xxl} height={space.xxl} borderRadius={borderRadius.circle} />
</Skeleton>
);
};
Component API
Skeleton
Skeleton subcomponents must be wrapped by the Skeleton container component.
<Skeleton>
<Skeleton.Header />
<Skeleton.Text />
</Skeleton>
Skeleton places its children in a container element with aria-hidden set to true and
announces itself using a visually hidden element.
Props
Props extend from div. Changing the as prop will change the element interface.
| Name | Type | Description | Default |
|---|---|---|---|
aria-label | string | For accessibility reasons, IMPORTANT: Since we take over the use of | |
children | ReactNode | ||
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | div |
ref | React.Ref<R = div> | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If |
Skeleton.Header
Skeleton.Header renders a placeholder for header content such as headings.
Props
Props extend from div. Changing the as prop will change the element interface.
| Name | Type | Description | Default |
|---|---|---|---|
backgroundColor | string | The background color of the skeleton | |
height | number | string | The height of the shape in | |
width | number | string | The width of the shape in | '100%' |
cs | | The | |
children | React.ReactNode | ||
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | div |
ref | React.Ref<R = div> | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If |
Skeleton.Text
Skeleton.Text renders a placeholder for text content such as paragraphs. Each placeholder
line has a width of 100% and a fixed height of 21px, with the last line having a width of
60% if there are multiple lines.
Props
Props extend from div. Changing the as prop will change the element interface.
| Name | Type | Description | Default |
|---|---|---|---|
lineCount | number | The number of "lines" that SkeletonText will display. If there is more than one line, the last line will have a width of | 2 |
backgroundColor | string | The background color of the skeleton | |
children | React.ReactNode | ||
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | div |
ref | React.Ref<R = div> | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If |
Skeleton.Shape
Skeleton.Shape renders a placeholder for graphic elements such as icons, avatars and small
images. Set the height, width, and borderRadius props of the Skeleton.Shape to create
various rectangular and circular shapes.
Props
Props extend from div. Changing the as prop will change the element interface.
| Name | Type | Description | Default |
|---|---|---|---|
width | number | string | The width of the shape in | '100%' |
height | number | string | The height of the shape in | |
borderRadius | number | string | The borderRadius of the shape in | 0 |
backgroundColor | string | The background color of the skeleton | |
cs | | The | |
children | React.ReactNode | ||
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | div |
ref | React.Ref<R = div> | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If |
Accessibility Guidelines
- A Skeleton should announce to users using a screen reader that content or a page is being loaded.
Content Guidelines
- Though the Skeleton component does not use actual content, the Header Skeleton and the Text Skeleton elements should be used as though they are actual content.
- The Header Skeleton will represent headings and sub-headings while the Text Skeleton will represent paragraph or body text.
Anatomy

- Shape Skeleton: Represents graphical elements such as avatars, icons, and small images.
- Header Skeleton: Represent headings and subheadings.
- Text Skeleton: Represent paragraph and body text.
Usage Guidance
- Tailor Skeleton to provide an approximate representation of the final page layout and content that will be loaded. If the skeleton presented does not closely match the final content loaded, consider using a different loading animation instead.
- Use a shimmer animation within the entire Skeleton to reinforce the notion that the page is loading behind the scenes.
- Use Skeleton for pages that require longer initial load times, over 300ms.
- Use Skeleton for pages where all content will load at the same time.
- Skeleton is designed specifically to be used against a white background.
- If content fails to load, use a contextual Empty State that clearly communicates why there is no data, and explains any next steps the user should take.
When to Use
- Use Skeleton if the visual layout/format of the overall content being loaded is known ahead of time.
- Use on pages where all or a majority of the page will take time to load.
When to Use Something Else
- If the visual layout/format of the content being loaded is unknown; or you need to indicate processing or that change will occur on the page (rather than loading UI elements), consider using a Loading Animtation instead.
- If load times are insignificant (under 100ms), consider not using a loading treatment at all as it will not help perceived performance.
Variations
Circle
Use Circle Skeleton for Avatars and Icons.

Custom
Custom Skeleton is used to represent small images before they are loaded onto the screen.

Header
Header Skeleton is used as a loading placeholder to cover all heading text styles: H1, H2, and H3.

Text
Text Skeleton is used as a loading placeholder to cover all body and subtext text styles.

API Guidelines
Component Definition
public struct SkeletonLoader: ViewWD-Standard SkeletonLoader component, a custom SwiftUI view. The SkeletonLoader view represents the loading state of an incoming view
Properties
body
public var body: some ViewMethods
init(_:doAnimate:)
public init(_ components: [SkeletonLoaderComponent] = [
.avatar,
.shorterText,
.text,
.divider
], doAnimate: Bool = true)Parameters
| Name | Description |
|---|---|
| components | An array of SkeletonLoaderComponents used to form a skeleton view. These components will be positioned in the view container based on their type (i.e. .avatar is anchored to the left, .divider is anchored to the bottom, .icons are stacked horizontally, and text components are stacked vertically). |
Accessibility Guidelines
- Screen Readers announce that content or a page is being loaded.
- When a new page is displayed, be sure the user’s focus begins at the top of the screen again.
- When used for a section (or sections) of the page, screen readers should announce the section is still loading, and politely alert users when loading is finished.
Content Guidelines
- Though the Skeleton component does not use actual content, the Header Skeleton and the Text Skeleton should be used as if they were actual content.
- The Header Skeleton represents headings and subheadings while the Text Skeleton represents paragraph or body text.
Anatomy

- Shape Skeleton: Represents graphical elements such as avatars, icons, and small images.
- Header Skeleton: Represent headings and subheadings.
- Text Skeleton: Represent paragraph and body text.
Usage Guidance
- Tailor Skeleton to provide an approximate representation of the final page layout and content that will be loaded. If the skeleton presented does not closely match the final content loaded, consider using a different loading animation instead.
- Use a shimmer animation within the entire Skeleton to reinforce the notion that the page is loading behind the scenes.
- Use Skeleton for pages that require longer initial load times, over 300ms.
- Use Skeleton for pages where all content will load at the same time.
- Skeleton is designed specifically to be used against a white background.
- If content fails to load, use a contextual Empty State that clearly communicates why there is no data, and explains any next steps the user should take.
When to Use
- Use Skeleton if the visual layout/format of the overall content being loaded is known ahead of time.
- Use on pages where all or a majority of the page will take time to load.
When to Use Something Else
- If the visual layout/format of the content being loaded is unknown; or you need to indicate processing or that change will occur on the page (rather than loading UI elements), consider using a loading animation instead.
- If load times are insignificant (under 100ms), consider not using a loading treatment at all as it will not help perceived performance.
Variations
Circle
Use Circle Skeleton for Avatars and Icons.

Custom
Custom Skeleton is used to represent small images before they are loaded onto the screen.

Header
Header Skeleton is used as a loading placeholder to cover all heading text styles: H1, H2, and H3.

Text
Text Skeleton is used as a loading placeholder to cover all body and subtext text styles.

API Guidelines
Component Definition
fun SkeletonLoadingUiComponent(
components: List; SkeletonComponent; = DEFAULT_SET_COMPONENTS_WITH_DIVIDER,
doAnimate: Boolean = true
)Parameters
| Name | Description |
|---|---|
| components | A list of SkeletonComponents that will be displayed in a row. The available SkeletonComponents are: Avatar, Icon, Header, Text, Shorter Text, Divider, and Custom Shape |
| doAnimate | Boolean that controls whether the skeleton loader will display the shimmer animation |
Accessibility Guidelines
- Screen Readers announce that content or a page is being loaded.
- When a new page is displayed, be sure the user’s focus begins at the top of the screen again.
- When used for a section (or sections) of the page, screen readers should announce the section is still loading, and politely alert users when loading is finished.
Content Guidelines
- Though the Skeleton component does not use actual content, the Header Skeleton and the Text Skeleton should be used as if they were actual content.
- The Header Skeleton represents headings and subheadings while the Text Skeleton represents paragraph or body text.
Can't Find What You Need?
Check out our FAQ section which may help you find the information you're looking for. For further information, contact the #ask-canvas-design or #ask-canvas-kitchannels on Slack.