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

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

Thank you very much.

1 Like

is there a way to make the animations default for modal?

enterAnimation: 'modal-alert-pop-in',
leaveAnimation: 'modal-alert-pop-out'

i just dont feel good in writng the same thing all over the app.

I don’t know how it would be possible to make it default. I guess you could use abstract classes or components

I need to implement faceted filter search in my project. the concept of this search is that user can see background page where results are updated once they tick a filter or type other keywords. the search refined that way.

I am not sure what to use to do this, is having a modal page as the search page with filters opening like a sliding menu to achieve this ?? or maybe use the dual feature menu , the one that slide from right or any other means to accomplish this if its possible?

I am looking for some advice , thanx

Bro i use your code but im getting a darker background on .fixed-content do you know what im doing wrong?

I faced recently something like this too on iPad due to the last Ionic css changes inside the framework.

For my app I solved it like following, don’t know if it will solve your problem, but it deserve a try I guess:

1- Add a css class attribute to your modal (note: you could also not set an attribute and use !important in your css but I don’t like that, I rather set a style)

let modal: Modal = this.modalController.create(MyModal, {
            aParam: this.myParam
        },
        {
            enterAnimation: 'modal-alert-pop-in',
            leaveAnimation: 'modal-alert-pop-out',
            cssClass: 'my-modal' // <---- HERE the new attribute
        });

2- In the css, set the box-shadow to none. Pay attention, set it outside your component, that’s why pay attention to use a unique css class attribute name

your-component {
}

ion-modal {
  &.my-modal {
    div.modal-wrapper {
        box-shadow: none; // <---- This was the shadow I faced
    }
 }

Ahh i tried but did not work, i will keep trying! Thank you for your time :slight_smile:

1 Like

Ok if someone find the same problem this is how i solved with @reedrichards help.

page-modal-add-qty {

ion-content {
    &.content {
        div.scroll-content {
            top: 10%;
            left: 10%;
            width: 80%;
            height: 30%;
            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: inherit;
        
        div.scroll-content {
            background-color: #fafafa;
            border-radius: 2px;
            box-shadow: 0 16px 20px rgba(0, 0, 0, 0.4);
            padding: 24px;
        }
    }
}

}

ion-modal {
&.my-modal {
div.modal-wrapper {
box-shadow: none; // <---- This was the shadow I faced
}
}}

2 Likes

congrats for finding your solution @lucasarts321!

Just my 2cts here, but wouldnt it be a better option to override sass variables on inset dimensions and border radius for some of the issues mentioned?

I have set inset dimensions to 90% in my project and works like a charm on tablets. Same for popover.

But then all your modal have the same size.

Furthermore having a custom modal allows you to put more than “just” text and a default button in a modal. For example in my case I needed a title, subtitle, slides with images, text, custom button etc.

Depends on the business need I guess…

1 Like