22 CSS Transition Effects 11 / 22
Modal Open Close Transition
Six modal entrance animations: scale-in, slide-up, flip-in, bounce overshoot, slide-right and unfold, with backdrop-filter blur overlay.
This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.
The code
<div class="wrap">
<h1>Modal Transitions</h1>
<p class="sub">6 CSS transition effects for opening and closing modals — click each to preview</p>
<div id="animInfo" class="anim-info">Click any button below to open its modal variant</div>
<span class="sl">Open a modal</span>
<h2>6 entrance animations</h2>
<div class="grid">
<button class="trig-btn" style="--c:#059669" onclick="openModal('m1')">⬆ Scale in</button>
<button class="trig-btn" style="--c:#7c3aed" onclick="openModal('m2')">⬆ Slide up</button>
<button class="trig-btn" style="--c:#0ea5e9" onclick="openModal('m3')">↻ Flip in</button>
<button class="trig-btn" style="--c:#f97316" onclick="openModal('m4')">🎯 Bounce</button>
<button class="trig-btn" style="--c:#ec4899" onclick="openModal('m5')">→ Slide right</button>
<button class="trig-btn" style="--c:#d97706" onclick="openModal('m6')">⬇ Unfold</button>
</div>
</div>
<!-- Modal 1 — Scale in (success) -->
<div class="overlay" id="m1" onclick="if(event.target===this)closeModal('m1')">
<div class="modal m-scale">
<button class="mclose" onclick="closeModal('m1')">✕</button>
<div class="modal-type">Scale entrance</div>
<span class="modal-icon">✅</span>
<h3>Deployment complete</h3>
<p>Your application has been deployed to production successfully. All 4 health checks passed with zero downtime.</p>
<div class="modal-actions">
<button class="m-primary" onclick="closeModal('m1')">View deployment</button>
<button class="m-secondary" onclick="closeModal('m1')">Dismiss</button>
</div>
</div>
</div>
<!-- Modal 2 — Slide up (default) -->
<div class="overlay" id="m2" onclick="if(event.target===this)closeModal('m2')">
<div class="modal m-slideup">
<button class="mclose" onclick="closeModal('m2')">✕</button>
<div class="modal-type">Slide up entrance</div>
<span class="modal-icon">🚀</span>
<h3>Start your free trial</h3>
<p>Get full access to all Pro features for 14 days. No credit card required. Cancel any time.</p>
<div class="modal-actions">
<button class="m-primary" onclick="closeModal('m2')">Start free trial</button>
<button class="m-secondary" onclick="closeModal('m2')">Maybe later</button>
</div>
</div>
</div>
<!-- Modal 3 — Flip in (info) -->
<div class="overlay" id="m3" onclick="if(event.target===this)closeModal('m3')">
<div class="modal m-flip var-info">
<button class="mclose" onclick="closeModal('m3')">✕</button>
<div class="modal-type">Flip entrance</div>
<span class="modal-icon">ℹ️</span>
<h3>Update available</h3>
<p>Version 4.2.0 is ready to install. This update includes performance improvements and 3 bug fixes.</p>
<div class="modal-actions">
<button class="m-primary" onclick="closeModal('m3')">Install now</button>
<button class="m-secondary" onclick="closeModal('m3')">Remind later</button>
</div>
</div>
</div>
<!-- Modal 4 — Bounce -->
<div class="overlay" id="m4" onclick="if(event.target===this)closeModal('m4')">
<div class="modal m-bounce">
<button class="mclose" onclick="closeModal('m4')">✕</button>
<div class="modal-type">Bounce entrance</div>
<span class="modal-icon">🎉</span>
<h3>Congratulations!</h3>
<p>You've unlocked the Pro tier. All premium features are now active on your account.</p>
<div class="modal-actions">
<button class="m-primary" onclick="closeModal('m4')">Explore features</button>
<button class="m-secondary" onclick="closeModal('m4')">Close</button>
</div>
</div>
</div>
<!-- Modal 5 — Slide from right -->
<div class="overlay" id="m5" onclick="if(event.target===this)closeModal('m5')">
<div class="modal m-right var-err">
<button class="mclose" onclick="closeModal('m5')">✕</button>
<div class="modal-type">Slide right entrance</div>
<span class="modal-icon">⚠️</span>
<h3>Delete this workspace?</h3>
<p>This action cannot be undone. All projects, data and team members will be permanently removed.</p>
<div class="modal-actions">
<button class="m-primary" onclick="closeModal('m5')">Delete permanently</button>
<button class="m-secondary" onclick="closeModal('m5')">Cancel</button>
</div>
</div>
</div>
<!-- Modal 6 — Unfold -->
<div class="overlay" id="m6" onclick="if(event.target===this)closeModal('m6')">
<div class="modal m-unfold var-warn" style="max-width:480px">
<button class="mclose" onclick="closeModal('m6')">✕</button>
<div class="modal-type">Unfold entrance</div>
<span class="modal-icon">⚡</span>
<h3>Usage limit approaching</h3>
<p>You've used 89% of your monthly API quota. Upgrade to Pro to avoid service interruption.</p>
<div class="modal-actions">
<button class="m-primary" onclick="closeModal('m6')">Upgrade plan</button>
<button class="m-secondary" onclick="closeModal('m6')">Dismiss</button>
</div>
</div>
</div> <div class="wrap">
<h1>Modal Transitions</h1>
<p class="sub">6 CSS transition effects for opening and closing modals — click each to preview</p>
<div id="animInfo" class="anim-info">Click any button below to open its modal variant</div>
<span class="sl">Open a modal</span>
<h2>6 entrance animations</h2>
<div class="grid">
<button class="trig-btn" style="--c:#059669" onclick="openModal('m1')">⬆ Scale in</button>
<button class="trig-btn" style="--c:#7c3aed" onclick="openModal('m2')">⬆ Slide up</button>
<button class="trig-btn" style="--c:#0ea5e9" onclick="openModal('m3')">↻ Flip in</button>
<button class="trig-btn" style="--c:#f97316" onclick="openModal('m4')">🎯 Bounce</button>
<button class="trig-btn" style="--c:#ec4899" onclick="openModal('m5')">→ Slide right</button>
<button class="trig-btn" style="--c:#d97706" onclick="openModal('m6')">⬇ Unfold</button>
</div>
</div>
<!-- Modal 1 — Scale in (success) -->
<div class="overlay" id="m1" onclick="if(event.target===this)closeModal('m1')">
<div class="modal m-scale">
<button class="mclose" onclick="closeModal('m1')">✕</button>
<div class="modal-type">Scale entrance</div>
<span class="modal-icon">✅</span>
<h3>Deployment complete</h3>
<p>Your application has been deployed to production successfully. All 4 health checks passed with zero downtime.</p>
<div class="modal-actions">
<button class="m-primary" onclick="closeModal('m1')">View deployment</button>
<button class="m-secondary" onclick="closeModal('m1')">Dismiss</button>
</div>
</div>
</div>
<!-- Modal 2 — Slide up (default) -->
<div class="overlay" id="m2" onclick="if(event.target===this)closeModal('m2')">
<div class="modal m-slideup">
<button class="mclose" onclick="closeModal('m2')">✕</button>
<div class="modal-type">Slide up entrance</div>
<span class="modal-icon">🚀</span>
<h3>Start your free trial</h3>
<p>Get full access to all Pro features for 14 days. No credit card required. Cancel any time.</p>
<div class="modal-actions">
<button class="m-primary" onclick="closeModal('m2')">Start free trial</button>
<button class="m-secondary" onclick="closeModal('m2')">Maybe later</button>
</div>
</div>
</div>
<!-- Modal 3 — Flip in (info) -->
<div class="overlay" id="m3" onclick="if(event.target===this)closeModal('m3')">
<div class="modal m-flip var-info">
<button class="mclose" onclick="closeModal('m3')">✕</button>
<div class="modal-type">Flip entrance</div>
<span class="modal-icon">ℹ️</span>
<h3>Update available</h3>
<p>Version 4.2.0 is ready to install. This update includes performance improvements and 3 bug fixes.</p>
<div class="modal-actions">
<button class="m-primary" onclick="closeModal('m3')">Install now</button>
<button class="m-secondary" onclick="closeModal('m3')">Remind later</button>
</div>
</div>
</div>
<!-- Modal 4 — Bounce -->
<div class="overlay" id="m4" onclick="if(event.target===this)closeModal('m4')">
<div class="modal m-bounce">
<button class="mclose" onclick="closeModal('m4')">✕</button>
<div class="modal-type">Bounce entrance</div>
<span class="modal-icon">🎉</span>
<h3>Congratulations!</h3>
<p>You've unlocked the Pro tier. All premium features are now active on your account.</p>
<div class="modal-actions">
<button class="m-primary" onclick="closeModal('m4')">Explore features</button>
<button class="m-secondary" onclick="closeModal('m4')">Close</button>
</div>
</div>
</div>
<!-- Modal 5 — Slide from right -->
<div class="overlay" id="m5" onclick="if(event.target===this)closeModal('m5')">
<div class="modal m-right var-err">
<button class="mclose" onclick="closeModal('m5')">✕</button>
<div class="modal-type">Slide right entrance</div>
<span class="modal-icon">⚠️</span>
<h3>Delete this workspace?</h3>
<p>This action cannot be undone. All projects, data and team members will be permanently removed.</p>
<div class="modal-actions">
<button class="m-primary" onclick="closeModal('m5')">Delete permanently</button>
<button class="m-secondary" onclick="closeModal('m5')">Cancel</button>
</div>
</div>
</div>
<!-- Modal 6 — Unfold -->
<div class="overlay" id="m6" onclick="if(event.target===this)closeModal('m6')">
<div class="modal m-unfold var-warn" style="max-width:480px">
<button class="mclose" onclick="closeModal('m6')">✕</button>
<div class="modal-type">Unfold entrance</div>
<span class="modal-icon">⚡</span>
<h3>Usage limit approaching</h3>
<p>You've used 89% of your monthly API quota. Upgrade to Pro to avoid service interruption.</p>
<div class="modal-actions">
<button class="m-primary" onclick="closeModal('m6')">Upgrade plan</button>
<button class="m-secondary" onclick="closeModal('m6')">Dismiss</button>
</div>
</div>
</div>@import url('https://fonts.googleapis.com/css2?family=Epilogue:wght@400;600;700;800&display=swap');
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Epilogue',sans-serif;background:#ecfdf5;color:#0f172a;min-height:100vh;padding:60px 24px}
.wrap{max-width:1000px;margin:0 auto}
h1{font-size:clamp(2rem,5vw,3rem);font-weight:800;text-align:center;margin-bottom:8px;letter-spacing:-.03em;color:#0f172a}
.sub{text-align:center;color:#64748b;margin-bottom:56px}
.sl{font-size:.68rem;font-weight:700;letter-spacing:.25em;text-transform:uppercase;color:#10b981;margin-bottom:12px;display:block}
h2{font-size:1.15rem;font-weight:700;margin-bottom:20px}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:16px;margin-bottom:48px}
.trig-btn{padding:14px 24px;border-radius:10px;font-family:'Epilogue';font-weight:700;font-size:.9rem;cursor:pointer;border:none;background:var(--c,#059669);color:#fff;transition:transform .1s,filter .2s;display:flex;align-items:center;justify-content:center;gap:8px}
.trig-btn:hover{filter:brightness(1.1)}
.trig-btn:active{transform:scale(.97)}
/* OVERLAY */
.overlay{position:fixed;inset:0;background:rgba(0,0,0,.5);backdrop-filter:blur(4px);z-index:100;display:flex;align-items:center;justify-content:center;padding:20px;
opacity:0;pointer-events:none;transition:opacity .3s}
.overlay.open{opacity:1;pointer-events:auto}
/* MODAL BASE */
.modal{background:#fff;border-radius:20px;padding:36px;width:100%;max-width:480px;position:relative;
box-shadow:0 24px 80px rgba(0,0,0,.25)}
/* Modal close btn */
.mclose{position:absolute;top:16px;right:16px;width:32px;height:32px;border-radius:50%;background:#f1f5f9;border:none;font-size:1rem;cursor:pointer;display:grid;place-items:center;color:#64748b;transition:background .2s}
.mclose:hover{background:#e2e8f0;color:#0f172a}
/* M1 — Scale in */
.m-scale{transform:scale(.85);transition:transform .35s cubic-bezier(.34,1.56,.64,1),opacity .25s}
.overlay.open .m-scale{transform:scale(1)}
.overlay:not(.open) .m-scale{transform:scale(.85)}
/* M2 — Slide up */
.m-slideup{transform:translateY(60px);opacity:0;transition:transform .4s cubic-bezier(.22,1,.36,1),opacity .3s}
.overlay.open .m-slideup{transform:translateY(0);opacity:1}
/* M3 — Flip in */
.m-flip{transform:perspective(800px) rotateX(-20deg);opacity:0;transform-origin:top;transition:transform .4s cubic-bezier(.22,1,.36,1),opacity .3s}
.overlay.open .m-flip{transform:perspective(800px) rotateX(0);opacity:1}
/* M4 — Bounce */
.m-bounce{transform:scale(.3);opacity:0;transition:transform .5s cubic-bezier(.34,1.8,.64,1),opacity .2s}
.overlay.open .m-bounce{transform:scale(1);opacity:1}
/* M5 — Slide from right */
.m-right{transform:translateX(80px);opacity:0;transition:transform .4s cubic-bezier(.22,1,.36,1),opacity .3s}
.overlay.open .m-right{transform:translateX(0);opacity:1}
/* M6 — Unfold (height expand) */
.m-unfold{max-height:0;overflow:hidden;opacity:0;transition:max-height .5s cubic-bezier(.22,1,.36,1),opacity .4s .1s;padding:0 36px}
.overlay.open .m-unfold{max-height:500px;opacity:1;padding:36px}
/* modal content shared */
.modal h3{font-size:1.25rem;font-weight:700;margin-bottom:8px}
.modal p{font-size:.9rem;color:#64748b;line-height:1.6;margin-bottom:20px}
.modal-actions{display:flex;gap:10px}
.m-primary{flex:1;padding:12px;border-radius:8px;background:#059669;color:#fff;font-family:'Epilogue';font-weight:700;font-size:.9rem;border:none;cursor:pointer;transition:background .2s}
.m-primary:hover{background:#047857}
.m-secondary{flex:1;padding:12px;border-radius:8px;background:#f1f5f9;color:#0f172a;font-family:'Epilogue';font-weight:700;font-size:.9rem;border:none;cursor:pointer;transition:background .2s}
.m-secondary:hover{background:#e2e8f0}
.modal-type{font-size:.68rem;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:#10b981;margin-bottom:12px}
.modal-icon{font-size:2.5rem;margin-bottom:12px;display:block}
/* variant colours */
.var-warn h3{color:#d97706}
.var-warn .m-primary{background:#d97706}
.var-warn .m-primary:hover{background:#b45309}
.var-warn .modal-type{color:#d97706}
.var-err h3{color:#dc2626}
.var-err .m-primary{background:#dc2626}
.var-err .m-primary:hover{background:#b91c1c}
.var-err .modal-type{color:#dc2626}
.var-info h3{color:#2563eb}
.var-info .m-primary{background:#2563eb}
.var-info .m-primary:hover{background:#1d4ed8}
.var-info .modal-type{color:#2563eb}
/* current info badge */
.anim-info{background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;padding:12px 16px;font-size:.8rem;color:#166534;margin-bottom:40px}
@media (prefers-reduced-motion:reduce){.modal,.overlay{transition:none !important;transform:none !important}} @import url('https://fonts.googleapis.com/css2?family=Epilogue:wght@400;600;700;800&display=swap');
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:'Epilogue',sans-serif;background:#ecfdf5;color:#0f172a;min-height:100vh;padding:60px 24px}
.wrap{max-width:1000px;margin:0 auto}
h1{font-size:clamp(2rem,5vw,3rem);font-weight:800;text-align:center;margin-bottom:8px;letter-spacing:-.03em;color:#0f172a}
.sub{text-align:center;color:#64748b;margin-bottom:56px}
.sl{font-size:.68rem;font-weight:700;letter-spacing:.25em;text-transform:uppercase;color:#10b981;margin-bottom:12px;display:block}
h2{font-size:1.15rem;font-weight:700;margin-bottom:20px}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:16px;margin-bottom:48px}
.trig-btn{padding:14px 24px;border-radius:10px;font-family:'Epilogue';font-weight:700;font-size:.9rem;cursor:pointer;border:none;background:var(--c,#059669);color:#fff;transition:transform .1s,filter .2s;display:flex;align-items:center;justify-content:center;gap:8px}
.trig-btn:hover{filter:brightness(1.1)}
.trig-btn:active{transform:scale(.97)}
/* OVERLAY */
.overlay{position:fixed;inset:0;background:rgba(0,0,0,.5);backdrop-filter:blur(4px);z-index:100;display:flex;align-items:center;justify-content:center;padding:20px;
opacity:0;pointer-events:none;transition:opacity .3s}
.overlay.open{opacity:1;pointer-events:auto}
/* MODAL BASE */
.modal{background:#fff;border-radius:20px;padding:36px;width:100%;max-width:480px;position:relative;
box-shadow:0 24px 80px rgba(0,0,0,.25)}
/* Modal close btn */
.mclose{position:absolute;top:16px;right:16px;width:32px;height:32px;border-radius:50%;background:#f1f5f9;border:none;font-size:1rem;cursor:pointer;display:grid;place-items:center;color:#64748b;transition:background .2s}
.mclose:hover{background:#e2e8f0;color:#0f172a}
/* M1 — Scale in */
.m-scale{transform:scale(.85);transition:transform .35s cubic-bezier(.34,1.56,.64,1),opacity .25s}
.overlay.open .m-scale{transform:scale(1)}
.overlay:not(.open) .m-scale{transform:scale(.85)}
/* M2 — Slide up */
.m-slideup{transform:translateY(60px);opacity:0;transition:transform .4s cubic-bezier(.22,1,.36,1),opacity .3s}
.overlay.open .m-slideup{transform:translateY(0);opacity:1}
/* M3 — Flip in */
.m-flip{transform:perspective(800px) rotateX(-20deg);opacity:0;transform-origin:top;transition:transform .4s cubic-bezier(.22,1,.36,1),opacity .3s}
.overlay.open .m-flip{transform:perspective(800px) rotateX(0);opacity:1}
/* M4 — Bounce */
.m-bounce{transform:scale(.3);opacity:0;transition:transform .5s cubic-bezier(.34,1.8,.64,1),opacity .2s}
.overlay.open .m-bounce{transform:scale(1);opacity:1}
/* M5 — Slide from right */
.m-right{transform:translateX(80px);opacity:0;transition:transform .4s cubic-bezier(.22,1,.36,1),opacity .3s}
.overlay.open .m-right{transform:translateX(0);opacity:1}
/* M6 — Unfold (height expand) */
.m-unfold{max-height:0;overflow:hidden;opacity:0;transition:max-height .5s cubic-bezier(.22,1,.36,1),opacity .4s .1s;padding:0 36px}
.overlay.open .m-unfold{max-height:500px;opacity:1;padding:36px}
/* modal content shared */
.modal h3{font-size:1.25rem;font-weight:700;margin-bottom:8px}
.modal p{font-size:.9rem;color:#64748b;line-height:1.6;margin-bottom:20px}
.modal-actions{display:flex;gap:10px}
.m-primary{flex:1;padding:12px;border-radius:8px;background:#059669;color:#fff;font-family:'Epilogue';font-weight:700;font-size:.9rem;border:none;cursor:pointer;transition:background .2s}
.m-primary:hover{background:#047857}
.m-secondary{flex:1;padding:12px;border-radius:8px;background:#f1f5f9;color:#0f172a;font-family:'Epilogue';font-weight:700;font-size:.9rem;border:none;cursor:pointer;transition:background .2s}
.m-secondary:hover{background:#e2e8f0}
.modal-type{font-size:.68rem;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:#10b981;margin-bottom:12px}
.modal-icon{font-size:2.5rem;margin-bottom:12px;display:block}
/* variant colours */
.var-warn h3{color:#d97706}
.var-warn .m-primary{background:#d97706}
.var-warn .m-primary:hover{background:#b45309}
.var-warn .modal-type{color:#d97706}
.var-err h3{color:#dc2626}
.var-err .m-primary{background:#dc2626}
.var-err .m-primary:hover{background:#b91c1c}
.var-err .modal-type{color:#dc2626}
.var-info h3{color:#2563eb}
.var-info .m-primary{background:#2563eb}
.var-info .m-primary:hover{background:#1d4ed8}
.var-info .modal-type{color:#2563eb}
/* current info badge */
.anim-info{background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;padding:12px 16px;font-size:.8rem;color:#166534;margin-bottom:40px}
@media (prefers-reduced-motion:reduce){.modal,.overlay{transition:none !important;transform:none !important}}function openModal(id){
document.getElementById(id).classList.add('open');
document.getElementById('animInfo').textContent='Transition: ' + {m1:'scale(.85) → scale(1)',m2:'translateY(60px) → translateY(0)',m3:'perspective rotateX(-20deg) → rotateX(0)',m4:'scale(.3) → scale(1) with overshoot',m5:'translateX(80px) → translateX(0)',m6:'max-height 0 → 500px'}[id];
}
function closeModal(id){ document.getElementById(id).classList.remove('open'); }
document.addEventListener('keydown', e=>{ if(e.key==='Escape') document.querySelectorAll('.overlay.open').forEach(m=>m.classList.remove('open')); }); function openModal(id){
document.getElementById(id).classList.add('open');
document.getElementById('animInfo').textContent='Transition: ' + {m1:'scale(.85) → scale(1)',m2:'translateY(60px) → translateY(0)',m3:'perspective rotateX(-20deg) → rotateX(0)',m4:'scale(.3) → scale(1) with overshoot',m5:'translateX(80px) → translateX(0)',m6:'max-height 0 → 500px'}[id];
}
function closeModal(id){ document.getElementById(id).classList.remove('open'); }
document.addEventListener('keydown', e=>{ if(e.key==='Escape') document.querySelectorAll('.overlay.open').forEach(m=>m.classList.remove('open')); });More from 22 CSS Transition Effects
Staggered List AnimationCursor Trail EffectMagnetic Button EffectSplit Text Reveal TransitionProgress Bar AnimationButton Hover TransitionsFlip Card 3D TransitionText Reveal AnimationImage Zoom Hover TransitionBackground Color TransitionBorder Animation TransitionNavigation Hover Transition
View the full collection →