使用智能 CSS 基于用戶滾動(dòng)位置應(yīng)用樣式
通過將當(dāng)前滾動(dòng)偏移量添加到到 html 元素的屬性上,我們可以根據(jù)當(dāng)前滾動(dòng)位置設(shè)置網(wǎng)頁(yè)上的元素樣式。我們可以使用它來(lái)構(gòu)建一個(gè)浮動(dòng)在網(wǎng)頁(yè)頂部的導(dǎo)航組件。
這是我們將使用的 HTML,<header> 組件是我們盼望當(dāng)我們向下滾動(dòng)時(shí),始終浮動(dòng)在網(wǎng)頁(yè)頂部的一個(gè)組件。
<header>I'm the page header</header> <p>Lot's of content here...</p> <p>More beautiful content...</p> <p>Content...</p>
首先,我們將監(jiān)聽 document 上的 'scroll' 事件,并且每次用戶滾動(dòng)時(shí)我們都會(huì)掏出當(dāng)前的 scrollY 值。
document.addEventListener('scroll', () => { document.documentElement.dataset.scroll = window.scrollY; });
我們將滾動(dòng)位置存儲(chǔ)在 html 元素的數(shù)據(jù)屬性中。假如您使用開發(fā)工具查看 DOM,它將如下所示:<html data-scroll="0">
如今我們可以使用此屬性來(lái)設(shè)置網(wǎng)頁(yè)上的元素樣式。
/* 保證 header標(biāo)簽始終高于 3em */ header { min-height: 3em; width: 100%; background-color: #fff; } /* 在網(wǎng)頁(yè)頂部保留與 header 的 min-height 雷同的高度 */ html:not([data-scroll='0']) body { padding-top: 3em; } /* 將 header 標(biāo)簽切換成 fixed 定位模式,并且將它固定在網(wǎng)頁(yè)頂部 */ html:not([data-scroll='0']) header { position: fixed; top: 0; z-index: 1; /* box-shadow 屬性能夠加強(qiáng)浮動(dòng)的結(jié)果 */ box-shadow: 0 0 .5em rgba(0, 0, 0, .5); }
基本上就是如許,當(dāng)用戶向下滾動(dòng)時(shí),header 標(biāo)簽將主動(dòng)從網(wǎng)頁(yè)中星散并浮動(dòng)在內(nèi)容之上。javascript 代碼并不關(guān)心這一點(diǎn),它的義務(wù)就是將滾動(dòng)偏移量放在數(shù)據(jù)屬性中。這很完善,由于 javascript 和 CSS 之間沒有緊密耦合。
但仍有一些可以改進(jìn)的地方,重要是在性能方面。
首先,我們必須修改 javascript 腳本,以適應(yīng)網(wǎng)頁(yè)加載時(shí)滾動(dòng)位置不在頂部的情況。在如許的情況下,header 標(biāo)簽將呈現(xiàn)錯(cuò)誤的樣式。
網(wǎng)頁(yè)加載時(shí),我們必須快速獲取當(dāng)前的滾動(dòng)偏移量,如許確保了我們始終與當(dāng)前的網(wǎng)頁(yè)的狀況同步。
// 讀出當(dāng)前網(wǎng)頁(yè)的滾動(dòng)位置并將其存入 document 的 data 屬性中 // 因此我們就可以在我們的樣式表中使用它 const storeScroll = () => { document.documentElement.dataset.scroll = window.scrollY; } // 監(jiān)聽滾動(dòng)事件 document.addEventListener('scroll', storeScroll); // 第一次打開網(wǎng)頁(yè)時(shí)就更新滾動(dòng)位置 storeScroll();
接下來(lái)我們將看一些性能方面改進(jìn)。假如我們想要獲取 scrollY 滾動(dòng)位置,欣賞器將必須計(jì)算網(wǎng)頁(yè)上每個(gè)元素的位置,以確保它返回精確的位置。假如我們不強(qiáng)制它每次滾動(dòng)都取值才是最好的做法。
要做到這一點(diǎn),我們必要一個(gè) debounce(防抖動(dòng))方法,這個(gè)方法會(huì)將我們的取值請(qǐng)求加入一個(gè)隊(duì)列中,在欣賞器預(yù)備好繪制下一幀之前都不會(huì)重新取值,此時(shí)它已經(jīng)計(jì)算出了網(wǎng)頁(yè)上所有元素的位置,所以它不會(huì)賡續(xù)重復(fù)雷同的工作。
// 防抖動(dòng)函數(shù)接受一個(gè)我們自定義的函數(shù)作為參數(shù) const debounce = (fn) => { // 這包含了對(duì) requestAnimationFrame 的引用,所以我們可以在我們盼望的任何時(shí)候制止它 let frame; // 防抖動(dòng)函數(shù)將返回一個(gè)可以接受多個(gè)參數(shù)的新函數(shù) return (...params) => { // 假如 frame 的值存在,那就消滅對(duì)應(yīng)的回調(diào) if (frame) { cancelAnimationFrame(frame); } // 使我們的回調(diào)在欣賞器下一幀刷新時(shí)實(shí)行 frame = requestAnimationFrame(() => { // 實(shí)行我們的自定義函數(shù)并傳遞我們的參數(shù) fn(...params); }); } }; // Reads out the scroll position and stores it in the data attribute // so we can use it in our stylesheets const storeScroll = () => { document.documentElement.dataset.scroll = window.scrollY; } // Listen for new scroll events, here we debounce our `storeScroll` function document.addEventListener('scroll', debounce(storeScroll)); // Update scroll position for first time storeScroll();
通過標(biāo)記事件為 passive 狀況,我們可以告訴欣賞器我們的滾動(dòng)事件不會(huì)被觸摸交互阻止(例如與谷歌地圖等插件交互時(shí))。這許可欣賞器立即滾動(dòng)網(wǎng)頁(yè),由于它如今知道該事件不會(huì)被阻止。
document.addEventListener('scroll', debounce(storeScroll), { passive: true });
解決了性能題目后,我們?nèi)缃窨梢酝ㄟ^穩(wěn)固的體例使用 javascript 將獲取的數(shù)據(jù)提供應(yīng) CSS,并可以使用它來(lái)為網(wǎng)頁(yè)上的元素添加樣式。
以上就是本文的悉數(shù)內(nèi)容,盼望對(duì)大家的學(xué)習(xí)有所幫助,也盼望大家多多支持圖趣網(wǎng)。
本文地址:http://m.pkvc.cn/tutorial/wd496.html
- 專訪:石墨文檔產(chǎn)品總監(jiān)羅穎
- UI設(shè)計(jì)不得不知的移動(dòng)端UI尺寸適
- 光音移動(dòng)設(shè)計(jì)規(guī)范 — 表單類
- 體驗(yàn)設(shè)計(jì)中的排序問題
- 網(wǎng)頁(yè)設(shè)計(jì)精粹 網(wǎng)頁(yè)中那些迷人的按
- aliued:響應(yīng)式設(shè)計(jì)的現(xiàn)狀與趨勢(shì)
- 10個(gè)智能對(duì)象處理的ps技巧
- 網(wǎng)頁(yè)UI - 原子設(shè)計(jì)理論(上)
- 如何通過設(shè)計(jì)提升banner點(diǎn)擊率?
- 晉小彥視覺設(shè)計(jì)系列文章(二):全屏