Skip to main content

Overview

The navigation component provides a fixed header with smooth scrolling navigation links, a responsive mobile hamburger menu, and automatic active section highlighting as users scroll.

HTML Structure

Desktop Navigation

index.html (lines 26-40)
<header class="fixed w-full bg-black bg-opacity-90 z-50 shadow-lg">
  <div class="container mx-auto px-6 py-4">
    <div class="flex justify-between items-center">
      <h1 class="text-2xl font-bold red-accent">NILVER <span class="text-white">T.I</span></h1>
      <nav class="hidden md:block">
        <ul class="flex space-x-8">
          <li><a href="#home" class="nav-link text-white hover:text-red-accent transition">Inicio</a></li>
          <li><a href="#skills" class="nav-link text-white hover:text-red-accent transition">Habilidades</a></li>
          <li><a href="#projects" class="nav-link text-white hover:text-red-accent transition">Proyectos</a></li>
          <li><a href="#contact" class="nav-link text-white hover:text-red-accent transition">Contacto</a></li>
        </ul>
      </nav>
      <button class="md:hidden text-white focus:outline-none" id="mobileMenuButton">
        <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
        </svg>
      </button>
    </div>
  </div>
</header>

Mobile Navigation Menu

index.html (lines 49-56)
<div class="md:hidden hidden bg-black py-4" id="mobileMenu">
  <ul class="flex flex-col items-center space-y-4">
    <li><a href="#home" class="nav-link text-white hover:text-red-accent transition">Inicio</a></li>
    <li><a href="#skills" class="nav-link text-white hover:text-red-accent transition">Habilidades</a></li>
    <li><a href="#projects" class="nav-link text-white hover:text-red-accent transition">Proyectos</a></li>
    <li><a href="#contact" class="nav-link text-white hover:text-red-accent transition">Contacto</a></li>
  </ul>
</div>

JavaScript Functionality

Mobile Menu Toggle

main.js (lines 5-17)
const mobileBtn = document.getElementById('mobileMenuButton');
const mobileMenu = document.getElementById('mobileMenu');
if (mobileBtn && mobileMenu) {
  mobileBtn.addEventListener('click', () => {
    mobileMenu.classList.toggle('hidden');
  });

  // Auto-close menu when clicking a link
  mobileMenu.querySelectorAll('a').forEach(link => {
    link.addEventListener('click', () => {
      mobileMenu.classList.add('hidden');
    });
  });
}

Smooth Scroll Navigation

main.js (lines 19-31)
const navLinks = document.querySelectorAll('a[href^="#"]');
navLinks.forEach(link => {
  link.addEventListener('click', e => {
    e.preventDefault();
    const targetId = link.getAttribute('href');
    const section = document.querySelector(targetId);
    if (section) {
      window.scrollTo({ top: section.offsetTop - 80, behavior: 'smooth' });
    }
    document.querySelectorAll('.nav-link').forEach(nav => nav.classList.remove('active-nav'));
    link.classList.add('active-nav');
  });
});
The offsetTop - 80 calculation accounts for the fixed header height, ensuring content isn’t hidden behind the navigation when scrolling to a section.

Active Section Highlighting

main.js (lines 33-47)
function highlightSection() {
  const sections = document.querySelectorAll('section');
  let current = '';
  sections.forEach(sec => {
    if (pageYOffset >= sec.offsetTop - 100) {
      current = sec.id;
    }
  });
  navLinks.forEach(link => {
    link.classList.remove('active-nav');
    if (link.getAttribute('href') === `#${current}`) link.classList.add('active-nav');
  });
}
window.addEventListener('scroll', highlightSection);
highlightSection(); // Initialize on page load
How it works:
  1. Monitors scroll position with a scroll event listener
  2. Compares scroll position against each section’s offset
  3. Adds active-nav class to the corresponding navigation link
  4. Triggers visual underline effect via CSS

CSS Styling

estilos.css (lines 79-100)
.nav-link {
  position: relative;
}

.nav-link::after {
  content: '';
  position: absolute;
  width: 0;
  height: 2px;
  bottom: -5px;
  left: 0;
  background-color: #E50914;
  transition: width 0.3s ease;
}

.nav-link:hover::after {
  width: 100%;
}

.active-nav::after {
  width: 100%;
}
  • The ::after pseudo-element creates an animated underline
  • Starts at width: 0 and expands to 100% on hover
  • The active-nav class keeps the underline visible for the current section
  • Positioned 5px below the link text with bottom: -5px

Customization

1

Update Desktop Navigation

Add a new list item in the desktop <nav> section:
<li><a href="#about" class="nav-link text-white hover:text-red-accent transition">About</a></li>
2

Update Mobile Menu

Add the same link in the mobile menu:
<li><a href="#about" class="nav-link text-white hover:text-red-accent transition">About</a></li>
3

Create the Section

Add a corresponding section with matching ID:
<section id="about" class="py-20 bg-black bg-opacity-50">
  <!-- Section content -->
</section>

Changing the Accent Color

Update the red accent color throughout the navigation:
.red-accent {
  color: #E50914; /* Change to your color */
}

.nav-link::after {
  background-color: #E50914; /* Match the accent color */
}

Adjusting Header Height

To change the fixed header height:
  1. Update the py-4 class in the header container (line 27)
  2. Adjust the scroll offset in main.js line 26:
    window.scrollTo({ top: section.offsetTop - 100, behavior: 'smooth' });
    // Change 80 to match your new header height
    

Responsive Behavior

Screen SizeBehaviorCSS Class
Mobile (< 768px)Hamburger menu visible, nav links hiddenmd:hidden
Tablet/Desktop (≥ 768px)Full navigation visible, hamburger hiddenhidden md:block

Accessibility Features

Keyboard Navigation

All navigation links are focusable and accessible via Tab key

Semantic HTML

Uses proper <header> and <nav> elements for screen readers

Focus States

Button includes focus:outline-none with visible hover states

ARIA Labels

Consider adding aria-label="Main navigation" to the nav element
Recommended Enhancement: Add an aria-label to the mobile menu button for better screen reader support:
<button aria-label="Toggle mobile menu" id="mobileMenuButton">

Complete Example

Here’s a full working example with all features:
Complete Navigation Component
<!-- Header -->
<header class="fixed w-full bg-black bg-opacity-90 z-50 shadow-lg">
  <div class="container mx-auto px-6 py-4">
    <div class="flex justify-between items-center">
      <h1 class="text-2xl font-bold red-accent">NILVER <span class="text-white">T.I</span></h1>
      <nav class="hidden md:block">
        <ul class="flex space-x-8">
          <li><a href="#home" class="nav-link text-white hover:text-red-accent transition">Inicio</a></li>
          <li><a href="#skills" class="nav-link text-white hover:text-red-accent transition">Habilidades</a></li>
          <li><a href="#projects" class="nav-link text-white hover:text-red-accent transition">Proyectos</a></li>
          <li><a href="#contact" class="nav-link text-white hover:text-red-accent transition">Contacto</a></li>
        </ul>
      </nav>
      <button class="md:hidden text-white focus:outline-none" id="mobileMenuButton">
        <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
        </svg>
      </button>
    </div>
  </div>
  <div class="md:hidden hidden bg-black py-4" id="mobileMenu">
    <ul class="flex flex-col items-center space-y-4">
      <li><a href="#home" class="nav-link text-white hover:text-red-accent transition">Inicio</a></li>
      <li><a href="#skills" class="nav-link text-white hover:text-red-accent transition">Habilidades</a></li>
      <li><a href="#projects" class="nav-link text-white hover:text-red-accent transition">Proyectos</a></li>
      <li><a href="#contact" class="nav-link text-white hover:text-red-accent transition">Contacto</a></li>
    </ul>
  </div>
</header>

<script>
// Initialize navigation
const mobileBtn = document.getElementById('mobileMenuButton');
const mobileMenu = document.getElementById('mobileMenu');
const navLinks = document.querySelectorAll('a[href^="#"]');

// Mobile menu toggle
mobileBtn?.addEventListener('click', () => {
  mobileMenu.classList.toggle('hidden');
});

// Smooth scroll
navLinks.forEach(link => {
  link.addEventListener('click', e => {
    e.preventDefault();
    const section = document.querySelector(link.getAttribute('href'));
    if (section) {
      window.scrollTo({ top: section.offsetTop - 80, behavior: 'smooth' });
      mobileMenu.classList.add('hidden');
    }
  });
});

// Active section highlighting
window.addEventListener('scroll', () => {
  const sections = document.querySelectorAll('section');
  let current = '';
  sections.forEach(sec => {
    if (pageYOffset >= sec.offsetTop - 100) current = sec.id;
  });
  navLinks.forEach(link => {
    link.classList.remove('active-nav');
    if (link.getAttribute('href') === `#${current}`) link.classList.add('active-nav');
  });
});
</script>

Troubleshooting

Increase the offset value in the smooth scroll calculation:
window.scrollTo({ top: section.offsetTop - 100, behavior: 'smooth' });
// Increase from 80 to 100 or higher
Adjust the scroll threshold in highlightSection() function:
if (pageYOffset >= sec.offsetTop - 150) {
  // Increase from 100 to 150
}

Build docs developers (and LLMs) love