Facebook UI
Navigation Bar
Hide Show Menu
Expand Contract Feature
Web Design

Imitate Facebook hide/show expanding/contracting Navigation Bar

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

A Facebook-style navigation bar usually does two things at once: it hides when the user scrolls down to free space for content, and it reappears when the user scrolls up or explicitly opens navigation. The effect feels simple, but the implementation needs to balance animation smoothness, accessibility, and predictable state.

Start with a Stable Navigation Structure

Before adding scroll behavior, build semantic markup with an explicit toggle button. That gives keyboard and screen-reader users the same navigation access as pointer users.

html
1<header id="topbar" class="topbar">
2  <button id="navToggle"
3          class="nav-toggle"
4          aria-expanded="false"
5          aria-controls="primaryNav">
6    Menu
7  </button>
8
9  <nav id="primaryNav" class="primary-nav" aria-label="Primary">
10    <a href="#home">Home</a>
11    <a href="#friends">Friends</a>
12    <a href="#groups">Groups</a>
13    <a href="#profile">Profile</a>
14  </nav>
15</header>

The button is not optional. If navigation can collapse, there must be a clear control that reveals it again.

Use CSS Transforms for Smooth Hide and Show

For the bar itself, transform is usually smoother than constantly changing top or recalculating layout-heavy properties.

css
1:root {
2  --bar-height: 64px;
3  --bg: #1c1e21;
4  --fg: #f0f2f5;
5}
6
7.topbar {
8  position: sticky;
9  top: 0;
10  z-index: 100;
11  background: var(--bg);
12  color: var(--fg);
13  transition: transform 220ms ease;
14}
15
16.topbar.hidden {
17  transform: translateY(calc(-1 * var(--bar-height)));
18}
19
20.primary-nav {
21  display: grid;
22  grid-template-columns: repeat(4, minmax(0, 1fr));
23  gap: 8px;
24  overflow: hidden;
25  max-height: 120px;
26  transition: max-height 220ms ease, opacity 220ms ease;
27  opacity: 1;
28}
29
30.primary-nav.collapsed {
31  max-height: 0;
32  opacity: 0;
33}

This separates two ideas: hiding the whole bar on scroll and collapsing the nav links when the user toggles the menu state.

Detect Scroll Direction Without Jank

The common pattern is to hide the bar only after meaningful downward movement, then reveal it on upward movement. Use requestAnimationFrame to avoid doing expensive work for every raw scroll event.

javascript
1const topbar = document.getElementById('topbar');
2let lastY = window.scrollY;
3let ticking = false;
4
5function onScroll() {
6  const currentY = window.scrollY;
7  const delta = currentY - lastY;
8
9  if (Math.abs(delta) > 6) {
10    if (delta > 0 && currentY > 80) {
11      topbar.classList.add('hidden');
12    } else {
13      topbar.classList.remove('hidden');
14    }
15    lastY = currentY;
16  }
17
18  ticking = false;
19}
20
21window.addEventListener('scroll', () => {
22  if (!ticking) {
23    requestAnimationFrame(onScroll);
24    ticking = true;
25  }
26});

That threshold prevents the bar from flickering on tiny finger movements.

Add Explicit Expand and Collapse Behavior

The user should also be able to expand or collapse the navigation without relying on scroll direction.

javascript
1const nav = document.getElementById('primaryNav');
2const toggle = document.getElementById('navToggle');
3
4toggle.addEventListener('click', () => {
5  nav.classList.toggle('collapsed');
6  const expanded = !nav.classList.contains('collapsed');
7  toggle.setAttribute('aria-expanded', String(expanded));
8});

If you want the app to remember the user's preference after reload, persist only the collapsed state, not every transient scroll state.

Accessibility and Mobile Details Matter

A polished version should not hide navigation while focus is inside the menu. It should also handle long labels, larger text sizes, and orientation changes. On touch devices, the threshold for hide-on-scroll usually needs testing because overly aggressive behavior feels unstable.

In practice, test these scenarios:

  • fast downward scrolling in a long feed
  • upward flicks that should reveal the bar quickly
  • keyboard navigation while the menu is open
  • large text accessibility settings
  • refresh or route change with preserved collapsed state

Common Pitfalls

  • Running layout-heavy logic directly inside raw scroll handlers.
  • Hiding the navigation bar while a menu item still has keyboard focus.
  • Treating visual collapse and accessibility state as separate concerns.
  • Using fixed pixel assumptions that break on small screens or large text.
  • Copying the motion pattern without deciding whether it actually improves that page.

Summary

  • Build the navigation with semantic HTML and an explicit toggle first.
  • Use CSS transforms for hide and show animations instead of layout-heavy movement.
  • Detect scroll direction with a threshold and requestAnimationFrame.
  • Let users explicitly expand or collapse the menu, not only through scrolling.
  • Validate the behavior on mobile and with accessibility settings before shipping.

Course illustration
Course illustration

All Rights Reserved.