Skip to content

Commit 63d34b9

Browse files
docs(img): deprecate ion-img and update migration guide to reflect this (#4565)
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
1 parent 586ea6e commit 63d34b9

40 files changed

Lines changed: 235 additions & 306 deletions

docs/api/accordion.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,11 @@ When used inside an `ion-accordion-group`, `ion-accordion` has full keyboard sup
190190

191191
The accordion animation works by knowing the height of the `content` slot when the animation starts. The accordion expects that this height will remain consistent throughout the animation. As a result, developers should avoid performing any operation that may change the height of the content during the animation.
192192

193-
For example, using [ion-img](./img) may cause layout shifts as it lazily loads images. This means that as the animation plays, `ion-img` will load the image data, and the dimensions of `ion-img` will change to account for the loaded image data. This can result in the height of the `content` slot changing. Developers have a few options for avoiding this:
193+
For example, lazily loading images may cause layout shifts as they load. As the animation plays, a lazily loaded image (such as a native `<img>` with `loading="lazy"`) loads its data and changes its dimensions to fit, which can change the height of the `content` slot. Developers have a few options for avoiding this:
194194

195-
1. Use an `img` element without any lazy loading. `ion-img` always uses lazy loading, but `img` does not use lazy loading by default. This is the simplest option and works well if you have small images that do not significantly benefit from lazy loading.
195+
1. Load images eagerly by omitting `loading="lazy"`. An `<img>` does not lazy load by default, so the image loads up front instead of during the animation. This is the simplest option and works well if you have small images that do not significantly benefit from lazy loading.
196196

197-
2. Set a minimum width and height on `ion-img`. If you need to use lazy loading and know the dimensions of the images ahead of time (such as if you are loading icons of the same size), you can set the `ion-img` to have a minimum width or height using CSS. This gives developers the benefit of lazy loading while avoiding layout shifts. This works when using an `img` element with `loading="lazy"` too!
197+
2. Reserve space for the image ahead of time. If you need lazy loading and know the dimensions of the images (such as loading icons of the same size), set a width and height on the `<img>` using its attributes or CSS. This gives you the benefit of lazy loading while avoiding layout shifts.
198198

199199
3. If neither of these options are applicable, developers may want to consider disabling animations altogether by using the `animated` property on [ion-accordion-group](./accordion-group).
200200

docs/api/img.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@ import Slots from '@ionic-internal/component-api/v9/img/slots.md';
1111

1212
<head>
1313
<title>ion-img: Img Tag to Lazy Load Images in Viewport</title>
14-
<meta name="description" content="Img tag lazy loads images whenever the tag is in the viewport. Utilize this component when generating large lists—as images are only loaded when visible." />
14+
<meta name="description" content="The ion-img component lazily loads images as they enter the viewport. It is deprecated in favor of a native img tag with lazy loading." />
1515
</head>
1616

1717
import EncapsulationPill from '@components/page/api/EncapsulationPill';
1818

1919
<EncapsulationPill type="shadow" />
2020

21+
:::warning Deprecated
22+
`ion-img` is deprecated and will be removed in Ionic 10. Use a native `<img>` tag with [loading="lazy"](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img#loading) instead. Refer to the [migration guide](../updating/9-0.md#img) for details on replacing events and styling.
23+
:::
2124

2225
Img is a tag that will lazily load an image whenever the tag is in the viewport. This is extremely useful when generating a large list as images are only loaded when they're visible. The component uses [Intersection Observer](https://caniuse.com/#feat=intersectionobserver) internally, which is supported in most modern browsers, but falls back to a `setTimeout` when it is not supported.
2326

@@ -43,4 +46,4 @@ import Basic from '@site/static/usage/v9/img/basic/index.md';
4346
<CustomProps />
4447

4548
## Slots
46-
<Slots />
49+
<Slots />

docs/reference/browser-support.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ In pursuit of [adaptive styling](../core-concepts/fundamentals.md#adaptive-styli
1818

1919
| Framework | Android | iOS |
2020
| :-------: | :--------------------: | :---: |
21+
| Ionic v9 | 5.1+ with Chromium 89+ | 16.0+ |
2122
| Ionic v8 | 5.1+ with Chromium 89+ | 15.0+ |
2223
| Ionic v7 | 5.1+ with Chromium 79+ | 14.0+ |
2324
| Ionic v6 | 5.0+ with Chromium 60+ | 13.0+ |
@@ -38,10 +39,10 @@ To figure out what version of the webview a device is running, log `window.navig
3839

3940
Ionic supports the following browsers:
4041

41-
| Browser | Ionic v8 | Ionic v7 | Ionic v6 | Ionic v5 | Ionic v4 |
42-
| :---------: | :------: | :------: | :------: | :------: | :------: |
43-
| **Chrome** | 89+ | 79+ | 60+ |||
44-
| **Safari** | 15+ | 14+ | 13+ |||
45-
| **Edge** | 89+ | 79+ | 79+ | 79+ ||
46-
| **Firefox** | 75+ | 70+ | 63+ |||
47-
| **IE 11** | **X** | **X** | **X** | **X** | **X** |
42+
| Browser | Ionic v9 | Ionic v8 | Ionic v7 | Ionic v6 | Ionic v5 | Ionic v4 |
43+
| :---------: | :------: | :------: | :------: | :------: | :------: | :------: |
44+
| **Chrome** | 89+ | 89+ | 79+ | 60+ |||
45+
| **Safari** | 16+ | 15+ | 14+ | 13+ |||
46+
| **Edge** | 89+ | 89+ | 79+ | 79+ | 79+ ||
47+
| **Firefox** | 75+ | 75+ | 70+ | 63+ |||
48+
| **IE 11** | **X** | **X** | **X** | **X** | **X** | **X** |

docs/updating/9-0.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,23 @@ The `exports` field defines the supported public entry points, and imports of pa
411411

412412
Apps on `moduleResolution: "node"` (classic) and webpack 4 keep resolving through the legacy fields and need no changes.
413413

414+
## Required Changes
415+
416+
### Browser Support
417+
418+
The list of browsers that Ionic supports has changed. Review the [Browser Support Guide](../reference/browser-support) to ensure you are deploying apps to supported browsers.
419+
420+
If you have a `browserslist` or `.browserslistrc` file, update it with the following content:
421+
422+
```
423+
Chrome >=89
424+
ChromeAndroid >=89
425+
Firefox >=75
426+
Edge >=89
427+
Safari >=16
428+
iOS >=16
429+
```
430+
414431
### Legacy Picker
415432

416433
1. Remove any usages of the `ion-picker-legacy` and `ion-picker-legacy-column` components. These components have been removed in Ionic 9. The recommended path forward is to use `ion-picker` inside a modal. Review the [Picker in Modal documentation](../api/picker.md#picker-in-modal) for more information.
@@ -423,6 +440,42 @@ The `ionChange` event on `ion-select` now only fires when the value changes. Pre
423440

424441
If your code relied on `ionChange` firing on every confirmation (for example, to detect that the user closed the overlay without changing anything), listen for `ionDismiss` instead, or use the `didDismiss` event on the underlying alert or action sheet.
425442

443+
### Img
444+
445+
`ion-img` is deprecated and will be removed in Ionic 10. The component was created to lazy-load images before browsers supported lazy loading natively. Modern browsers now support the [`loading="lazy"`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img#loading) attribute on the native `<img>` element, so the component is no longer needed.
446+
447+
Replace `ion-img` with a native `<img>` tag. Add `loading="lazy"` for lazy loading, and `decoding="async"` to match the asynchronous decoding `ion-img` applied by default. The `alt` and `src` properties map directly to the native attributes of the same name:
448+
449+
```diff
450+
- <ion-img src="/assets/image.png" alt="Description"></ion-img>
451+
+ <img src="/assets/image.png" alt="Description" loading="lazy" decoding="async" />
452+
```
453+
454+
#### Events
455+
456+
The native `<img>` element does not emit Ionic's custom events. Use the standard DOM events instead:
457+
458+
| `ion-img` event | Native `<img>` replacement |
459+
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
460+
| `ionImgWillLoad` | No native equivalent. This fired when the image scrolled into view and lazy loading began. With native `loading="lazy"` the browser handles this internally. To know when an image is about to enter the viewport, use an [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver). |
461+
| `ionImgDidLoad` | [`load`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/load_event)¹ |
462+
| `ionError` | [`error`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/error_event)¹ |
463+
464+
¹ Native `load` and `error` do not bubble, while the Ionic events did. If you used event delegation (one listener on a parent), listen on each `<img>` instead, or use the capture phase: `parent.addEventListener('load', handler, true)`.
465+
466+
#### Styling
467+
468+
`ion-img` exposed an `image` CSS shadow part for styling the inner image. With a native `<img>`, style the element directly instead:
469+
470+
```diff
471+
- ion-img::part(image) {
472+
- border-radius: 8px;
473+
- }
474+
+ img {
475+
+ border-radius: 8px;
476+
+ }
477+
```
478+
426479
### Input
427480

428481
The `autocorrect` property on `ion-input` is now a `boolean` (default `false`) instead of `'on' | 'off'`. Because the attribute coerces to `true` for any value other than the string `"false"`, `autocorrect="off"` now enables autocorrect.

static/usage/v9/modal/card/basic/angular/example_component_html.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<ion-list>
2323
<ion-item>
2424
<ion-avatar slot="start">
25-
<ion-img src="https://i.pravatar.cc/300?u=b"></ion-img>
25+
<img src="https://i.pravatar.cc/300?u=b" alt="Portrait of Connor Smith" />
2626
</ion-avatar>
2727
<ion-label>
2828
<h2>Connor Smith</h2>
@@ -31,7 +31,7 @@
3131
</ion-item>
3232
<ion-item>
3333
<ion-avatar slot="start">
34-
<ion-img src="https://i.pravatar.cc/300?u=a"></ion-img>
34+
<img src="https://i.pravatar.cc/300?u=a" alt="Portrait of Daniel Smith" />
3535
</ion-avatar>
3636
<ion-label>
3737
<h2>Daniel Smith</h2>
@@ -40,7 +40,7 @@
4040
</ion-item>
4141
<ion-item>
4242
<ion-avatar slot="start">
43-
<ion-img src="https://i.pravatar.cc/300?u=d"></ion-img>
43+
<img src="https://i.pravatar.cc/300?u=d" alt="Portrait of Greg Smith" />
4444
</ion-avatar>
4545
<ion-label>
4646
<h2>Greg Smith</h2>
@@ -49,7 +49,7 @@
4949
</ion-item>
5050
<ion-item>
5151
<ion-avatar slot="start">
52-
<ion-img src="https://i.pravatar.cc/300?u=e"></ion-img>
52+
<img src="https://i.pravatar.cc/300?u=l" alt="Portrait of Zoey Smith" />
5353
</ion-avatar>
5454
<ion-label>
5555
<h2>Zoey Smith</h2>

static/usage/v9/modal/card/basic/angular/example_component_ts.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
IonButtons,
77
IonContent,
88
IonHeader,
9-
IonImg,
109
IonItem,
1110
IonLabel,
1211
IonList,
@@ -25,7 +24,6 @@ import {
2524
IonButtons,
2625
IonContent,
2726
IonHeader,
28-
IonImg,
2927
IonItem,
3028
IonLabel,
3129
IonList,

static/usage/v9/modal/card/basic/demo.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
<ion-list>
3535
<ion-item>
3636
<ion-avatar slot="start">
37-
<ion-img src="https://i.pravatar.cc/300?u=b" />
37+
<img src="https://i.pravatar.cc/300?u=b" alt="Portrait of Connor Smith" />
3838
</ion-avatar>
3939
<ion-label>
4040
<h2>Connor Smith</h2>
@@ -43,7 +43,7 @@ <h2>Connor Smith</h2>
4343
</ion-item>
4444
<ion-item>
4545
<ion-avatar slot="start">
46-
<ion-img src="https://i.pravatar.cc/300?u=a" />
46+
<img src="https://i.pravatar.cc/300?u=a" alt="Portrait of Daniel Smith" />
4747
</ion-avatar>
4848
<ion-label>
4949
<h2>Daniel Smith</h2>
@@ -52,7 +52,7 @@ <h2>Daniel Smith</h2>
5252
</ion-item>
5353
<ion-item>
5454
<ion-avatar slot="start">
55-
<ion-img src="https://i.pravatar.cc/300?u=d" />
55+
<img src="https://i.pravatar.cc/300?u=d" alt="Portrait of Greg Smith" />
5656
</ion-avatar>
5757
<ion-label>
5858
<h2>Greg Smith</h2>
@@ -61,7 +61,7 @@ <h2>Greg Smith</h2>
6161
</ion-item>
6262
<ion-item>
6363
<ion-avatar slot="start">
64-
<ion-img src="https://i.pravatar.cc/300?u=e" />
64+
<img src="https://i.pravatar.cc/300?u=l" alt="Portrait of Zoey Smith" />
6565
</ion-avatar>
6666
<ion-label>
6767
<h2>Zoey Smith</h2>

static/usage/v9/modal/card/basic/javascript.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<ion-list>
2222
<ion-item>
2323
<ion-avatar slot="start">
24-
<ion-img src="https://i.pravatar.cc/300?u=b" />
24+
<img src="https://i.pravatar.cc/300?u=b" alt="Portrait of Connor Smith" />
2525
</ion-avatar>
2626
<ion-label>
2727
<h2>Connor Smith</h2>
@@ -30,7 +30,7 @@
3030
</ion-item>
3131
<ion-item>
3232
<ion-avatar slot="start">
33-
<ion-img src="https://i.pravatar.cc/300?u=a" />
33+
<img src="https://i.pravatar.cc/300?u=a" alt="Portrait of Daniel Smith" />
3434
</ion-avatar>
3535
<ion-label>
3636
<h2>Daniel Smith</h2>
@@ -39,7 +39,7 @@
3939
</ion-item>
4040
<ion-item>
4141
<ion-avatar slot="start">
42-
<ion-img src="https://i.pravatar.cc/300?u=d" />
42+
<img src="https://i.pravatar.cc/300?u=d" alt="Portrait of Greg Smith" />
4343
</ion-avatar>
4444
<ion-label>
4545
<h2>Greg Smith</h2>
@@ -48,7 +48,7 @@
4848
</ion-item>
4949
<ion-item>
5050
<ion-avatar slot="start">
51-
<ion-img src="https://i.pravatar.cc/300?u=e" />
51+
<img src="https://i.pravatar.cc/300?u=l" alt="Portrait of Zoey Smith" />
5252
</ion-avatar>
5353
<ion-label>
5454
<h2>Zoey Smith</h2>

static/usage/v9/modal/card/basic/react.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
IonItem,
1414
IonLabel,
1515
IonAvatar,
16-
IonImg,
1716
} from '@ionic/react';
1817

1918
function Example() {
@@ -54,7 +53,7 @@ function Example() {
5453
<IonList>
5554
<IonItem>
5655
<IonAvatar slot="start">
57-
<IonImg src="https://i.pravatar.cc/300?u=b" />
56+
<img src="https://i.pravatar.cc/300?u=b" alt="Portrait of Connor Smith" />
5857
</IonAvatar>
5958
<IonLabel>
6059
<h2>Connor Smith</h2>
@@ -63,7 +62,7 @@ function Example() {
6362
</IonItem>
6463
<IonItem>
6564
<IonAvatar slot="start">
66-
<IonImg src="https://i.pravatar.cc/300?u=a" />
65+
<img src="https://i.pravatar.cc/300?u=a" alt="Portrait of Daniel Smith" />
6766
</IonAvatar>
6867
<IonLabel>
6968
<h2>Daniel Smith</h2>
@@ -72,7 +71,7 @@ function Example() {
7271
</IonItem>
7372
<IonItem>
7473
<IonAvatar slot="start">
75-
<IonImg src="https://i.pravatar.cc/300?u=d" />
74+
<img src="https://i.pravatar.cc/300?u=d" alt="Portrait of Greg Smith" />
7675
</IonAvatar>
7776
<IonLabel>
7877
<h2>Greg Smith</h2>
@@ -81,7 +80,7 @@ function Example() {
8180
</IonItem>
8281
<IonItem>
8382
<IonAvatar slot="start">
84-
<IonImg src="https://i.pravatar.cc/300?u=e" />
83+
<img src="https://i.pravatar.cc/300?u=l" alt="Portrait of Zoey Smith" />
8584
</IonAvatar>
8685
<IonLabel>
8786
<h2>Zoey Smith</h2>

static/usage/v9/modal/card/basic/vue.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<ion-list>
2323
<ion-item>
2424
<ion-avatar slot="start">
25-
<ion-img src="https://i.pravatar.cc/300?u=b"></ion-img>
25+
<img src="https://i.pravatar.cc/300?u=b" alt="Portrait of Connor Smith" />
2626
</ion-avatar>
2727
<ion-label>
2828
<h2>Connor Smith</h2>
@@ -31,7 +31,7 @@
3131
</ion-item>
3232
<ion-item>
3333
<ion-avatar slot="start">
34-
<ion-img src="https://i.pravatar.cc/300?u=a"></ion-img>
34+
<img src="https://i.pravatar.cc/300?u=a" alt="Portrait of Daniel Smith" />
3535
</ion-avatar>
3636
<ion-label>
3737
<h2>Daniel Smith</h2>
@@ -40,7 +40,7 @@
4040
</ion-item>
4141
<ion-item>
4242
<ion-avatar slot="start">
43-
<ion-img src="https://i.pravatar.cc/300?u=d"></ion-img>
43+
<img src="https://i.pravatar.cc/300?u=d" alt="Portrait of Greg Smith" />
4444
</ion-avatar>
4545
<ion-label>
4646
<h2>Greg Smith</h2>
@@ -49,7 +49,7 @@
4949
</ion-item>
5050
<ion-item>
5151
<ion-avatar slot="start">
52-
<ion-img src="https://i.pravatar.cc/300?u=e"></ion-img>
52+
<img src="https://i.pravatar.cc/300?u=l" alt="Portrait of Zoey Smith" />
5353
</ion-avatar>
5454
<ion-label>
5555
<h2>Zoey Smith</h2>
@@ -75,7 +75,6 @@
7575
IonItem,
7676
IonList,
7777
IonAvatar,
78-
IonImg,
7978
IonLabel,
8079
IonPage,
8180
} from '@ionic/vue';

0 commit comments

Comments
 (0)