Skip to main content

Overview

The Natours navigation is a sophisticated full-screen menu system with a hamburger icon that transforms into an X when opened. It features a radially expanding background and smooth fade-in effects, all built with pure CSS using the checkbox hack technique.

Visual Behavior

1

Closed State

  • Hamburger icon visible in top-right corner
  • Circular button with three horizontal lines
  • Navigation menu hidden
2

Click/Tap

  • Hidden checkbox toggles state
  • Background circle expands from button
  • Menu icon transforms to X
3

Open State

  • Full-screen navigation overlay
  • Menu items fade in
  • Animated hover effects on links

Complete Navigation Structure

index.html:23-44
<div class="navigation">
  <input type="checkbox" class="navigation__checkbox" 
         id="navi-toggle" title="navi-toggle" />

  <label for="navi-toggle" class="navigation__button">
    <span class="navigation__icon">&nbsp;</span>
  </label>
  
  <div class="navigation__background">
    &nbsp;
  </div>

  <nav class="navigation__nav">
    <ul class="navigation__list">
      <li class="navigation__item">
        <a href="#" class="navigation__link">
          <span>01</span> Home
        </a>
      </li>
      <li class="navigation__item">
        <a href="#section-about" class="navigation__link">
          <span>02</span> About Natous
        </a>
      </li>
      <li class="navigation__item">
        <a href="#section-features" class="navigation__link">
          <span>03</span> Your benefits
        </a>
      </li>
      <li class="navigation__item">
        <a href="#section-tours" class="navigation__link">
          <span>04</span> Popular tours
        </a>
      </li>
      <li class="navigation__item">
        <a href="#section-stories" class="navigation__link">
          <span>05</span> Stories
        </a>
      </li>
      <li class="navigation__item">
        <a href="#section-book" class="navigation__link">
          <span>06</span> Book now
        </a>
      </li>
    </ul>
  </nav>
</div>
The navigation uses a hidden checkbox to control the open/closed state. This “checkbox hack” allows toggle functionality without JavaScript.

Checkbox (Hidden Controller)

sass/components/layout/_navigation.scss:5
&__checkbox { 
  display: none; 
}
The checkbox is completely hidden but remains functional. When the label is clicked, the checkbox toggles, triggering CSS state changes through the :checked pseudo-class.

Toggle Button

The circular button in the top-right corner:
sass/components/layout/_navigation.scss:7-19
&__button {
  background-color: $color-white;
  height: 7rem;
  width: 7rem;
  position: fixed;
  top: 6rem;
  right: 6rem;
  border-radius: 50%;
  z-index: 2000;
  box-shadow: 0 1rem 3rem rgba($color-black, .1);
  text-align: center;
  cursor: pointer;
}

Button Features

position: fixed;
top: 6rem;
right: 6rem;
z-index: 2000;  // Above everything
Fixed positioning keeps the button visible during page scroll. Highest z-index ensures it stays on top.

Expanding Background

The circular element that expands to cover the screen:
sass/components/layout/_navigation.scss:21-31
&__background {
  width: 6rem;
  height: 6rem;
  border-radius: 50%;
  position: fixed;
  top: 6.5rem;
  right: 6.5rem;
  background: radial-gradient($color-primary-light, $color-primary-dark);
  z-index: 1000;
  transition: transform .6s cubic-bezier(0.86, 0, 0.07, 1);
}

Background Properties

Initial size: 6rem × 6rem (slightly smaller than button) Position: Centered behind the button (offset by 0.5rem) Z-index: 1000 (below button at 2000, above content) Gradient: Radial gradient from light green to dark green

Expansion Animation

sass/components/layout/_navigation.scss:84
&__checkbox:checked ~ &__background { 
  transform: scale(82); 
}
The background circle is 6rem (60px). To cover a typical viewport:
  • Original size: 60px
  • Scaled size: 60px × 82 = 4,920px
  • This ensures coverage on screens up to ~5000px
The scale transform is GPU-accelerated for smooth performance.

Custom Easing

transition: transform .6s cubic-bezier(0.86, 0, 0.07, 1);
Cubic bezier breakdown:
  • Fast start (0.86 at first control point)
  • Smooth middle (0 at second control point)
  • Quick finish (0.07, 1)
This creates an organic, “breathing” expansion effect. The full-screen menu overlay:
sass/components/layout/_navigation.scss:33-43
&__nav {
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1500;
  
  opacity: 0;
  width: 0;
  transition: all .6s ease;
}

Hidden State

  • Opacity: 0 - Invisible
  • Width: 0 - Takes no space
  • Z-index: 1500 - Between background (1000) and button (2000)

Open State

sass/components/layout/_navigation.scss:86-89
&__checkbox:checked ~ &__nav {
  opacity: 1;
  width: 100%;
}
When checkbox is checked:
  • Opacity fades from 0 to 1
  • Width expands from 0 to 100%
  • Both animate over 0.6s
Centered menu items:
sass/components/layout/_navigation.scss:45-51
&__list {
  list-style: none;
  text-align: center;
  width: 100%;
  
  @include absCenter;
}
The absCenter mixin positions the list perfectly in the center:
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

List Items

sass/components/layout/_navigation.scss:53
&__item { 
  margin: 1rem; 
}
Simple vertical spacing between menu items. Large, animated text links with gradient hover effect:
sass/components/layout/_navigation.scss:55-81
&__link {
  &:link,
  &:visited {
    display: inline-block;
    font-size: 3rem;
    font-weight: 300;
    padding: 1rem 2rem;
    color: $color-white;
    text-decoration: none;
    text-transform: uppercase;
    background-image: linear-gradient(120deg, 
      transparent 0%, 
      transparent 50%, 
      $color-white 50%);
    background-size: 230%;
    transition: all .4s ease;

    span {
      margin-right: 1.5rem;
      display: inline-block;
    }
  }
  
  &:hover,
  &:active {
    background-position: 100%;
    color: $color-primary;
    transform: translateX(1rem);
  }
}
Typography:
font-size: 3rem;           // Large 30px
font-weight: 300;          // Light weight
text-transform: uppercase;
color: $color-white;
Number styling:
span {
  margin-right: 1.5rem;    // Space between number and text
  display: inline-block;
}

Gradient Hover Effect

The link uses a clever gradient background trick:
background-image: linear-gradient(
  120deg, 
  transparent 0%,      // Left half: transparent
  transparent 50%,     // Left half: transparent
  $color-white 50%     // Right half: white
);
background-size: 230%;  // 2.3x wider than link

How the Gradient Works

1

Setup

Background is 230% wide with white on the right half. Only the left edge is visible.
2

Hover

background-position: 100% shifts the gradient to the right, revealing the white portion.
3

Result

White background sweeps in from left to right behind the text.
4

Text Color

Text changes from white to green, creating contrast against the new white background.
Diagonal gradient: The 120deg angle creates a dynamic, diagonal sweep rather than a straight horizontal slide.

Hamburger Icon

The three-line menu icon that animates to an X:
sass/components/layout/_navigation.scss:92-115
&__icon {
  position: relative;
  margin-top: 3.5rem;

  &,
  &::before,
  &::after {
    width: 3rem;
    height: 2px;
    background-color: $color-grey-dark-3;
    display: inline-block;
  }

  &::before,
  &::after {
    content: "";
    position: absolute;
    left: 0;
    transition: all .2s ease;
  }

  &::before { top: -.8rem; }
  &::after { top: .8rem; }
}

Icon Structure

Three horizontal lines created with one element and two pseudo-elements:
.navigation__icon {
  width: 3rem;
  height: 2px;
  background-color: $color-grey-dark-3;
}
The main element is the middle line.

Icon Hover Effect

Lines spread apart on hover:
sass/components/layout/_navigation.scss:117-118
&__button:hover &__icon::before { top: -1rem; }
&__button:hover &__icon::after { top: 1rem; }
Top line moves up from -0.8rem to -1rem; bottom line moves down from 0.8rem to 1rem.

Icon Transformation to X

When the menu opens, the hamburger transforms:
sass/components/layout/_navigation.scss:119-129
&__checkbox:checked + &__button &__icon { 
  background-color: transparent; 
}

&__checkbox:checked + &__button &__icon::before {
  top: 0;
  transform: rotate(135deg);
}

&__checkbox:checked + &__button &__icon::after { 
  top: 0;
  transform: rotate(-135deg); 
}

Transformation Steps

1

Hide Middle Line

background-color: transparent;
Middle line becomes invisible.
2

Move Lines to Center

top: 0;  // Both ::before and ::after
Top and bottom lines move to the middle position.
3

Rotate to Form X

transform: rotate(135deg);   // Top line
transform: rotate(-135deg);  // Bottom line
Lines rotate in opposite directions creating an X.
Why 135 degrees? This creates a perfect X shape. Each line rotates 135° from horizontal, making them perpendicular when combined (270° total difference = 360° - 90° = X shape).

JavaScript Enhancement

Optional JavaScript to close menu when clicking a link:
index.html:380-388
const navLinks = document.querySelectorAll('.navigation__link');

navLinks.forEach(link => {
  link.addEventListener('click', function () {
    document.getElementById('navi-toggle').checked = false;
  });
});
Purpose: When user clicks a navigation link, the menu automatically closes by unchecking the checkbox.
This JavaScript is optional. The navigation works without it, but this adds a better user experience for in-page navigation.

Complete Interaction Flow

1

User Clicks Button

Clicking the <label> toggles the hidden <input type="checkbox">
2

Checkbox Checked

The :checked pseudo-class becomes active on the checkbox
3

Background Expands

&__checkbox:checked ~ &__background { transform: scale(82); }
Background circle scales up to cover screen
4

Menu Appears

&__checkbox:checked ~ &__nav { opacity: 1; width: 100%; }
Navigation fades in and expands to full width
5

Icon Transforms

&__checkbox:checked + &__button &__icon { /* transform to X */ }
Hamburger icon animates to X shape

Selectors Explained

Adjacent Sibling: +

&__checkbox:checked + &__button
Selects the button that immediately follows the checked checkbox in the HTML.

General Sibling: ~

&__checkbox:checked ~ &__background
&__checkbox:checked ~ &__nav
Selects elements that are siblings (at the same level) that come after the checkbox.

Child/Descendant

&__checkbox:checked + &__button &__icon
Selects the icon inside the button that follows the checked checkbox.

Z-Index Stacking

Elements are carefully layered:
// Lowest
&__background { z-index: 1000; }  // Expanding background
&__nav { z-index: 1500; }         // Menu content
&__button { z-index: 2000; }      // Toggle button
// Highest
This ensures:
  1. Background expands behind everything
  2. Menu appears above background
  3. Button stays on top for closing

Responsive Considerations

Button Positioning

top: 6rem;   // 60px from top
right: 6rem; // 60px from right
For smaller screens, you might adjust:
@media (max-width: 56.25em) {  // 900px
  .navigation__button {
    top: 4rem;
    right: 4rem;
  }
  
  .navigation__background {
    top: 4.5rem;
    right: 4.5rem;
  }
}

Accessibility Considerations

Keyboard Navigation

The checkbox can receive keyboard focus:
<input type="checkbox" class="navigation__checkbox" 
       id="navi-toggle" title="navi-toggle" />
Consider adding visible focus styles:
.navigation__checkbox:focus + .navigation__button {
  outline: 3px solid $color-primary;
  outline-offset: 3px;
}

Screen Readers

Add ARIA labels for better accessibility:
<div class="navigation" aria-label="Main navigation">
  <input type="checkbox" class="navigation__checkbox" 
         id="navi-toggle" aria-label="Toggle navigation menu" />
  
  <label for="navi-toggle" class="navigation__button" 
         aria-label="Menu toggle button">
    <span class="navigation__icon">&nbsp;</span>
  </label>
  
  <nav class="navigation__nav" aria-label="Main menu">
    <!-- navigation items -->
  </nav>
</div>

Browser Compatibility

CSS Required:
  • Transform: All modern browsers
  • Transitions: All modern browsers
  • Sibling selectors: All browsers including IE9+
  • Checkbox hack: All browsers
No JavaScript required for core functionality, making it highly reliable.

Performance Notes

GPU Acceleration: Using transform instead of width/height for animations triggers hardware acceleration:
transform: scale(82);  // GPU accelerated ✓
This is much more performant than:
width: 4920px;  // Causes reflow ✗

Summary

The navigation component showcases:
  • Checkbox hack for stateful CSS without JavaScript
  • 3D transforms for smooth, performant animations
  • Pseudo-elements for icon creation
  • Gradient backgrounds for visual richness
  • Complex selectors for state management
  • Fixed positioning for persistent UI element
  • Z-index stacking for proper layering
  • Custom easing for organic motion
  • BEM methodology for organized, maintainable code
This component demonstrates advanced CSS techniques to create a fully functional navigation menu without relying on JavaScript for the core interaction.

Build docs developers (and LLMs) love