au lancement, un logo factice se place au centre, puis glisse et se réduit jusqu’au coin gauche de la navbar (emplacement “brand”). Le petit logo de la navbar apparaît ensuite. Respecte prefers-reduced-motion.
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Logo centre → navbar</title>
<style>
:root{ --dur-move: 900ms; --ease: cubic-bezier(.2,.8,.16,1); }
body{ margin:0; font-family:system-ui,-apple-system,"SF Pro Display",Segoe UI,Roboto,Helvetica,Arial; background:#fff }
/* Navbar */
.nav{
position:sticky; top:0; z-index:10;
display:flex; gap:12px; align-items:center; justify-content:space-between;
padding:12px 16px; background:#ffffffcc; -webkit-backdrop-filter:saturate(180%) blur(12px);
backdrop-filter:saturate(180%) blur(12px); border-bottom:1px solid #eee;
}
.brand-slot{
width:36px; height:36px; border-radius:10px; position:relative; overflow:hidden;
background:#f2f4f8; box-shadow: inset 0 1px 0 #fff, 0 6px 16px rgba(0,0,0,.08);
}
.brand-minilogo{
position:absolute; inset:0; display:grid; place-items:center;
font-weight:800; font-size:16px; color:#0a84ff; opacity:0; transform:scale(.85);
transition: opacity .35s var(--ease), transform .35s var(--ease);
}
.brand-slot.show .brand-minilogo{ opacity:1; transform:scale(1) }
/* Splash logo (overlay) */
#logo-launch{
position:fixed; inset:0; display:grid; place-items:center; z-index:2000;
background: radial-gradient(120% 100% at 10% 10%, #eaf1ff 0%, #ffffff 40%) no-repeat #fff;
}
#logo-launch .logo{
width:120px; height:120px; border-radius:28px; display:grid; place-items:center;
background: linear-gradient(180deg,#0a84ff,#006ae6);
color:#fff; font-weight:800; font-size:28px; letter-spacing:.3px;
box-shadow: 0 18px 42px rgba(10,132,255,.35), inset 0 1px 0 rgba(255,255,255,.65);
will-change: transform;
}
#logo-launch.done{ opacity:0; visibility:hidden; transition: opacity .35s ease }
/* Demo content */
main{ max-width:860px; margin:24px auto; padding:0 16px }
p{ line-height:1.65; color:#2b2b2b }
@media (prefers-reduced-motion: reduce){
#logo-launch{ display:none !important; }
.brand-slot .brand-minilogo{ opacity:1 !important; transform:none !important; }
}
</style>
</head>
<body>
<div id="logo-launch" aria-hidden="true">
<div class="logo">LOGO</div>
</div>
<header class="nav">
<div class="brand-slot" aria-label="Accueil">
<span class="brand-minilogo">LOGO</span>
</div>
<nav>Accueil · Produits · Aide</nav>
</header>
<main>
<h1>Animation de lancement</h1>
<p>Le logo démarre au centre puis se loge dans la marque de la navbar . Ce texte est là pour donner un peu de hauteur à la page web.</p>
<script>document.write('<p>'+('Lorem ipsum dolor sit amet, consectetur adipiscing elit. '.repeat(40))+'</p>'.repeat(12));</script>
</main>
<script>
(function(){
const overlay = document.getElementById('logo-launch');
const moving = overlay.querySelector('.logo');
const target = document.querySelector('.brand-slot');
function animate(){
const tRect = target.getBoundingClientRect();
const mRect = moving.getBoundingClientRect();
// Centre → centre (delta)
const dx = (tRect.left + tRect.width/2) - (mRect.left + mRect.width/2);
const dy = (tRect.top + tRect.height/2) - (mRect.top + mRect.height/2);
// Échelle (logo final un peu plus petit que le slot)
const scale = (tRect.height * 0.78) / mRect.height;
moving.style.transition = `transform var(--dur-move) var(--ease)`;
moving.style.transform = `translate(${dx}px, ${dy}px) scale(${scale})`;
moving.addEventListener('transitionend', () => {
// Affiche le mini-logo de la navbar, puis retire l’overlay
target.classList.add('show');
overlay.classList.add('done');
setTimeout(()=> overlay.remove(), 380);
}, {once:true});
}
// Lancer après mise en page
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => requestAnimationFrame(animate));
} else {
requestAnimationFrame(animate);
}
})();
</script>
</body>
</html>