目標
實作當 scroll 超過導覽列時,導覽列固定在最頂端的效果
step 1 : 取得 HTML 頁面中的元素,以及導覽列頂部距離與
const nav = document.querySelector('#main') // 選取導覽列
let topOfNav = nav.offsetTop // 導覽列 nav 頂部到 window 的距離
step 2 : 監聽 window 的 scroll 事件,scroll 發生時觸發 fixNav function
window.scrollY
: 垂直 scroll 的距離。
element.offsetTop
: 該元素到頂端的距離。
offsetParent
: 與元素最近的,有被定位(position 不為 static)的父層。
function fixNav(){
// 如果捲軸 Y軸方向捲動的量超過 nav 到頂部的距離
if(window.scrollY >= topOfNav){
//增加 fixed-nav 這個 class name
document.body.classList.add('fixed-nav')
// position 被設定為 fixed 時,不佔據原有的高度
// 因此設定在 body 設定 padding-top (導覽列的 offsetHeight)
// 讓下方的區塊不會往上跳動(jerky jump)
document.body.style.paddingTop = nav.offsetHeight + 'px'
}else{
//移除 fixed-nav 這個 class name
document.body.classList.remove('fixed-nav')
//清除 padding-top
document.body.style.paddingTop=''
}
}}
window.addEventListener('scroll', fixNav)
css
/* 在 body 添加 class name = fixed-nav 時*/
.fixed-nav .site-wrap {
/* 下方頁面區塊有放大效果 */
transform: scale(1);
}
.fixed-nav nav {
/* 導覽列的 position 改為 fixed ,固定在上方,並加上陰影 */
position: fixed;
box-shadow: 0 5px rgba(0,0,0,0.1);
}
.fixed-nav li.logo {
/* 把 logo 因爲寬度增加而顯示*/
/* max-width 才能有 transition 動畫效果,width沒有*/
max-width: 500px;
}
參考資料:
- Element: getBoundingClientRect() method @MDN
- Vanilla JavaScript Sticky Nav - #JavaScript30 24/30 @Wes Bos
- [ Alex 宅幹嘛 ] 👨💻 深入淺出 Javascript30 快速導覽 | Day 24:Sticky Nav @Alex 宅幹嘛
- 24 - Sticky Nav @guahsu
- Sticky Nav@dusin
- JS30-Day24-Sticky Nav@王郁翔
- JS30 自學筆記 Day24_Sticky Nav@jen147774ny
- JS30 讀書會 Day 24 - Sticky Nav@Raye