--- title: SkeletonImage description: >- SkeletonImage is used to provide a low fidelity representation of an image before it appears on the page. api_version: 2025-07 api_name: customer-account-ui-extensions source_url: html: >- https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/ui-components/media-and-visuals/skeletonimage md: >- https://shopify.dev/docs/api/customer-account-ui-extensions/2025-07/ui-components/media-and-visuals/skeletonimage.md --- Migrate to Polaris Version 2025-07 is the last API version to support React-based UI components. Later versions use [web components](https://shopify.dev/docs/api/customer-account-ui-extensions/latest/polaris-web-components), native UI elements with built-in accessibility, better performance, and consistent styling with [Shopify's design system](https://shopify.dev/docs/apps/design). Check out the [migration guide](https://shopify.dev/docs/apps/build/customer-accounts/migrate-to-web-components) to upgrade your extension. # Skeleton​Image SkeletonImage is used to provide a low fidelity representation of an image before it appears on the page. ### Support Targets (25) ### Supported targets * Customer​Account::Kitchen​Sink * customer-account.​footer.​render-after * customer-account.​order-index.​announcement.​render * customer-account.​order-index.​block.​render * customer-account.​order-status.​announcement.​render * customer-account.​order-status.​block.​render * customer-account.​order-status.​cart-line-item.​render-after * customer-account.​order-status.​cart-line-list.​render-after * customer-account.​order-status.​customer-information.​render-after * customer-account.​order-status.​fulfillment-details.​render-after * customer-account.​order-status.​payment-details.​render-after * customer-account.​order-status.​return-details.​render-after * customer-account.​order-status.​unfulfilled-items.​render-after * customer-account.​order.​action.​menu-item.​render * customer-account.​order.​action.​render * customer-account.​order.​page.​render * customer-account.​page.​render * customer-account.​profile.​addresses.​render-after * customer-account.​profile.​announcement.​render * customer-account.​profile.​block.​render * customer-account.​profile.​company-details.​render-after * customer-account.​profile.​company-location-addresses.​render-after * customer-account.​profile.​company-location-payment.​render-after * customer-account.​profile.​company-location-staff.​render-after * customer-account.​profile.​payment.​render-after ## SkeletonImageProps * **aspectRatio** **number** The aspect ratio to display the skeleton at (fills the width of the parent container and sets the height accordingly). Use this to reserve the correct space for an image before it loads, preventing content jumping. * **blockSize** **MaybeResponsiveConditionalStyle\** The block size (height in horizontal writing modes) of the skeleton placeholder. * `number`: The size in pixels. * `` `${number}%` ``: The size as a percentage of the parent container's block size. * `fill`: Takes all the available space. Learn more about the [block-size](https://developer.mozilla.org/en-US/docs/Web/CSS/block-size) property. * **id** **string** A unique identifier for the component. * **inlineSize** **MaybeResponsiveConditionalStyle\** The inline size (width in horizontal writing modes) of the skeleton placeholder. * `number`: The size in pixels. * `` `${number}%` ``: The size as a percentage of the parent container's inline size. * `fill`: Takes all the available space. Learn more about the [inline-size](https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size) property. ### MaybeResponsiveConditionalStyle A type that represents a value that can be a conditional style. The conditions are based on the viewport size. We highly recommend using the \`Style\` helper which simplifies the creation of conditional styles. ```ts T | ConditionalStyle ``` ### ConditionalStyle A conditional style definition that maps one or more conditions to different values. The \`default\` value is used as a fallback when none of the conditions in \`conditionals\` are satisfied. * conditionals An array of conditional values. ```ts ConditionalValue[] ``` * default The default value applied when none of the conditional values specified in \`conditionals\` are met. ```ts T ``` ### ConditionalValue A single conditional branch that pairs a set of conditions with the value to apply when those conditions are met. * conditions The conditions that must be met for the value to be applied. At least one condition must be specified. ```ts AcceptedConditions ``` * value The value that will be applied if the conditions are met. ```ts T ``` ### ViewportSizeCondition A condition that targets layouts based on the inline size (width in horizontal writing modes) of the viewport. * viewportInlineSize The minimum viewport inline size that the condition must match. ```ts { min: T; } ``` Examples ## Preview ![](https://cdn.shopify.com/shopifycloud/shopify-dev/development/assets/assets/images/templated-apis-screenshots/checkout-ui-extensions/2025-07/skeletonimage-default-FXO81Xcs.png) ### Examples * #### Basic SkeletonImage ##### React ```tsx import { reactExtension, SkeletonImage, } from '@shopify/ui-extensions-react/customer-account'; export default reactExtension( 'customer-account.page.render', () => , ); function Extension() { return ( ); } ``` ##### JS ```js import {extension, SkeletonImage} from '@shopify/ui-extensions/customer-account'; export default extension('customer-account.page.render', (root) => { const skeletonImage = root.createComponent(SkeletonImage, { inlineSize: 300, blockSize: 300, }); root.appendChild(skeletonImage); }); ``` * #### Using skeleton loaders to prevent layout shifts on content load. ##### Description When adding content to a layout, incorporate a skeleton loader that renders the approximate size and position of the content during loading. This will provide a seamless transition from skeleton loaders to the content, and prevent any layout shift when the resulting content loads. ##### React ```jsx import { reactExtension, View, BlockStack, InlineLayout, SkeletonImage, Image, Icon, SkeletonText, Text, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); export const ProductThumbnail = ({ source = 'https://yourawesomeimage.com', }) => ( {source ? ( ) : ( )} ); export const LoadingStateSkeletons = () => { const loading = true; const [item1, item2] = [ { title: 'Felipe Toledo WildFire', variantTitle: 'Medium', price: '$330.00', }, { title: 'Roller', variantTitle: 'Medium', price: '$248.00', }, ]; const itemInfo = ({title, variantTitle}) => loading ? ( <> {title} {variantTitle} ) : ( <> {title} {variantTitle} ); const order = (item) => ( {loading ? ( ) : ( )} {itemInfo(item)} {loading ? ( {item.price} ) : ( {item.price} )} ); return ( {order(item1)} {order(item2)} ); }; ``` ##### JavaScript ```js import { extension, BlockStack, View, InlineLayout, Image, Icon, Text, SkeletonImage, SkeletonText, } from '@shopify/ui-extensions/checkout'; export default extension( 'purchase.checkout.block.render', (root) => { const source = 'https://yourawesomeimage.com'; const loading = true; const [item1, item2] = [ { title: 'Felipe Toledo WildFire', variantTitle: 'Medium', price: '$330.00', }, { title: 'Roller', variantTitle: 'Medium', price: '$248.00', }, ]; const thumbnail = root.createComponent( View, { minBlockSize: 64, cornerRadius: 'large', maxInlineSize: 64, minInlineSize: 64, border: 'base', }, [ source ? root.createComponent(Image, { fit: 'cover', aspectRatio: 1, source, cornerRadius: 'large', }) : root.createComponent( View, {maxInlineSize: 33}, [ root.createComponent(Icon, { source: 'camera', size: 'fill', }), ], ), ], ); const itemInfo = ({title, variantTitle}) => root.createComponent( BlockStack, { spacing: 'extraTight', }, [ loading ? (root.createComponent( SkeletonText, {}, title, ), root.createComponent( SkeletonText, {}, variantTitle, )) : (root.createComponent( Text, {}, title, ), root.createComponent( Text, {}, variantTitle, )), ], ); const order = (item) => root.createComponent( InlineLayout, { columns: ['auto', 'fill', 'auto'], spacing: 'base', blockAlignment: 'center', }, [ loading ? root.createComponent( SkeletonImage, { blockSize: 64, inlineSize: 64, }, ) : thumbnail, itemInfo(item), loading ? root.createComponent( SkeletonText, {}, item.price, ) : root.createComponent( Text, {}, item.price, ), ], ); const view = root.createComponent( View, { maxInlineSize: 400, }, [ root.createComponent(BlockStack, {}, [ order(item1), order(item2), ]), ], ); root.appendChild(view); }, ); ```