吸頂效果方案與實現

一、場景

需求:tab需要在劃出視口的時候吸頂(sticky),方便點擊切換下方內容。

二、方案

1、采用scroll監聽+fixed定位。a) 監聽頁面被卷高度scrollTop,和 要sticky的元素距離頁面的高度offsetTop,如果前者大于后者,設置fixed樣式。b)通過getBoundingClientRect()監聽要sticky元素的位置top 和0,stickyHeight和bottom進行比較,如果前者小于后者,設置fixed樣式。

2、采用position:sticky定位。

三、position : sticky

粘性定位是相對定位和固定定位的混合。元素在跨越特定閾值例如,從視口頂部10像素)前為相對定位,之后為固定定位。

須指定top,right,bottomleft四個閾值其中之一,才可使粘性定位生效。否則其行為與相對定位相同。

四、方案實現

.fixed-top{

????position: fixed;

????left:0;

????top:0; //num

????z-index:10;

}

1-a、scroll + scrollTop +?offsetTop + fixed

$(window).scroll(function(){

????var $stickyEl = $('.sticky');

????var scrollT = $(window).scrollTop();

????if (scrollT > (_stickyT-num)) { //num是吸頂時距離viewport頂部的距離

????????$stickyEl.addClass('fixed-top');

????} else {

????????$stickyEl.removeClass('fixed-top');

????}

});

1-b、scroll +?getBoundingClientRect +?fixed

$(window).scroll(function() {

????var $stickyEl = $('.sticky');

????var rect = $stickyEl.getBoundingClientRect();

????if(rect.top < 0 && (rect.bottom - stickyHeight) > 0) {

????????!$stickyEl.hasClass('fixed-top') && $stickyEl.addClass('fixed-top').css('width', stickyWidth +'px');

????}else{

????????$stickyEl.hasClass('fixed-top') && $stickyEl.removeClass('fixed-top').css('width','auto');

????}

});

或者

vardocClientWidth = document.documentElement.clientHeight;

rect.bottom > docClientWidth && (rect.top + stickyHeight) < docClientWidth;

2、sticky樣式

.sticky-top{

????position: -webkit-sticky;

????position: sticky;

????top:0;

????left:0;

????z-index:10;

}

五、整體實現

思路:

1)通過sticky屬性值是否可用的監測,如果可以,采用方案2,如果不可以,采用方案1-a;

2)在使用方案1-a時,滾動實時監聽會帶來頻繁的調用回調函數,引來性能問題,在此采用函數截流的方式解決;

3)在接觸到閥值臨界是會有跳動,這是因為當sticky元素被固定的時候,它會脫離普通文檔流,所以要利用它的父元素把sticky元素的高度在普通文檔流中撐起來,以免在固定效果出現的時候,target元素的內容出現跳動的情況。

ps:(1)一般還是采用scroll,但是ios只有在滾動停止時才會調用回調函數;所以找到了sticky;但是sticky對低版本兼容度不夠,但是對目前主流及高版本android和ios兼容度還ok,所以采用sticky優先的原則,判斷是否支持sticky,來實現。

整體實現:

js:

//吸頂start

varfixTop={

????stickyEl :$('.sticky'),

????stickyT:function() {

????????returnthis.stickyEl.offset().top;

????},

????num? ? ? :0,????

????// bannerImg: document.getElementById("bannerImg"),

????init:function(){

????????// var u = navigator.userAgent;

????????// var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1;????

????????// var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);

????????var_num=this.num;

????????varisSupportSticky=this.isSupportSticky();

????????if(isSupportSticky) {

????????????this.sticky();

????????????return;

????????}

????????this.scroll(_num);

????},

? ? scroll:function(num){//滾動監聽添加fixed樣式

????????var_this=this;

????????var_stickyT=_this.stickyT();

????????this.stickyHolder();

????????$(window).scroll(this.throttle(function(){

????????// var scrollT = document.body.scrollTop;

????????varscrollT=$(window).scrollTop();

????????// console.log(scrollT,_stickyT-num);

????????if(scrollT>(_stickyT-num)) {

????????????_this.stickyEl.addClass('fixed-top');

????????}else{

????????????_this.stickyEl.removeClass('fixed-top');

????????}

????},10));

????},????

????sticky:function(){//添加sticky樣式

????????var_this=this;

????????_this.stickyEl.addClass('sticky-top');

????},

? ? ? ?isSupportSticky:function(){//判斷是否支持sticky

? ? ? ?varprefixTestList=['','-webkit-'];

????????varstickyText='';

? ? ? ??for(vari=0;i<prefixTestList.length;i++) {

stickyText+='position:'+prefixTestList[i]+'sticky;';

}

// 創建一個dom來檢查

vardiv=document.createElement('div');

div.style.cssText=stickyText;

document.body.appendChild(div);

varisSupport=/sticky/i.test(window.getComputedStyle(div).position);

document.body.removeChild(div);

div=null;

returnisSupport;

},

stickyHolder:function(){//守家占位符

varstickyHolder=document.createElement('div');

varstickyElDom=this.stickyEl.get(0);

varrect=stickyElDom.getBoundingClientRect();

// console.log(rect);

stickyElDom.parentNode.replaceChild(stickyHolder,stickyElDom);

stickyHolder.appendChild(stickyElDom);

stickyHolder.style.height=rect.height+'px';

},

throttle:function(func, wait){//函數截流

vartimer=null;

returnfunction() {

varself=this,

args=arguments;

if(timer)clearTimeout(timer);

timer=setTimeout(function() {

returntypeoffunc==='function'&&func.apply(self,args);

},wait);

}

}

}

fixTop.init();

//吸頂end

html:

<body>

????<div class="banner"></div>

????<div class="tab sticky"></div>

????<div?class="content"></div>

</body>

css:

body{

margin:0;

}

div{

width:100%;

}

.banner{

/* overflow: hidden; */

height:500px;

background-color: yellowgreen;

}

.tab{

height:80px;

background-color: blue;

}

.content{

height:3000px;

}

.fixed-top{

position: fixed;

/*width: 100%;*/

left:0;

top:0;

z-index:10;

}

.sticky-top{

/* 滾過初始位置時自動吸頂 */

/*? */

position: -webkit-sticky;

position: sticky;

top:0;

left:0;

z-index:10;

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,107評論 2 375