Toggle navigation
☰
Home
HTML
CSS
Scripting
Database
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Shrink on Scroll Sticky Navbar</title> <style> /* ======================================== CSS Custom Properties (Base Theme) ======================================== */ :root { --color-background: #ffffff; --color-text-primary: #212529; --color-text-secondary: #6c757d; --color-primary: #007bff; --color-border: #dee2e6; /* These properties will be animated */ --navbar-height-large: 90px; --navbar-height-small: 60px; --logo-font-size-large: 1.75rem; --logo-font-size-small: 1.25rem; --font-family-sans-serif: system-ui, -apple-system, sans-serif; --font-weight-bold: 700; --container-width: 1140px; --transition-speed: 0.3s; --border-radius: 0.3rem; } /* ======================================== Global Resets & Base Styles ======================================== */ *, *::before, *::after { box-sizing: border-box; } body { margin: 0; font-family: var(--font-family-sans-serif); } .content { height: 200vh; max-width: var(--container-width); margin: 0 auto; padding: calc(var(--navbar-height-large) + 2rem) 1rem; } ul { list-style: none; margin: 0; padding: 0; } a { text-decoration: none; color: var(--color-text-secondary); transition: color var(--transition-speed) ease; } a:hover, a:focus { color: var(--color-text-primary); } /* ======================================== Main Navbar Structure & Default (Large) State ======================================== */ .navbar { position: sticky; top: 0; z-index: 1000; display: flex; align-items: center; /* Start with the large height */ height: var(--navbar-height-large); background-color: var(--color-background); box-shadow: 0 2px 4px rgba(0,0,0,0.05); /* Animate the height property */ transition: height var(--transition-speed) ease; } .navbar__container { display: flex; justify-content: space-between; align-items: center; width: 100%; max-width: var(--container-width); margin: 0 auto; padding: 0 1.5rem; } .navbar__brand { font-weight: var(--font-weight-bold); color: var(--color-text-primary); /* Start with the large font size */ font-size: var(--logo-font-size-large); /* Animate the font-size property */ transition: font-size var(--transition-speed) ease; } /* ======================================== Scrolled (Small) State Styles ======================================== These styles are applied when the .is-scrolled class is added via JS. */ .navbar.is-scrolled { height: var(--navbar-height-small); /* Shrink height */ box-shadow: 0 4px 12px rgba(0,0,0,0.1); /* Stronger shadow */ } .navbar.is-scrolled .navbar__brand { font-size: var(--logo-font-size-small); /* Shrink font size */ } /* ======================================== Mobile Menu & Toggle ======================================== */ .navbar__toggle { display: block; border: 1px solid var(--color-border); border-radius: var(--border-radius); padding: 0.25rem 0.75rem; background: transparent; cursor: pointer; } .navbar__toggle .bar { display: block; width: 22px; height: 2px; margin: 6px 0; background-color: var(--color-text-primary); transition: transform var(--transition-speed) ease; } .navbar__toggle.is-active .bar:nth-child(1) { transform: translateY(8px) rotate(45deg); } .navbar__toggle.is-active .bar:nth-child(2) { opacity: 0; } .navbar__toggle.is-active .bar:nth-child(3) { transform: translateY(-8px) rotate(-45deg); } .navbar__menu { display: none; flex-direction: column; position: absolute; left: 0; /* The top position must adapt when the navbar shrinks */ top: var(--navbar-height-large); width: 100%; background-color: var(--color-background); border-bottom: 1px solid var(--color-border); transition: top var(--transition-speed) ease; z-index: 999; } .navbar.is-scrolled .navbar__menu { top: var(--navbar-height-small); } .navbar__menu.is-active { display: flex; } .navbar__item { text-align: center; border-top: 1px solid var(--color-border); } .navbar__link { display: block; padding: 1.25rem; font-weight: bold; } :is(.navbar__toggle, .navbar__link):focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; border-radius: var(--border-radius); } /* ======================================== Desktop Navbar Styles ======================================== */ @media (min-width: 992px) { .navbar__toggle { display: none; } .navbar__menu { display: flex; flex-direction: row; align-items: center; position: static; width: auto; background: none; border: none; transition: none; } .navbar__list { display: flex; align-items: center; gap: 1rem; } .navbar__item { border-top: none; } .navbar__link { padding: 1rem; /* Animate padding for the shrink effect */ transition: padding var(--transition-speed) ease, color var(--transition-speed) ease; } /* Adjust padding on links when scrolled */ .navbar.is-scrolled .navbar__link { padding: 0.5rem 1rem; } .navbar__link--cta { color: #fff; background-color: var(--color-primary); border-radius: var(--border-radius); transition: padding var(--transition-speed) ease, background-color var(--transition-speed) ease; } .navbar__link--cta:hover, .navbar__link--cta:focus { color: #fff; background-color: #0b5ed7; } } </style> </head> <body> <header class="navbar" id="main-navbar"> <div class="navbar__container"> <a href="#" class="navbar__brand">Brand</a> <button class="navbar__toggle" id="navbarToggle" aria-label="Toggle navigation" aria-controls="navbarMenu" aria-expanded="false"> <span class="bar"></span><span class="bar"></span><span class="bar"></span> </button> <nav id="navbarMenu" class="navbar__menu" role="navigation"> <ul class="navbar__list"> <li class="navbar__item"><a href="#" class="navbar__link">Home</a></li> <li class="navbar__item"><a href="#" class="navbar__link">Features</a></li> <li class="navbar__item"><a href="#" class="navbar__link">About</a></li> <li class="navbar__item"><a href="#" class="navbar__link navbar__link--cta">Request Demo</a></li> </ul> </nav> </div> </header> <main class="content"> <h1>Shrink on Scroll Navbar</h1> <p>Scroll down to see the header gracefully shrink to a smaller size.</p> </main> <script> document.addEventListener('DOMContentLoaded', function () { const navbarToggle = document.getElementById('navbarToggle'); const navbarMenu = document.getElementById('navbarMenu'); // Standard mobile menu toggle if (navbarToggle && navbarMenu) { navbarToggle.addEventListener('click', function () { navbarToggle.classList.toggle('is-active'); navbarMenu.classList.toggle('is-active'); const isExpanded = navbarMenu.classList.contains('is-active'); navbarToggle.setAttribute('aria-expanded', isExpanded); }); } // --- Shrink on Scroll Logic --- const mainNavbar = document.getElementById('main-navbar'); // Define how far to scroll (in pixels) before shrinking the navbar const scrollThreshold = 50; if (mainNavbar) { window.addEventListener('scroll', function() { // The class 'is-scrolled' will be added if scrollY is > threshold, // and removed if it's not. `toggle` with the second argument is perfect for this. mainNavbar.classList.toggle('is-scrolled', window.scrollY > scrollThreshold); }); } }); </script> </body> </html>