Image Optimization Best Practices

Maintain fast and responsive websites on tablets, mobiles, and desktops by tailoring image sizes to adjust based on a device’s screen resolution. This section includes best practices to ensure images on your customer’s store are responsive, load faster, and have no layout shifts.

Switch Resolution Based on the Browser Size

Ensure your customer’s browser picks responsive and optimized images based on their device screen size. When you build custom components, implement attributes, srcset and sizes, in the img element.

srcset defines a set of images based on the device's screen size and resolution. The srcset attribute helps you define multiple image sources of different widths, separated by a comma. Browser picks the most appropriate image, based on the screen size and resolution. The attribute sizes define the size of the image element. You can use any length value to represent the size, but not percentages. For example, the size can represent the absolute width (480 px) or a width relative to the viewport (50 vw).

For example, consider an image with these attributes:

<img
  srcset="product-480w.jpg 480w, product-800w.jpg 800w"
  sizes="(max-width: 600px) 480px,800px"
  src="product-800w.jpg"
  alt="Product Image">

From the example,

  • (product-480w.jpg) represents the image filename and type, and(480w)represents the image’s intrinsic width in pixels.
  • (max-width: 600px)480px represents that if the viewport width is up to 600 px, each image takes up 480-px width.

You can also provide a better user experience for customers using stores by specifying the srcset in the picture element to include a higher resolution version of the image. For example, consider a picture element where the srcsetattribute has x-descriptors and thesizes attribute isn’t defined.

<picture>
  <source srcset="product.png?width=400, product.png?width=800 2x">
  <source media="(max-width: 800px)" srcset="product.png?width=200, product.png?width=400 2x">
  <img src="product.png" alt="Product Image">
</picture>

If the device accessing the page has a standard or a low-resolution display, with one device pixel representing each CSS pixel, the product.png?width=400 image is displayed. Whereas if the device has a high resolution of two device pixels per CSS pixel or more, the product.png?width=800 image is displayed.

Avoid Cumulative Layout Shifts

Ensure that your customer’s browser can reserve the appropriate amount of space in the layout before the images are fully loaded, thus preventing any disruptive shifts. Define the image's aspect ratio, which is the ratio of width to height. This example shows how width and height are defined for an image.

<img
  src="product.png"
  width="800px" height="800px"
  alt="Product Image">

This example shows the width and aspect ratio attributes added to the image.

//html
<img
  src="product.png"
  alt="Product Image">

//css
img {
  width: 800px;
  aspect-ratio: 1/1;
}

Improve Image Loading Time

Ensure images have a high quality and small size, for a quicker loading time. Leverage the built-in image scaling CDN (Content Delivery Network) and CMS (Content Management System) capabilities. Automatically scale images, instead of uploading the same image in different sizes. By using the resource resolver from experience/resourceResolver, component developers can leverage a URL resolver that works for both CDN and CMS.
Here’s an example of how to scale images to the appropriate sizes for the various devices and screen resolutions.

import { resolve } from 'experience/resourceResolver';

// External URL && Cloudflare
const externalUrl = resolve('https://www.imageserver/product.png', true, { width: 800, height: 800 });
console.log(externalUrl)
// {storeHostname}/cdn-cgi/images/width=800&height=800/https://www.imageserver/product.png

// CMS URL && no CDN
const cmsUrl = resolve('cms/sfsites/product.png', true, { width: 800, height: 800 });
console.log(cmsUrl)
// cms/sfsites/product.png?width=800&height=800

Enhance Image Using the Experience-Picture Component

If you prefer to customize an image with appropriate source elements, and not create the attributes srcset and sizes, use the experience-picture component. This component allows you to define multiple sources for the image based on factors such as device resolution, viewport size, and pixel density.

The component exposes these properties

Property Type Default Description
alternativeText string | undefined undefined The alternative text for the image. This value is set to empty for decorative images.
loading lazy | eager | undefined eager Determines how the image is loaded on a webpage.
url string | undefined undefined The placeholder image if the specified image isn’t found or unable to load.
images ImageData[] | undefined undefined The srcSet for each form factor or media query. Either use CustomizedImageData with your own media query or use the PredefinedImageData with the formFactor name and a media query based on the SLDS breakpoints, which is created automatically.

Consider this example that explains how to use the component.

 ## Image Types
type CustomizedImageData =
{
  /**
  * media condition that defines breakpoint
  * optional - if unset the slds default can be used by setting the formFactor
  */
  media?: string;

  /**
  * defines a set of source sizes, each containing a media condition and a size value
  * (min-width: 768px) 700px,
  * (min-width: 1024px) 600px,
  * 500px
  */
  sizes: string;

  /**
  * defines image sources containing an url followed by a whitespace and either a width descriptor or pixel density
  * product-small.jpg 700w,
  * product-medium.jpg 1200w,
  * product-large.jpg 1600w
  */
  srcSet: string;
};

type PredefinedImageData =
{
  /**
  * used to mimic the slds breakpoints for different screen sizes
  */
  formFactor: FormFactor;

  /**
  * defines a set of source sizes, each containing a media condition and a size value
  * (min-width: 768px) 700px,
  * (min-width: 1024px) 600px,
  * 500px
  */
  sizes?: string;

  /**
  * defines image sources containing an url followed by a whitespace and either a width descriptor or pixel density
  * product-small.jpg,
  * product-medium.jpg 2x,
  * product-large.jpg 3x
  */
  srcSet: string;
};

export type ImageData = PredefinedImageData | CustomizedImageData;
export type FormFactor = 'mobile' | 'tablet' | 'desktop';

Additionally you can use a utility method from experience/picture to create those srcSets based on the image widths of your component.

type ImageSizes = Record<FormFactor, number>;
createImageDataMap(url, [ImageSizes], [devicePixelRatio])

Here’s an example:

createImageDataMap(
  'https://example.com/image.jpg',
  {
    mobile: 200,
    tablet: 400,
    desktop: 600
  }
  [1, 2]
)

--> returns a srcSet for each of the form factors
[
  {
    formFactor: 'mobile'
    srcSet: 'https://example.com/image.jpg?width=200,
    https://example.com/image.jpg?width=400 2x'
  },
  {
    formFactor: 'tablet'
    srcSet: 'https://example.com/image.jpg?width=2=400,
    https://example.com/image.jpg?width=800 2x'
  }
  {
    formFactor: 'desktop'
    srcSet: 'https://example.com/image.jpg?width=600,
    https://example.com/image.jpg?width=800 2x'
  }
]
// The picture component uses these media queries for the different form factors
export const MEDIA_QUERIES: { mobile: string; tablet: string; desktop: string } =
{
  mobile: '(max-width: 47.9375em)',
  tablet: '(max-width: 64em)',
  desktop: '(min-width: 64.0625em)',
};
<experience-picture
  alternative-text="Product Image"
  url="https://example.com/image.jpg"
  images="{images}"
></experience-picture>

--> inside the picture component this html is generated
<picture>
  <source
    media="(min-width: 64.0625em)"
    srcset="https://example.com/image.jpg?width=600, https://example.com/image.jpg?width=800 2x"
  />
  <source
    media="(max-width: 64em)"
    srcset="https://example.com/image.jpg?width=400, https://example.com/image.jpg?width=800 2x"
  />
  <source
    media="(max-width: 47.9375em)"
    srcset="https://example.com/image.jpg?width=200, https://example.com/image.jpg?width=400 2x"
  />
  <img src="https://example.com/image.jpg" alt="Product Image" />
</picture>