Bottom Sheet Modal behaves differently on different devices + doesn’t resize with keyboard

Hey everyone,

I’m building a small bottom-sheet style modal in Ionic React that contains an <IonInput> and should open cleanly above the keyboard. On some devices it looks perfect, and on others it behaves completely differently especially when the keyboard is open.

What I’m trying to achieve

A modal that:

  • opens as a compact bottom sheet

  • has rounded corners

  • autofocuses the input

  • shifts up with the keyboard

  • uses a small breakpoint like 0.22 so it stays tight and minimal

Basically a consistent “native iOS input sheet” style.


The issues

Across different devices (Android phones, iPhones, tablets), the modal behaves inconsistently:

1. The breakpoint height changes drastically between devices.
initialBreakpoint={0.22} looks perfect on smaller screens, but becomes very tall on larger screens, losing the “bottom sheet” look.

2. When the keyboard opens, the modal does not resize.
It leaves a large empty area above the keyboard instead of adjusting.

3. Even with:

Keyboard: {
  resize: KeyboardResize.Body
}

…the modal still does not react to keyboard height changes.


My question

Is there a recommended or official way to make an Ionic modal behave like a consistent, keyboard-aware bottom sheet across ALL device sizes?

Or maybe a different component I should be using?

Or is this just a current limitation of the modal + breakpoint system?

Any guidance or examples are appreciated.


Here’s my current code (simplified):

import {
  IonButton,
  IonButtons,
  IonContent,
  IonHeader,
  IonIcon,
  IonInput,
  IonModal,
  IonToolbar,
} from "@ionic/react";
import React, { useRef } from "react";
import { listOutline, calendarNumberOutline } from "ionicons/icons";
import "../theme/RevisionedAddTask.css";

type Props = {
  modal: React.RefObject<HTMLIonModalElement | null>;
  setShowAddModal: (t: boolean) => void;
  showAddModal: boolean;
};

const RevisionedAddTask: React.FC<Props> = ({
  modal,
  showAddModal,
  setShowAddModal,
}) => {
  const inputRef = useRef<HTMLIonInputElement>(null);

  return (
    <IonModal
      ref={modal}
      isOpen={showAddModal}
      initialBreakpoint={0.22}
      onWillPresent={() => console.log("Modal will present")}
      onDidPresent={() => {
        console.log("Modal did present – focusing input");
        inputRef.current?.setFocus();
      }}
      onDidDismiss={({ detail }) => {
        setShowAddModal(false);
        console.log(`Dismissed with role: ${detail.role}`);
      }}
      showBackdrop={true}
      handle={false}
      animated={false}
      className="keyboard-shift rounded-modal"
    >
      <IonContent
        onMouseDown={(e) => e.preventDefault()}
        onTouchStart={(e) => e.preventDefault()}
        className="ion-padding no-scroll"
      >
        <IonInput
          ref={inputRef}
          aria-label="Custom input"
          placeholder="Task label"
          counter={true}
          maxlength={30}
          shape="round"
        />

        <IonButtons>
          <IonButton size="small" fill="clear" shape="round" className="transparent-button">
            <IonIcon slot="icon-only" icon={listOutline} />
          </IonButton>

          <IonButton size="small" fill="clear" shape="round" className="transparent-button">
            <IonIcon slot="icon-only" icon={calendarNumberOutline} />
          </IonButton>

          <IonButton fill="clear" className="bottom-right">
            Save
          </IonButton>
        </IonButtons>
      </IonContent>
    </IonModal>
  );
};

export default RevisionedAddTask;

Thanks!

I’m sharing examples of how the layout changes across different devices when using the same code. Just to clarify I’m referring to the modal’s height, not its width.

Some modals are higher in height than others

Hey Benji,

I’ve run into similar issues with Ionic modals + keyboard behavior across devices. A few thoughts that might help:

  1. Use keyboardResize on the IonContent instead of the global config – sometimes the global KeyboardResize.Body doesn’t propagate correctly to the modal:
<IonContent fullscreen keyboardResize="ionic" ...>

The "ionic" option is more consistent across devices.

  1. Listen to keyboard events – you can manually adjust the modal height based on keyboardWillShow and keyboardWillHide events from @ionic/react-hooks/keyboard or Capacitor’s Keyboard plugin:
import { useKeyboard } from '@ionic/react-hooks/keyboard';

const { keyboardHeight } = useKeyboard();

Then adjust the modal style.height dynamically or use a custom CSS variable for your breakpoint.

  1. Custom CSS for dynamic height – since initialBreakpoint is static, you could override it using a CSS variable based on viewport height:
.rounded-modal {
  --height: calc(22vh - var(--keyboard-height, 0px));
}

Update --keyboard-height dynamically via JS when the keyboard opens.

  1. Consider IonBottomSheet alternatives – some devs use a combination of IonPopover or a full-screen modal with custom rounded corners and manual drag handling to mimic a bottom sheet, giving you full control over keyboard shifts.

Basically, the default breakpoint + modal system isn’t fully responsive to keyboards across all devices, so a bit of manual adjustment is usually required.