Morphing Dialog New
A project card that grows into a dialog on click, via the View Transitions API with a FLIP fallback. For case studies and team profiles.
Renovatie · 1.200 m2
Kantoor Delft
Een jaren-zeventig kantoor aan de Schie, omgebouwd tot energielabel A met behoud van de betonnen gevel. Opgeleverd in 14 weken, terwijl de huurders bleven werken.
How to use it
- Paste the HTML where the components should appear.
- Add the CSS to your stylesheet. All classes are prefixed, so nothing clashes with your own styles.
- Add the JavaScript and call init() with the element that contains the HTML.
<!-- Morphing Dialog · Bron: Motion Primitives · licentie MIT. Laat deze vermelding staan bij hergebruik. -->
<div class="jouw-container">
<div class="mdl"><button class="mdl__card" aria-haspopup="dialog"><span class="mdl__img"></span><span class="mdl__ct"><b>Kantoor Delft</b><em>Renovatie · 2026</em></span><span class="mdl__plus">+</span></button>
<div class="mdl__dlg" role="dialog" aria-label="Kantoor Delft" hidden><span class="mdl__img mdl__img--l"></span><div class="mdl__body"><span class="mdl__kick">Renovatie · 1.200 m2</span><h4>Kantoor Delft</h4><p>Een jaren-zeventig kantoor aan de Schie, omgebouwd tot energielabel A met behoud van de betonnen gevel. Opgeleverd in 14 weken, terwijl de huurders bleven werken.</p></div><button class="mdl__x" aria-label="Sluiten">×</button></div></div>
</div>/* Morphing Dialog · Bron: Motion Primitives · licentie MIT. Laat deze vermelding staan bij hergebruik. */
.mdl{position:absolute;inset:0;background:#f4f3f1;font-family:'Switzer',system-ui,sans-serif;display:flex;align-items:center;justify-content:center;overflow:hidden}
.mdl__card{width:160px;border:0;padding:0;background:#fff;border-radius:6px;overflow:hidden;cursor:pointer;text-align:left;position:relative;box-shadow:0 1px 0 rgba(10,10,10,.08)}
.mdl__card:hover .mdl__plus{background:#F5480F;color:#fff}
.mdl__img{display:block;height:84px;background:linear-gradient(160deg,#F5480F 0 40%,#0a0a0a 40% 100%)}
.mdl__ct{display:flex;flex-direction:column;padding:8px 10px 10px;color:#0a0a0a}
.mdl__ct b{font-size:13px}.mdl__ct em{font-style:normal;font-size:11px;color:rgba(10,10,10,.6)}
.mdl__plus{position:absolute;right:8px;bottom:9px;width:20px;height:20px;border-radius:50%;border:1px solid #0a0a0a;display:flex;align-items:center;justify-content:center;font-size:14px;line-height:1;transition:background .2s}
.mdl__dlg{position:absolute;inset:10px;background:#fff;border-radius:6px;display:flex;overflow:hidden;box-shadow:0 10px 30px rgba(10,10,10,.12)}
.mdl__dlg[hidden]{display:none}
.mdl__img--l{height:auto;flex:0 0 38%}
.mdl__body{padding:12px 14px;overflow:auto;color:#0a0a0a}
.mdl__kick{font:500 10px 'JetBrains Mono',monospace;letter-spacing:.12em;text-transform:uppercase;color:#F5480F}
.mdl__body h4{margin:6px 0;font:800 15px/1.2 'Boldonse','Switzer',system-ui,sans-serif;font-synthesis:none}
.mdl__body p{margin:0;font-size:12px;line-height:1.45;color:rgba(10,10,10,.75)}
.mdl__x{position:absolute;right:8px;top:8px;width:24px;height:24px;border-radius:50%;border:0;background:#0a0a0a;color:#fff;font-size:15px;line-height:1;cursor:pointer}
::view-transition-group(mdl-morph){animation-duration:.45s;animation-timing-function:cubic-bezier(.2,.8,.2,1)}
::view-transition-old(mdl-morph),::view-transition-new(mdl-morph){height:100%;object-fit:none;object-position:top left}// Morphing Dialog · Bron: Motion Primitives · licentie MIT. Laat deze vermelding staan bij hergebruik.
// root = het element waarin de HTML staat
function init(root){
root=root.querySelector('.mdl')||root;var card=root.querySelector('.mdl__card'),dlg=root.querySelector('.mdl__dlg'),x=root.querySelector('.mdl__x');var reduce=matchMedia('(prefers-reduced-motion: reduce)').matches;var open=false;
function swap(o){open=o;card.style.visibility=o?'hidden':'';dlg.hidden=!o;if(o)x.focus({preventScroll:true});else card.focus({preventScroll:true});}
function flip(from,to,o){var a=from.getBoundingClientRect();swap(o);var b=to.getBoundingClientRect();if(!to.animate)return;to.animate([{transform:'translate('+(a.left-b.left)+'px,'+(a.top-b.top)+'px) scale('+(a.width/b.width)+','+(a.height/b.height)+')',transformOrigin:'0 0',borderRadius:'10px'},{transform:'none',transformOrigin:'0 0'}],{duration:420,easing:'cubic-bezier(.2,.8,.2,1)'});}
function go(o){if(o===open)return;var from=o?card:dlg,to=o?dlg:card;if(reduce){swap(o);return;}
if(document.startViewTransition){from.style.viewTransitionName='mdl-morph';var vt=document.startViewTransition(function(){from.style.viewTransitionName='';to.style.viewTransitionName='mdl-morph';swap(o);});vt.finished.then(function(){to.style.viewTransitionName='';},function(){to.style.viewTransitionName='';});}else flip(from,to,o);}
card.addEventListener('click',function(){go(true);});x.addEventListener('click',function(){go(false);});root.addEventListener('keydown',function(e){if(e.key==='Escape')go(false);});
}
init(document.querySelector('.jouw-container'));
More components
Seen something you like?
Add it to your selection and send it over. We build your site around it, in your brand.
Get in touch →