Smart header

The header shrinks after the first scroll, hides when you read down, and returns when you scroll up.

How it works

The script compares each scroll position with the previous one. Past 40px the header gets a compact class; moving down more than a few pixels adds a hidden class, moving up removes it. Small jitters are ignored.

Full file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Smart header</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; }
body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; -webkit-font-smoothing: antialiased; }

body { background: #eef1f5; color: #1f2933; }
.bar {
  position: fixed; inset: 0 0 auto 0; z-index: 5; height: 96px; padding: 0 28px;
  display: flex; align-items: center; justify-content: space-between;
  background: #fff; box-shadow: 0 1px 0 #dde3ea;
  transition: height .3s, transform .35s;
  font: 1.1rem system-ui, sans-serif;
}
.bar strong { font-size: 1.8rem; transition: font-size .3s; }
.bar nav a { margin-left: 20px; }
.bar.compact { height: 56px; }
.bar.compact strong { font-size: 1.2rem; }
.bar.hidden { transform: translateY(-100%); }
.feed { padding: 120px 24px 40vh; max-width: 640px; margin: 0 auto; display: grid; gap: 16px; }
.post { height: 180px; background: #fff; border-radius: 12px; padding: 20px; }
.post b { display: block; height: 14px; width: 60%; background: #dde3ea; border-radius: 7px; margin-bottom: 12px; }
.post i { display: block; height: 10px; background: #eef1f5; border-radius: 5px; margin-bottom: 8px; }
</style>
</head>
<body>
<header class="bar" id="bar"><strong>Logo</strong><nav><a>Work</a><a>About</a><a>Contact</a></nav></header>
<main class="feed" id="feed"></main>
<script>
const feed = document.getElementById('feed');
for (let i = 0; i < 14; i++) feed.insertAdjacentHTML('beforeend', '<div class="post"><b></b><i></i><i></i><i style="width:70%"></i></div>');
const bar = document.getElementById('bar');
let last = scrollY;
addEventListener('scroll', () => {
  const y = scrollY;
  bar.classList.toggle('compact', y > 40);
  if (Math.abs(y - last) > 6) {
    bar.classList.toggle('hidden', y > last && y > 200);
    last = y;
  }
}, { passive: true });
</script>
</body>
</html>

More sticky effects