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
< 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 >
< 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
Toggle Logic
How It Works
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' );
});
});
}
Toggle Button : Clicking the hamburger icon toggles the hidden class on the mobile menu
Auto-Close : When a navigation link is clicked, the menu automatically closes
Responsive : The mobile menu only appears on screens smaller than md (768px)
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
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:
Monitors scroll position with a scroll event listener
Compares scroll position against each section’s offset
Adds active-nav class to the corresponding navigation link
Triggers visual underline effect via CSS
CSS Styling
Navigation Link Hover Effect
estilos.css (lines 79-100)
.nav-link {
position : relative ;
}
.nav-link::after {
content : '' ;
position : absolute ;
width : 0 ;
height : 2 px ;
bottom : -5 px ;
left : 0 ;
background-color : #E50914 ;
transition : width 0.3 s ease ;
}
.nav-link:hover::after {
width : 100 % ;
}
.active-nav::after {
width : 100 % ;
}
Understanding the Underline Effect
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
Adding a New Navigation Link
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 >
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 >
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 */
}
To change the fixed header height:
Update the py-4 class in the header container (line 27)
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 Size Behavior CSS Class Mobile (< 768px) Hamburger menu visible, nav links hidden md:hiddenTablet/Desktop (≥ 768px) Full navigation visible, hamburger hidden hidden 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
Mobile menu not closing after clicking link
Sections hidden behind fixed header
Active navigation not highlighting correctly
Adjust the scroll threshold in highlightSection() function: if ( pageYOffset >= sec . offsetTop - 150 ) {
// Increase from 100 to 150
}