Custom modal / alert (with HTML, form...)

You can try it out if you want to find that out :wink: If you want to define a custom inset modal just use some custom css as @webtalk suggests.

.modal-wrapper {
position: absolute;
top: 80px;
left: 45px;
display: block;
width: 70%;
height: 62%;
}

Or just add a padding to ion-modal and add a background to see a nice backdrop:

ion-modal {
padding: 30px;
background: rgba(0,0,0,0.7)
}

3 Likes

can you provide something more than css, for zero-start beginners?

I’ve tried both of the proposed CSS solutions, and they both seem to prevent enableBackdropDismiss from working on phones. I think the padding is making the ion-backdrop unreachable, but I don’t know how to fix this. Any ideas?

1 Like

You have found a solution to this??

any update on this :slight_smile:

1 Like

My solution to this:

import { Renderer } from '@angular/core';
import { ModalController, NavParams, ViewController } from 'ionic-angular';

@Component(...)
class HomePage {

  constructor(
    public modalCtrl: ModalController
  ) { }

  presentProfileModal() {
    let profileModal = this.modalCtrl.create(Profile, { userId: 8675309 });
    profileModal.present();
  }

}

@Component(...)
class Profile {

  constructor(
    params: NavParams,
    public renderer: Renderer,
    public viewCtrl: ViewController
  ) {
    this.renderer.setElementClass(viewCtrl.pageRef().nativeElement, 'my-popup', true);
    console.log('UserId', params.get('userId'));
  }

}

Add this to your scss:

ion-modal.my-popup {
  @media (min-width: 300px) and (min-height: 500px) {
    ion-backdrop {
      visibility: visible;
    }
  }

  .modal-wrapper {
    position: absolute;
    overflow: hidden;
    max-width: 280px;
    border-radius: 2px;
    width: 80vw;
    height: 50vh;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    border: 0;
    box-shadow: 0 16px 20px rgba(0,0,0,.4);
    background-color: #fafafa;
  }
}

Or this css, which will propose dynamic height:

ion-modal.my-popup {
  @media (min-height: 500px) {
    ion-backdrop {
      visibility: visible;
    }
  }

  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: $z-index-overlay;

  display: flex;

  align-items: center;
  justify-content: center;

  contain: strict;
  .modal-wrapper {
    &,
    .ion-page,
    .ion-page .content,
    .ion-page .content .scroll-content {
      contain: content;
      position: relative;
      top: auto;
      left: auto;
    }

    z-index: $z-index-overlay-wrapper;
    display: flex;
    overflow: hidden;

    flex-direction: column;

    min-width: $alert-min-width;
    max-height: $alert-max-height;

    opacity: 0;

    height: auto;
    max-width: $alert-md-max-width;
    border-radius: $alert-md-border-radius;
    background-color: $alert-md-background-color;
    box-shadow: $alert-md-box-shadow;

    .ion-page .content {
      background-color: color($colors, light);
    }
  }
}

I just set a class to modal element when it is called and change the style.

  • The modal implementation source is based in the official API ModalController
15 Likes

Hey @rodolfosilva this worked like a charm. I have a question though, Do you know how can I disable the click on the back drop, thank you!

Thanks :smile: .

Yes, when you create the modal, you need to pass a parameter with enableBackdropDismiss = false.

Check this link:

Any idea on how to do i get the content right. I want the modal window to be as big as my content. Here is the screen shot of how am i currently having it.

The modal has too many white spaces and blank lines at the bottom.

Here is the code of modal page:

<ion-content padding class="guide-modal">
    <div>
      <p>SUPER!!!!</p>
      <p>Some Gyan First!</p>
      <p>We preach sustainable weight loss - max 1 </p>
      <p>kg of weight loss a week is healthy and </p>
      <p>tha is exactly what we would help you </p>
      <p>acheive :)</p>
      <button ion-button (click)="setGyanInput()">Hmmm, that's the right way</button>
    </div>
</ion-content>

And the SCSS is as:

page-guide {
    .guide-modal .modal{
        $modal-inset-min-width:0;
        $modal-inset-min-height-small:0;
        display: flex;
        height: auto;
    }
}

How to make border
I add border and border-radius, but it not working

The result:

Try add the css property:

overflow: hidden;

Hi, my background alpha compositing does not work, any ideas? THANK YOU
This is my css.
image
And this is result

How did you achieve the rounded corners? Mine doesn’t have round corners. border-radiusapplies the corners to the background, not the modal itself…

ion-modal
{
padding: 30px;
background: rgba(0,0,0,0.5);
border-radius: 25px;
}

If you try to style the entire ion-modal, thats pretty self explanatory. add the border to the content of the page itself, ie the header and the content and or footer. Just use yor browser inspector to find out which styles you have to give a border radius :slight_smile:

Can you please share the scss file I am facing the same issue as you

To style just one modal component (and not all modals in the ionic app), you can use this code:

modal {
    background-color: rgba(0, 0, 0, 0.5);
    ion-content.content{
        top: 10%;
        left: 10%;

        width: 80%;
        height: 80%;
        border-radius: 20px;
        .scroll-content {
            border-radius: 20px;
        }
    }
}
1 Like

cool @oopets, thx for your solution.

I modified your code like following to have a modal customized for iOS and Android:

modal {
    ion-content {
        &.content {
            div.scroll-content {
                top: 10%;
                left: 10%;
                width: 80%;
                height: 80%;
                overflow:hidden;
            }
        }

        &.content-ios {
            background-color: rgba(0, 0, 0, 0.3);

            div.scroll-content {
                background-color: #f8f8f8;
                border-radius: 13px;
                padding: 16px;
            }
        }

        &.content-md {
            background-color: rgba(0, 0, 0, 0.5);
            
            div.scroll-content {
                background-color: #fafafa;
                border-radius: 2px;
                box-shadow: 0 16px 20px rgba(0, 0, 0, 0.4);
                padding: 24px;
            }
        }
    }
}
3 Likes

Furthermore to the css, I think the transition should be updated too, because otherwise, the modal still gonna be displayed with a transition “bottom-to-top” inclusive a moving background which, I think, is quite ugly.

Since I tried hours to figure out a nice solution, here’s how to implement an “modal alert style transition” (thx to @onderceylan which explain how to build a custom transition, see Adding custom transitions/custom modal transition)

Basically following transition is a mix of:

  • Modal transition to select the element wrapper (ionic/src/components/modal/modal-transitions.ts)
  • Alert transition for the effect opacity itself (ionic/src/components/alert/alert-transitions.ts)

Here we go, create a new class, like my-special-transition.ts containing following:

    import {Animation, Transition} from 'ionic-angular';
    
    export class ModalAlertPopIn extends Transition {
        init() {
            super.init();
    
            const ele: HTMLElement = this.enteringView.pageRef().nativeElement;
            const backdropEle = ele.querySelector('ion-backdrop');
            const backdrop = new Animation(this.plt, backdropEle);
            const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper'));
    
            wrapper.fromTo('opacity', 0.01, 1).fromTo('scale', 1.1, 1);
            backdrop.fromTo('opacity', 0.01, 0.3);

            this
            .easing('ease-in-out')
            .duration(200)
            .add(backdrop)
            .add(wrapper);
        }
    }
    
    export class ModalAlertPopOut extends Transition {
        init() {
        super.init();
    
        const ele: HTMLElement = this.leavingView.pageRef().nativeElement;
        let backdrop = new Animation(this.plt, ele.querySelector('ion-backdrop'));
        let wrapperEle = <HTMLElement>ele.querySelector('.modal-wrapper');
        let wrapper = new Animation(this.plt, wrapperEle);

        wrapper.fromTo('opacity', 0.99, 0).fromTo('scale', 1, 0.9);
        backdrop.fromTo('opacity', 0.3, 0);

        this
            .easing('ease-in-out')
            .duration(200)
            .add(backdrop)
            .add(wrapper);
    }
}
    
    export class ModalAlertMdPopIn extends Transition {
        init() {
            super.init();
    
            const ele: HTMLElement = this.enteringView.pageRef().nativeElement;
            const backdrop = new Animation(this.plt, ele.querySelector('ion-backdrop'));
            const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper'));
    
            wrapper.fromTo('opacity', 0.01, 1).fromTo('scale', 1.1, 1);
            backdrop.fromTo('opacity', 0.01, 0.5);
    
            this
                .easing('ease-in-out')
                .duration(200)
                .add(backdrop)
                .add(wrapper);
            }
        }
    
    export class ModalAlertMdPopOut extends Transition {
        init() {
            super.init();

            const ele: HTMLElement = this.leavingView.pageRef().nativeElement;
            const backdrop = new Animation(this.plt, ele.querySelector('ion-backdrop'));
            const wrapper = new Animation(this.plt, ele.querySelector('.modal-wrapper'));
    
            wrapper.fromTo('opacity', 0.99, 0).fromTo('scale', 1, 0.9);
            backdrop.fromTo('opacity', 0.5, 0);
    
            this
                .easing('ease-in-out')
                .duration(200)
                .add(backdrop)
                .add(wrapper);
            }
    }

Then in your app.component.ts declare the new transitions, for example in your constructor:

let isAndroid: boolean = this.platform.is('android');
this.config.setTransition('modal-alert-pop-in', isAndroid ? ModalAlertMdPopIn : ModalAlertPopIn);
this.config.setTransition('modal-alert-pop-out', isAndroid ? ModalAlertMdPopOut : ModalAlertPopOut);

And finally, when you call your modal, just pass the custom transitions name

let modal: Modal = this.modalController.create(MyModal, {
                aParam: this.myParam
            },
            {
                enterAnimation: 'modal-alert-pop-in',
                leaveAnimation: 'modal-alert-pop-out'
            });


        modal.onDidDismiss(() => {
            // Nothing to do
        });

        modal.present();

Enjoy!

4 Likes

For the record, I just updated the above css to hide the over scroll in the modal (which seems to happens on android)

Thank you for providing this. You saved my time and it worked great :slight_smile:

1 Like