← All articles

Implementing a Half Modal in Ionic/Angular

CSS and ModalController options for half-height modals, backdrop on stacked modals, and expanding to full screen when the keyboard opens.

Published
Implementing a Half Modal in Ionic/Angular cover image

This article is part of the Ionic Framework / Capacitor Advent Calendar 2020.


The "half modal" you sometimes see on iOS shows up more often lately—AirPods pairing screens, purchase confirmations, and the like.

※ I accidentally bought Gem Pack A when Touch ID fired while I was taking this screenshot—a funny story.

Modals differ from push navigation: you use them for work that is not continuous with the previous view. A full-screen modal hides what was underneath; a half modal makes it clear you are pausing work while the previous view remains visible. Let us implement this in Ionic/Angular.

The Simplest Half Modal

First, add CSS for half-modal in a globally applied stylesheet such as global.scss.

.half-modal {
  align-items: flex-end;

  .modal-wrapper {
    height: 400px !important;
  }
  
  ion-header ion-toolbar:first-of-type {
    padding-top: 0;
  }
}

ion-app is display: flex, so the half modal as its child aligns to the bottom with align-items: flex-end;. Give the wrapper a height of 400px. ion-header ion-toolbar:first-of-type prevents iOS from automatically changing padding-top on ion-header ion-toolbar when using Cordova/Capacitor.

Assign this class when presenting the modal. Half modals feel better when they can be dismissed with a swipe, so enable swipeToClose too.

const modal = await this.modalCtrl.create({
  component: ModalPage,
  cssClass: ['half-modal'],
  swipeToClose: true,
});
await modal.present();

Simple enough.

Showing a Half Modal Over a Full Modal

Often you show a half modal on top of a full modal—so you do not stack full modals and confuse the user. With the approach above, the half modal may not show a backdrop behind it.

In Ionic, when you present more than one modal, later ones sit on top of the first. Stacked semi-transparent backdrops would compound opacity and darken the screen, so Ionic prevents that.

For a half modal, force the backdrop to show even on the second modal with CSS:

  .half-modal {
    align-items: flex-end;

    .modal-wrapper {
      height: 400px !important;
    }

    ion-header ion-toolbar:first-of-type {
      padding-top: 0;
    }
  
+   ion-backdrop {
+     --backdrop-opacity: var(--ion-backdrop-opacity, 0.4);
+   }
  }

Now the half modal has a backdrop behind it. Handy.

Expanding a Half Modal to Full Screen When the Keyboard Opens

On mobile, the keyboard can take nearly a third of the screen, which makes a half modal awkward. Ideally you avoid combining keyboard input with a half modal in the UI—but when you must, let it rise with the keyboard.

First, animate height changes on .half-modal. Temporarily set the modal height to 100% and restore the default padding-top on ion-header ion-toolbar.

  .half-modal {
    align-items: flex-end;

    .modal-wrapper {
 +    transition: height 420ms;
      height: 400px !important;
    }

    ion-header ion-toolbar:first-of-type {
      padding-top: 0;
    }
  
    ion-backdrop {
      --backdrop-opacity: var(--ion-backdrop-opacity, 0.4);
    }
    
+   &.half-modal-keyboard {
+     .modal-wrapper {
+       height: 100% !important;
+     }
+
+     ion-header ion-toolbar:first-of-type {
+       padding-top: var(--ion-safe-area-top, 0);
+     }
    }
  }

When the keyboard opens, add .half-modal-keyboard; when it closes, remove it. That switches between half and full modal as the keyboard appears.

It looks like this.

Simple enough. See you next time.