diff --git a/docs/api/accordion.md b/docs/api/accordion.md index 62e1f4f796..475b11b710 100644 --- a/docs/api/accordion.md +++ b/docs/api/accordion.md @@ -190,11 +190,11 @@ When used inside an `ion-accordion-group`, `ion-accordion` has full keyboard sup 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. -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: +For example, lazily loading images may cause layout shifts as they load. As the animation plays, a lazily loaded image (such as a native `` 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: -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. +1. Load images eagerly by omitting `loading="lazy"`. An `` 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. -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! +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 `` using its attributes or CSS. This gives you the benefit of lazy loading while avoiding layout shifts. 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). diff --git a/docs/api/img.md b/docs/api/img.md index e166024449..a36892e8d3 100644 --- a/docs/api/img.md +++ b/docs/api/img.md @@ -11,13 +11,16 @@ import Slots from '@ionic-internal/component-api/v9/img/slots.md'; ion-img: Img Tag to Lazy Load Images in Viewport - + import EncapsulationPill from '@components/page/api/EncapsulationPill'; +:::warning Deprecated +`ion-img` is deprecated and will be removed in Ionic 10. Use a native `` 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. +::: 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. @@ -43,4 +46,4 @@ import Basic from '@site/static/usage/v9/img/basic/index.md'; ## Slots - \ No newline at end of file + diff --git a/docs/reference/browser-support.md b/docs/reference/browser-support.md index bd4d7a07a8..0cae130d9a 100644 --- a/docs/reference/browser-support.md +++ b/docs/reference/browser-support.md @@ -18,6 +18,7 @@ In pursuit of [adaptive styling](../core-concepts/fundamentals.md#adaptive-styli | Framework | Android | iOS | | :-------: | :--------------------: | :---: | +| Ionic v9 | 5.1+ with Chromium 89+ | 16.0+ | | Ionic v8 | 5.1+ with Chromium 89+ | 15.0+ | | Ionic v7 | 5.1+ with Chromium 79+ | 14.0+ | | 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 Ionic supports the following browsers: -| Browser | Ionic v8 | Ionic v7 | Ionic v6 | Ionic v5 | Ionic v4 | -| :---------: | :------: | :------: | :------: | :------: | :------: | -| **Chrome** | 89+ | 79+ | 60+ | ✔ | ✔ | -| **Safari** | 15+ | 14+ | 13+ | ✔ | ✔ | -| **Edge** | 89+ | 79+ | 79+ | 79+ | ✔ | -| **Firefox** | 75+ | 70+ | 63+ | ✔ | ✔ | -| **IE 11** | **X** | **X** | **X** | **X** | **X** | +| Browser | Ionic v9 | Ionic v8 | Ionic v7 | Ionic v6 | Ionic v5 | Ionic v4 | +| :---------: | :------: | :------: | :------: | :------: | :------: | :------: | +| **Chrome** | 89+ | 89+ | 79+ | 60+ | ✔ | ✔ | +| **Safari** | 16+ | 15+ | 14+ | 13+ | ✔ | ✔ | +| **Edge** | 89+ | 89+ | 79+ | 79+ | 79+ | ✔ | +| **Firefox** | 75+ | 75+ | 70+ | 63+ | ✔ | ✔ | +| **IE 11** | **X** | **X** | **X** | **X** | **X** | **X** | diff --git a/docs/updating/9-0.md b/docs/updating/9-0.md index 035929d198..a309990728 100644 --- a/docs/updating/9-0.md +++ b/docs/updating/9-0.md @@ -411,6 +411,23 @@ The `exports` field defines the supported public entry points, and imports of pa Apps on `moduleResolution: "node"` (classic) and webpack 4 keep resolving through the legacy fields and need no changes. +## Required Changes + +### Browser Support + +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. + +If you have a `browserslist` or `.browserslistrc` file, update it with the following content: + +``` +Chrome >=89 +ChromeAndroid >=89 +Firefox >=75 +Edge >=89 +Safari >=16 +iOS >=16 +``` + ### Legacy Picker 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 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. +### Img + +`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 `` element, so the component is no longer needed. + +Replace `ion-img` with a native `` 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: + +```diff +- ++ Description +``` + +#### Events + +The native `` element does not emit Ionic's custom events. Use the standard DOM events instead: + +| `ion-img` event | Native `` replacement | +| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `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). | +| `ionImgDidLoad` | [`load`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/load_event)¹ | +| `ionError` | [`error`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/error_event)¹ | + +¹ 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 `` instead, or use the capture phase: `parent.addEventListener('load', handler, true)`. + +#### Styling + +`ion-img` exposed an `image` CSS shadow part for styling the inner image. With a native ``, style the element directly instead: + +```diff +- ion-img::part(image) { +- border-radius: 8px; +- } ++ img { ++ border-radius: 8px; ++ } +``` + ### Input 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.