👆 Scroll Down

Watch the header above stay fixed as you scroll!

Notice how it shrinks slightly when scrolled

📌 Sticky Header Implementation Guide

Sticky headers (або "fixed navigation") remain visible at top of viewport коли користувач scrolls down page. This UX pattern dramatically improves navigation accessibility, reduces clicks (menu always reachable), та provides persistent branding. Modern CSS з position: sticky makes implementation trivial порівняно з old JavaScript-heavy approaches. Для mushroom education site з long cultivation guides або research articles, sticky header keeps navigation, search, та category menus always accessible. Цей guide охоплює CSS sticky positioning, scroll-triggered animations, shrinking headers, mobile behavior, та performance optimization.

💻 CSS Implementation

Method 1: position: sticky (Modern, Recommended)

/* Simple sticky header з CSS */
header {
  position: sticky;
  top: 0; /* Distance від top коли sticks */
  z-index: 1000; /* Above other content */
  background: #667eea;
  padding: 20px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

/* Ensure parent allows sticking */
body {
  margin: 0;
  /* No specific parent height needed */
}

/* Optional: transition для smooth changes */
header {
  transition: padding 0.3s, box-shadow 0.3s;
}

Method 2: position: fixed (Legacy, More Control)

/* Always fixed (doesn't "stick", always visible) */
header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  width: 100%;
  z-index: 1000;
  background: #667eea;
  padding: 20px;
}

/* CRITICAL: Add padding до body для offset content */
body {
  padding-top: 80px; /* Height of fixed header */
}

/* Otherwise content будет hidden під header */

Shrinking Header on Scroll (JavaScript):

/* CSS states */
header {
  padding: 25px 40px;
  transition: all 0.3s ease;
}

header.scrolled {
  padding: 12px 40px; /* Smaller */
  box-shadow: 0 4px 20px rgba(0,0,0,0.2); /* Stronger shadow */
}

header.scrolled .logo {
  font-size: 1.2em; /* Shrink logo */
}

/* JavaScript */
window.addEventListener('scroll', () => {
  const header = document.querySelector('header');
  if (window.scrollY > 50) {
    header.classList.add('scrolled');
  } else {
    header.classList.remove('scrolled');
  }
});

Hide on Scroll Down, Show on Scroll Up:

/* CSS */
header {
  position: sticky;
  top: 0;
  transform: translateY(0);
  transition: transform 0.3s ease;
}

header.hidden {
  transform: translateY(-100%); /* Hide upward */
}

/* JavaScript */
let lastScrollY = window.scrollY;

window.addEventListener('scroll', () => {
  const header = document.querySelector('header');
  const currentScrollY = window.scrollY;
  
  if (currentScrollY > lastScrollY && currentScrollY > 100) {
    // Scrolling down
    header.classList.add('hidden');
  } else {
    // Scrolling up
    header.classList.remove('hidden');
  }
  
  lastScrollY = currentScrollY;
});

🎨 Advanced Techniques

Background Blur on Scroll

header.scrolled {
  background: rgba(102, 126, 234, 0.8);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

Color Change on Scroll

header {
  background: transparent;
}

header.scrolled {
  background: #667eea;
  border-bottom: 1px solid rgba(255,255,255,0.2);
}

Progress Bar

<div class="scroll-progress"></div>

.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  background: #667eea;
  width: 0%;
  transition: width 0.1s;
}

// JS
const progress = (scrollY / maxScroll) * 100;
progressBar.style.width = `${progress}%`;

Mobile Menu Toggle

@media (max-width: 768px) {
  header {
    padding: 15px 20px;
  }
  
  .nav {
    display: none;
  }
  
  .hamburger {
    display: block;
  }
}

⚡ Best Practices

Performance Optimization:

  • ✅ Use position: sticky (hardware-accelerated)
  • ✅ Debounce scroll listeners (don't run on every pixel)
  • ✅ Use will-change: transform для animations
  • ✅ Minimize repaints (avoid changing layout properties)
  • ❌ Avoid position: fixed з lots of children

Z-Index Hierarchy:

  • z-index: 10000 — Modals та overlays
  • z-index: 1000 — Sticky header ⭐
  • z-index: 100 — Dropdowns та tooltips
  • z-index: 10 — Elevated cards
  • z-index: 1 — Default stacking

Mobile Considerations:

  • ☐ Smaller padding на mobile (12-15px vs 20-25px desktop)
  • ☐ Hamburger menu для navigation (not full menu)
  • ☐ Logo може shrink більше aggressively
  • ☐ Consider hiding header on scroll down (save screen space)
  • ☐ Test на actual devices (iOS Safari quirks)

🍄 Mushroom Hub Implementation

Complete Example:

<!-- HTML -->
<header class="site-header" id="siteHeader">
  <div class="header-container">
    <div class="logo">
      🍄 Mushroom Knowledge Hub
    </div>
    <nav class="main-nav">
      <a href="/species">Species</a>
      <a href="/cultivation">Growing</a>
      <a href="/safety">Safety</a>
      <a href="/research">Research</a>
    </nav>
    <div class="header-search">
      <input type="search" placeholder="Search...">
    </div>
  </div>
</header>

<!-- CSS -->
<style>
.site-header {
  position: sticky;
  top: 0;
  z-index: 1000;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  padding: 20px 0;
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.site-header.scrolled {
  padding: 12px 0;
  box-shadow: 0 4px 20px rgba(102, 126, 234, 0.3);
}

.header-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 30px;
}

.logo {
  font-size: 1.5em;
  font-weight: 700;
  color: white;
  transition: font-size 0.3s;
}

.site-header.scrolled .logo {
  font-size: 1.2em;
}

.main-nav {
  display: flex;
  gap: 25px;
}

.main-nav a {
  color: white;
  text-decoration: none;
  font-weight: 500;
  transition: opacity 0.2s;
}

.main-nav a:hover {
  opacity: 0.8;
}

@media (max-width: 768px) {
  .site-header {
    padding: 15px 0;
  }
  
  .main-nav {
    display: none; /* Use hamburger menu */
  }
}
</style>

<!-- JavaScript -->
<script>
const header = document.getElementById('siteHeader');

window.addEventListener('scroll', () => {
  if (window.scrollY > 50) {
    header.classList.add('scrolled');
  } else {
    header.classList.remove('scrolled');
  }
}, { passive: true }); // Passive для better performance
</script>

✅ Sticky Header Checklist

Implementation Checklist:

  • position: sticky або fixed applied
  • top: 0 specified
  • z-index: 1000 або higher
  • ☐ Background color solid (not transparent)
  • ☐ Box-shadow для depth perception
  • ☐ Transition effects smooth (0.3s)
  • ☐ Scroll listener optimized (debounced або passive)
  • ☐ Mobile: Smaller size, hamburger menu
  • ☐ Body padding adjusted (if using fixed)
  • ☐ Tested on iOS Safari (known quirks)
  • ☐ Performance: No layout thrashing
  • ☐ Accessibility: Keyboard navigation works

Scroll back up to see header behavior!