【JavaScript 实现导航栏顶部吸附效果】
JavaScript 实现导航栏顶部吸附效果
导航栏顶部吸附(Sticky Navigation)是网页设计中常见的交互效果,当用户滚动页面时,导航栏会固定在浏览器窗口顶部。以下是几种实现方法:
方法一:纯CSS实现(推荐)
最简单的方法是使用CSS的position: sticky属性:
.navbar {position: sticky;top: 0;z-index: 1000;background-color: white;padding: 15px 0;box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
优点:
无需JavaScript
性能最佳
实现简单
浏览器支持:所有现代浏览器都支持sticky定位
方法二:JavaScript实现
如果需要更复杂的控制或支持旧版浏览器,可以使用JavaScript:
基本实现
window.addEventListener('scroll', function() {const navbar = document.querySelector('.navbar');const scrollPosition = window.scrollY;if (scrollPosition > 100) { // 滚动超过100px时固定navbar.classList.add('sticky');} else {navbar.classList.remove('sticky');}
});
对应CSS:
.navbar {position: relative;transition: all 0.3s ease;
}.navbar.sticky {position: fixed;top: 0;width: 100%;animation: slideDown 0.3s ease-out;
}@keyframes slideDown {from { transform: translateY(-100%); }to { transform: translateY(0); }
}
优化版本(避免布局抖动)
function stickyNav() {const navbar = document.querySelector('.navbar');const navbarHeight = navbar.offsetHeight;const placeholder = document.createElement('div');placeholder.style.height = navbarHeight + 'px';window.addEventListener('scroll', function() {if (window.scrollY > 100) {navbar.classList.add('sticky');navbar.parentNode.insertBefore(placeholder, navbar);} else {navbar.classList.remove('sticky');if (document.body.contains(placeholder)) {placeholder.remove();}}});
}document.addEventListener('DOMContentLoaded', stickyNav);
方法三:Intersection Observer API(现代方法)
const observer = new IntersectionObserver((entries) => {entries.forEach(entry => {const navbar = document.querySelector('.navbar');if (!entry.isIntersecting) {navbar.classList.add('sticky');} else {navbar.classList.remove('sticky');}});},{ threshold: 0.1 }
);const header = document.querySelector('header');
observer.observe(header);
完整示例代码
<!DOCTYPE html>
<html>
<head>
<style>body {margin: 0;font-family: Arial;height: 2000px; /* 为了演示滚动 */}header {height: 200px;background: lightblue;display: flex;align-items: center;justify-content: center;}.navbar {background: #333;color: white;padding: 15px;text-align: center;transition: all 0.3s ease;}.sticky {position: fixed;top: 0;width: 100%;box-shadow: 0 2px 5px rgba(0,0,0,0.2);animation: slideDown 0.3s ease-out;}@keyframes slideDown {from { transform: translateY(-100%); }to { transform: translateY(0); }}.content {padding: 20px;}
</style>
</head>
<body><header><h1>网站标题</h1>
</header><nav class="navbar"><a href="#">首页</a> |<a href="#">产品</a> |<a href="#">服务</a> |<a href="#">关于我们</a> |<a href="#">联系我们</a>
</nav><div class="content"><p>页面内容...</p>
</div><script>
document.addEventListener('DOMContentLoaded', function() {const navbar = document.querySelector('.navbar');const header = document.querySelector('header');const headerHeight = header.offsetHeight;const placeholder = document.createElement('div');window.addEventListener('scroll', function() {if (window.scrollY > headerHeight) {if (!navbar.classList.contains('sticky')) {placeholder.style.height = navbar.offsetHeight + 'px';navbar.parentNode.insertBefore(placeholder, navbar);}navbar.classList.add('sticky');} else {navbar.classList.remove('sticky');if (document.body.contains(placeholder)) {placeholder.remove();}}});
});
</script></body>
</html>
性能优化建议
防抖处理:减少scroll事件的触发频率
function debounce(func, wait = 10) {let timeout;return function() {const context = this;const args = arguments;clearTimeout(timeout);timeout = setTimeout(() => func.apply(context, args), wait);};
}window.addEventListener('scroll', debounce(stickyNav));
使用transform代替top(提升动画性能)
.sticky {position: fixed;transform: translateY(0);/* 而不是 top: 0; */
}
避免强制同步布局(减少reflow)
// 不好的做法 - 会导致强制同步布局
const height = element.offsetHeight;
element.style.height = height + 'px';// 好的做法 - 使用requestAnimationFrame
requestAnimationFrame(() => {const height = element.offsetHeight;element.style.height = height + 'px';
});
浏览器兼容性
对于旧版浏览器(如IE11),需要使用polyfill:
<!-- 为IE11提供classList支持 -->
<script src="https://cdn.jsdelivr.net/npm/classlist-polyfill@1.2.0/src/index.min.js"></script>
或者使用jQuery实现:
$(window).scroll(function() {if ($(this).scrollTop() > 100) {$('.navbar').addClass('sticky');} else {$('.navbar').removeClass('sticky');}
});
根据项目需求选择最适合的实现方式,现代项目博主推荐优先使用CSS的sticky定位,既简单又高效。