Why Modal Views Need Careful Timing
Modal views are the right choice when you need to interrupt the user for something genuinely important. Because they block the entire interface, they are inherently disruptive; overusing them is one of the fastest ways to annoy your users. When you do use them, animating the entrance and exit can make the interruption feel less jarring.
Two timing principles help here. Bring the modal view on screen slowly enough that it does not surprise the user, but dismiss it quickly when they are done so they can get back to your app without waiting.
Setting Up the Overlay
The modal overlay must cover the viewport, so its position is fixed:
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
opacity: 0;
will-change: transform, opacity;
}
Several properties matter in this default state:
opacity: 0keeps it invisible.pointer-events: nonelets clicks and touches pass through when it is hidden. Without this, the invisible overlay would block the whole page.will-change: opacity, transformflags the properties you intend to animate so the browser can prepare for the work.
When the modal is shown, it needs to accept interaction and become fully visible:
.modal.visible {
pointer-events: auto;
opacity: 1;
}
Toggling the visible class from JavaScript turns the modal on and off:
modal.classList.add('visible');
Animating Entrance and Exit
The code so far simply snaps the view in and out. Adding a transition fixes that:
.modal {
transform: scale(1.15);
transition:
transform 0.1s cubic-bezier(0.465, 0.183, 0.153, 0.946),
opacity 0.1s cubic-bezier(0.465, 0.183, 0.153, 0.946);
}
Adding scale to the transform gives a drop-on effect. The transition here covers both opacity and transform, using a custom ease-out curve over 0.1 seconds.
That duration is short and aggressive; good for a dismissal, poor for an entrance. Override the transition when the visible class is applied so the entrance is gentler:
.modal.visible {
transform: scale(1);
transition:
transform 0.3s cubic-bezier(0.465, 0.183, 0.153, 0.946),
opacity 0.3s cubic-bezier(0.465, 0.183, 0.153, 0.946);
}
With this override, the modal appears over 0.3 seconds; slow enough to come across as deliberate. It still disappears in the fast 0.1 seconds, which is exactly what a user wants when dismissing it.



