Skip to content

Latest commit

History

History
258 lines (152 loc) 路 13.7 KB

image-directive.md

File metadata and controls

258 lines (152 loc) 路 13.7 KB

Getting started with NgOptimizedImage

The NgOptimizedImage directive makes it easy to adopt performance best practices for loading images.

The directive ensures that the loading of the Largest Contentful Paint image is prioritized by:

  • Automatically setting the fetchpriority attribute on the <img> tag
  • Lazy loading other images by default
  • Asserting that there is a corresponding preconnect link tag in the document head
  • Generating a preload hint if app is using SSR

In addition to optimizing the loading of the LCP image, NgOptimizedImage enforces a number of image best practices:

Prerequisites

  1. You will need to import NgOptimizedImage from the @angular/common module into your application. The directive is defined as a standalone directive, so components should import it directly.
  2. Consider setting up an image loader. These steps are explained in the Configuring an Image Loader section.

Usage in a template

Overview

To activate the NgOptimizedImage directive, replace your image's src attribute with ngSrc.

<img ngSrc="cat.jpg" width="400" height="200">

If you're using a built-in third-party loader, make sure to omit the base URL path from src, as that will be prepended automatically by the loader.

Preventing layout shift

To prevent image-related layout shifts, the directive enforces that you set the width and height attributes for each image.

  • For responsive images, the width and height attributes should reflect the intrinsic size of the image.

  • For fixed size images, the width and height attributes should reflect the desired rendered size of the image. The aspect ratio of these attributes should always match the intrinsic aspect ratio of the image.

Note: if you don't know the size of your images, consider using "fill mode" to inherit the size of the parent container (see below).

Marking images as priority

Always mark the LCP image on your page as priority to prioritize its loading.

<img ngSrc="cat.jpg" width="400" height="200" priority>

Marking an image as priority applies the following optimizations:

Angular displays a warning during development if the LCP element is an image that does not have the priority attribute. A page鈥檚 LCP element can vary based on a number of factors - such as the dimensions of a user's screen, so a page may have multiple images that should be marked priority. See CSS for Web Vitals for more details.

Adding resource hints

You can add a preconnect resource hint for your image origin to ensure that the LCP image loads as quickly as possible. Always put resource hints in the <head> of the document.

<link rel="preconnect" href="https://my.cdn.origin" />

By default, if you use a loader for a third-party image service, the NgOptimizedImage directive will warn during development if it detects that there is no preconnect resource hint for the origin that serves the LCP image.

To disable these warnings, inject the PRECONNECT_CHECK_BLOCKLIST token:

providers: [ {provide: PRECONNECT_CHECK_BLOCKLIST, useValue: 'https://your-domain.com'} ],

Using fill mode

In cases where you want to have an image fill a containing element, you can use the fill attribute. This is often useful when you want to achieve a "background image" behavior, or when you don't know the exact width and height of your image.

When you add the fill attribute to your image, you do not need and should not include a width and height, as in this example:

<img ngSrc="cat.jpg" fill>

Adjusting image styling

Depending on the image's styling, adding width and height attributes may cause the image to render differently. NgOptimizedImage warns you if your image styling renders the image at a distorted aspect ratio.

You can typically fix this by adding height: auto or width: auto to your image styles. For more information, see the web.dev article on the <img> tag.

Requesting images at the correct size

Defining a srcset attribute ensures that the browser requests an image at the right size for your user's viewport, so it doesn't waste time downloading an image that's too large. NgOptimizedImage generates an appropriate srcset for the image, based on the presence and value of the sizes attribute on the image tag.

Fixed-size images

If your image should be "fixed" in size (i.e. the same size across devices, except for pixel density), there is no need to set a sizes attribute. A srcset can be generated automatically from the image's width and height attributes with no further input required.

Example srcset generated: <img ... srcset="image-400w.jpg 1x, image-800w.jpg 2x">

Responsive images

If your image should be responsive (i.e. grow and shrink according to viewport size), then you will need to define a sizes attribute to generate the srcset.

If you haven't used sizes before, a good place to start is to set it based on viewport width. For example, if your CSS causes the image to fill 100% of viewport width, set sizes to 100vw and the browser will select the image in the srcset that is closest to the viewport width (after accounting for pixel density). If your image is only likely to take up half the screen (ex: in a sidebar), set sizes to 50vw to ensure the browser selects a smaller image. And so on.

If you find that the above does not cover your desired image behavior, see the documentation on advanced sizes values.

By default, the responsive breakpoints are:

[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]

If you would like to customize these breakpoints, you can do so using the IMAGE_CONFIG provider:

providers: [ { provide: IMAGE_CONFIG, useValue: { breakpoints: [16, 48, 96, 128, 384, 640, 750, 828, 1080, 1200, 1920] } }, ],

If you would like to manually define a srcset attribute, you can provide your own using the ngSrcset attribute:

<img ngSrc="hero.jpg" ngSrcset="100w, 200w, 300w">

If the ngSrcset attribute is present, NgOptimizedImage generates and sets the srcset based on the sizes included. Do not include image file names in ngSrcset - the directive infers this information from ngSrc. The directive supports both width descriptors (e.g. 100w) and density descriptors (e.g. 1x).

<img ngSrc="hero.jpg" ngSrcset="100w, 200w, 300w" sizes="50vw">

Disabling automatic srcset generation

To disable srcset generation for a single image, you can add the disableOptimizedSrcset attribute on the image:

<img ngSrc="about.jpg" disableOptimizedSrcset>

Disabling image lazy loading

By default, NgOptimizedImage sets loading=lazy for all images that are not marked priority. You can disable this behavior for non-priority images by setting the loading attribute. This attribute accepts values: eager, auto, and lazy. See the documentation for the standard image loading attribute for details.

<img ngSrc="cat.jpg" width="400" height="200" loading="eager">

Advanced 'sizes' values

You may want to have images displayed at varying widths on differently-sized screens. A common example of this pattern is a grid- or column-based layout that renders a single column on mobile devices, and two columns on larger devices. You can capture this behavior in the sizes attribute, using a "media query" syntax, such as the following:

<img ngSrc="cat.jpg" width="400" height="200" sizes="(max-width: 768px) 100vw, 50vw">

The sizes attribute in the above example says "I expect this image to be 100 percent of the screen width on devices under 768px wide. Otherwise, I expect it to be 50 percent of the screen width.

For additional information about the sizes attribute, see web.dev or mdn.

Configuring an image loader for NgOptimizedImage

A "loader" is a function that generates an image transformation URL for a given image file. When appropriate, NgOptimizedImage sets the size, format, and image quality transformations for an image.

NgOptimizedImage provides both a generic loader that applies no transformations, as well as loaders for various third-party image services. It also supports writing your own custom loader.

Loader type Behavior
Generic loader The URL returned by the generic loader will always match the value of src. In other words, this loader applies no transformations. Sites that use Angular to serve images are the primary intended use case for this loader.
Loaders for third-party image services The URL returned by the loaders for third-party image services will follow API conventions used by that particular image service.
Custom loaders A custom loader's behavior is defined by its developer. You should use a custom loader if your image service isn't supported by the loaders that come preconfigured with NgOptimizedImage.

Based on the image services commonly used with Angular applications, NgOptimizedImage provides loaders preconfigured to work with the following image services:

Image Service Angular API Documentation
Cloudflare Image Resizing provideCloudflareLoader Documentation
Cloudinary provideCloudinaryLoader Documentation
ImageKit provideImageKitLoader Documentation
Imgix provideImgixLoader Documentation

To use the generic loader no additional code changes are necessary. This is the default behavior.

Built-in Loaders

To use an existing loader for a third-party image service, add the provider factory for your chosen service to the providers array. In the example below, the Imgix loader is used:

providers: [ provideImgixLoader('https://my.base.url/'), ],

The base URL for your image assets should be passed to the provider factory as an argument. For most sites, this base URL should match one of the following patterns:

You can learn more about the base URL structure in the docs of a corresponding CDN provider.

Custom Loaders

To use a custom loader, provide your loader function as a value for the IMAGE_LOADER DI token. In the example below, the custom loader function returns a URL starting with https://example.com that includes src and width as URL parameters.

providers: [ { provide: IMAGE_LOADER, useValue: (config: ImageLoaderConfig) => { return `https://example.com/images?src=${config.src}&width=${config.width}`; }, }, ],

A loader function for the NgOptimizedImage directive takes an object with the ImageLoaderConfig type (from @angular/common) as its argument and returns the absolute URL of the image asset. The ImageLoaderConfig object contains the src and width properties.

Note: a custom loader must support requesting images at various widths in order for ngSrcset to work properly.

@reviewed 2022-11-07