Skip to content

Commit

Permalink
docs(common): Refine NgOptimizedImage docs (#48035)
Browse files Browse the repository at this point in the history
Make several changes to the structure of the documentation, based on early feedback about the readability and usefulness of the docs.

PR Close #48035
  • Loading branch information
atcastle authored and thePunderWoman committed Nov 11, 2022
1 parent ec8b52a commit 954f700
Showing 1 changed file with 70 additions and 39 deletions.
109 changes: 70 additions & 39 deletions aio/content/guide/image-directive.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,52 @@

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](http://web.dev/lcp) image is prioritized by:
The directive ensures that the loading of the [Largest Contentful Paint (LCP)](http://web.dev/lcp) 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
* Automatically generating a `srcset` attribute
* Generating a [preload hint](https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload) if app is using SSR

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

* Uses [image CDN URLs to apply image optimizations](https://web.dev/image-cdns/#how-image-cdns-use-urls-to-indicate-optimization-options)
* Prevents layout shift by requiring `width` and `height`
* Warns if `width` or `height` have been set incorrectly
* Warns if the image will be visually distorted when rendered
* Using [image CDN URLs to apply image optimizations](https://web.dev/image-cdns/#how-image-cdns-use-urls-to-indicate-optimization-options)
* Preventing layout shift by requiring `width` and `height`
* Warning if `width` or `height` have been set incorrectly
* Warning if the image will be visually distorted when rendered

## Prerequisites
## Getting Started

1. You will need to import `NgOptimizedImage` from the `@angular/common` module into your application. The directive is defined as a [standalone directive](/guide/standalone-components), so components should import it directly.
2. Consider setting up an image loader. These steps are explained in the [Configuring an Image Loader](#configuring-an-image-loader-for-ngoptimizedimage) section.
#### Step 1: Import NgOptimizedImage

## Usage in a template
<code-example format="typescript" language="typescript">

### Overview
import { NgOptimizedImage } from '@angular/common'

To activate the `NgOptimizedImage` directive, replace your image's `src` attribute with `ngSrc`.
</code-example>

<code-example format="typescript" language="typescript">
The directive is defined as a [standalone directive](/guide/standalone-components), so components should import it directly.

&lt;img ngSrc="cat.jpg" width="400" height="200"&gt;
#### Step 2: (Optional) Set up a Loader

</code-example>
An image loader is not **required** in order to use NgOptimizedImage, but using one with an image CDN enables powerful performance features, including automatic `srcset`s for your images.

If you're using a [built-in third-party loader](#built-in-loaders), make sure to omit the base URL path from `src`, as that will be prepended automatically by the loader.
A brief guide for setting up a loader can be found in the [Configuring an Image Loader](#configuring-an-image-loader-for-ngoptimizedimage) section at the end of this page.

### Preventing layout shift
#### Step 3: Enable the directive

To prevent [image-related layout shifts](https://web.dev/css-web-vitals/#images-and-layout-shifts), the directive enforces that you set the `width` and `height` attributes for each image.
To activate the `NgOptimizedImage` directive, replace your image's `src` attribute with `ngSrc`.

* For responsive images, the `width` and `height` attributes should reflect
the [intrinsic size](https://developer.mozilla.org/en-US/docs/Glossary/Intrinsic_Size) of the image.
<code-example format="typescript" language="typescript">

* 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.
&lt;img ngSrc="cat.jpg"&gt;

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).
</code-example>

### Marking images as `priority`
If you're using a [built-in third-party loader](#built-in-loaders), make sure to omit the base URL path from `src`, as that will be prepended automatically by the loader.

#### Step 4: Mark images as `priority`

Always mark the [LCP image](https://web.dev/lcp/#what-elements-are-considered) on your page as `priority` to prioritize its loading.

Expand All @@ -64,47 +65,77 @@ 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’s 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](https://web.dev/css-web-vitals/#images-and-largest-contentful-paint-lcp) for more details.

### Adding resource hints
#### Step 5: Include Height and Width

You can add a [`preconnect` resource hint](https://web.dev/preconnect-and-dns-prefetch) 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.
In order to prevent [image-related layout shifts](https://web.dev/css-web-vitals/#images-and-layout-shifts), NgOptimizedImage requires that you specify a height and width for your image, as follows:

<code-example format="html" language="html">
<code-example format="typescript" language="typescript">

&lt;link rel="preconnect" href="https://my.cdn.origin" /&gt;
&lt;img ngSrc="cat.jpg" width="400" height="200"&gt;

</code-example>

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:

<code-example format="typescript" language="typescript">
For **responsive images** (images which you've styled to grow and shrink relative to the viewport), the `width` and `height` attributes should be the instrinsic size of the image file.

providers: [
{provide: PRECONNECT_CHECK_BLOCKLIST, useValue: 'https://your-domain.com'}
],
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.

</code-example>
Note: If you don't know the size of your images, consider using "fill mode" to inherit the size of the parent container, as described below:

### 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.
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. It can also be helpful when you don't know the exact width and height of your image, but you do have a parent container with a known size that you'd like to fit your image into (see "object-fit" below).

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:

<code-example format="typescript" language="typescript">

&lt;img ngSrc="cat.jpg" fill&gt;

</code-example>
</code-example>

You can use the [obect-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property to change how the image will fill its container. If you style your image with `object-fit: "contain"`, the image will maintain its aspect ratio and be "letterboxed" to fit the element. If you set `object-fit: "cover"`, the element will retain its aspect ratio, fully fill the element, and some content may be "cropped" off.

See visual examples of the above at the [MDN object-fit documentation.](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit)

You can also style your image with the [object-position property](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) to adjust its position within its containing element.

**Important note:** For the "fill" image to render properly, its parent element **must** be styled with `position: "relative"`, `position: "fixed"`, or `position: "absolute"`.

### 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](https://web.dev/patterns/web-vitals-patterns/images/img-tag).

### Requesting images at the correct size
If the `height` and `width` attribute on the image are preventing you from sizing the image the way you want with CSS, consider using "fill" mode instead, and styling the image's parent element.

## Performance Features

NgOptimizedImage includes a number of features designed to improve loading performance in your app. These features are described in this section.

### Add resource hints

You can add a [`preconnect` resource hint](https://web.dev/preconnect-and-dns-prefetch) 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.

<code-example format="html" language="html">

&lt;link rel="preconnect" href="https://my.cdn.origin" /&gt;

</code-example>

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:

<code-example format="typescript" language="typescript">

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

</code-example>

### Request images at the correct size with automatic `srcset`

Defining a [`srcset` attribute](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/srcset) 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](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/sizes) on the image tag.

Expand Down

0 comments on commit 954f700

Please sign in to comment.