refactor: transition navigation to a persistent fixed-wrapper layout with improved scroll-based floating state styles

This commit is contained in:
Firman Ramdhani
2026-07-29 15:42:39 +07:00
parent 6506122033
commit b43df8f35b
2 changed files with 28 additions and 70 deletions
+8 -4
View File
@@ -61,10 +61,10 @@ export default function Page() {
return (
<main>
{/* ============ NAV + HERO ============ */}
<header className="hero">
{/* ============ FIXED NAV ============ */}
<div className={`nav-wrapper ${isScrolled ? 'floating' : ''}`}>
<div className="container">
<nav className={`nav ${isScrolled ? 'nav-floating' : ''}`}>
<nav className="nav">
<div className="brand">
<a href="#">
<div className="brand-mark">
@@ -102,7 +102,11 @@ export default function Page() {
</div>
</div>
</nav>
<div className="nav-spacer"></div>
</div>
</div>
<header className="hero">
<div className="container">
<div className="hero-inner">
<h1>
+20 -66
View File
@@ -152,32 +152,7 @@
/* Animations that are hard to replicate purely via utility classes */
@layer utilities {
.nav-floating {
position: fixed;
top: 16px;
left: 50%;
transform: translateX(-50%);
width: calc(100% - 40px);
max-width: 1120px;
background: var(--color-brand-1-900);
backdrop-filter: blur(14px);
-webkit-backdrop-filter: blur(14px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 24px 48px -20px rgba(0, 0, 0, 0.55);
z-index: 1000;
animation: navFloatIn 0.4s cubic-bezier(0.16, 0.8, 0.44, 1);
}
@keyframes navFloatIn {
from {
opacity: 0;
transform: translate(-50%, -16px);
}
to {
opacity: 1;
transform: translate(-50%, 0);
}
}
.drift-a {
animation: driftA 7s ease-in-out infinite;
@@ -392,59 +367,38 @@
}
/* ---------- Nav ---------- */
.nav-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 1000;
pointer-events: none; /* Let clicks pass through empty space */
}
.nav-wrapper .container {
pointer-events: auto; /* Enable clicks on the nav itself */
}
.nav {
position: relative;
z-index: 20;
display: flex;
align-items: center;
justify-content: space-between;
padding: 26px 0;
transition:
background 0.35s ease,
box-shadow 0.35s ease,
padding 0.35s ease,
border-color 0.35s ease;
border-radius: var(--radius-md);
margin-top: 0;
border: 1px solid transparent;
transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.nav.nav-floating {
position: fixed;
top: 16px;
left: 50%;
transform: translateX(-50%);
width: calc(100% - 40px);
max-width: 1120px;
.nav-wrapper.floating .nav {
margin-top: 16px;
background: var(--color-brand-1-900);
backdrop-filter: blur(14px);
-webkit-backdrop-filter: blur(14px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: var(--radius-md);
padding: 12px 26px;
box-shadow: 0 24px 48px -20px rgba(0, 0, 0, 0.55);
z-index: 1000;
animation: navFloatIn 0.4s cubic-bezier(0.16, 0.8, 0.44, 1);
}
@keyframes navFloatIn {
from {
opacity: 0;
transform: translate(-50%, -16px);
}
to {
opacity: 1;
transform: translate(-50%, 0);
}
}
.nav-spacer {
display: none;
height: 0;
}
.nav-floating ~ .nav-spacer,
body.nav-is-floating .nav-spacer {
display: block;
height: 74px;
}
.brand {
@@ -525,7 +479,7 @@ body.nav-is-floating .nav-spacer {
.hero-inner {
position: relative;
z-index: 2;
padding: 8px 0 64px;
padding: 94px 0 64px;
}
.hero h1 {