Skip to main content

Ionic 9.0.0

Release Date: August 19, 2026

Ionic 9.0.0 is here — and before anyone gets carried away, this is a major version with a long list of breaking changes, released on August 19, 2026. It cleans up a lot of legacy, but it also removes things you were probably still using. Let's talk about what will actually hurt.

The Package Exports Allowlist Will Trip You Up

@ionic/core now declares an exports field in its package.json, and environments that use strict ESM resolution — Angular 21's default Vitest builder, raw Node, webpack 5, or TypeScript with moduleResolution: "bundler"/"node16"/"nodenext" — no longer resolve undocumented internal paths. `exports` is an allowlist. If you imported from an unlisted subpath, it breaks with ERR_UNSUPPORTED_DIR_IMPORT. Migrate to a supported subpath (@ionic/core/components, @ionic/core/loader, @ionic/core/hydrate, and so on) before upgrading. Apps on classic moduleResolution: "node" and webpack 4 are unaffected — for now.

ion-input Changed Underneath You

Three things on ion-input deserve your attention.

  • autocorrect is now a boolean, defaulting to false, rather than 'on' | 'off'. Because an HTML attribute coerces any non-empty string to true, the old autocorrect="off" now actually enables autocorrect. This is the kind of quiet footgun a major release loves to leave behind.
  • Floating labels changed behavior — they no longer float just because the input has slotted content; they float only when the input is focused or has a value.
  • The internal DOM was restructured with new .input-start, .input-control, and .input-end wrappers. If you targeted .input-wrapper .native-wrapper in your CSS, that selector path is gone and you will need to update it.

The Legacy Picker Is Dead

ion-picker-legacy, ion-picker-legacy-column, the pickerController, the React useIonPicker hook, and the associated PickerOptions/PickerButton/PickerColumn types are all removed. The inline ion-picker is the replacement. This is a forced migration, not an optional one.

ion-modal Handle Now Cycles By Default

The handleBehavior property on ion-modal now defaults to "cycle" instead of "none". That means sheet modal handles are now focusable and cycling through breakpoints — matching native iOS behavior and improving assistive-tech usability. It is also a behavior change. If you relied on the handle being inert, you must set handle-behavior="none" to keep the old behavior.

ion-nav No Longer Talks to the Router

ion-nav has been decoupled from ion-router. It is now a standalone imperative stack component driven only through root, push, pop, setRoot, and ion-nav-link. The router no longer discovers it, pushing/popping no longer updates the URL, and the internal setRouteId()/getRouteId() methods are gone. If you relied on ion-nav to drive the URL, swap it for ion-router-outlet. You can still keep an ion-nav inside a routed page for local, URL-less stacks.

Check Your Minimum Versions

Ionic 9 raises the floor across the stack: Chrome 89+, Safari 16+, Firefox 75+, Angular 18+, React 18 or 19, Vue 3.5+, iOS 16+, Android 5.1 with Chromium 89+, and Capacitor 7+. Notably, native platform detection no longer honors the Capacitor 2 isNative flag — apps on Capacitor 2 will report as web, so upgrade to a supported Capacitor version.

The Verdict

Ionic 9.0.0 is a genuine cleanup release — dropping legacy pickers, decoupling nav from routing, and modernizing package exports are all reasonable directions. But "reasonable direction" is cold comfort when you're mid-upgrade with broken selectors and a removed controller API. Budget real migration time, run the official migration guide, and test the sheet modal handle behavior, ion-input autocorrect, and any ion-nav-based flows on a branch before you touch production. It's a solid release — just don't freeform it.

What is New?

By continuing to use the site, you agree to the use of cookies.