頁面上有一排按鈕,懸浮在窗口頂端,不隨頁面滑動而滑動,這一組按鈕分別對應的是頁面的各個部分,點擊按鈕,頁面定位到對應的位置。javascript
拿到這個需求,很天然的想到,解決這個最簡單的方法是使用錨點(能靠HTML和css解決的,儘可能不使用jscss
想到使用錨點事情就比較簡單了,借用a標籤的href定位,很快就寫了一個Demo,
完整代碼:https://codepen.io/yangyang11...
關鍵代碼:html
<div id="content"> <div class="btn-container"> <a class="btn" href="#anchor1">錨點1</a> <a class="btn" href="#anchor2">錨點2</a> <a class="btn" href="#anchor3">錨點3</a> </div> <div id="anchor1" class="anchor-con">anchor1</div> <div id="anchor2" class="anchor-con">anchor2</div> <div id="anchor3" class="anchor-con">anchor3</div> </div>
這時候,點擊懸浮的button,頁面能夠實現快速定位。java
點了幾遍以後立馬就發現了一個坑,由於按鈕是懸浮的,而錨點定位,默認是定位到窗口頂端,這樣定位到的區域就會有一部分被懸浮的按鈕擋住
以下圖:
原始狀態:
點擊「錨點1」按鈕以後(黃色框起來的部分就是被遮蓋起來的部分):
由此引出一個問題,怎麼使a標籤的錨點不定位到窗口最頂端?json
網上搜了一些方法,其中有提到使用:target,主要添加幾行css瀏覽器
#anchor1:target, #anchor2:target, #anchor3:target { padding-top: 100px; // 這裏更改padding-top的值使其定位到不一樣地方 }
效果以下圖:
雖然能夠實現文字的不被遮擋,可是實際上,對於固定大小的div來講,很容易影響div的內部佈局,故不適用我這裏的狀況(然而這裏的:target在其餘地方做用仍是很是大的。佈局
換別的思路,想了個巧辦法,在每一個須要定位的節點前面加一個輔助節點,輔助節點的高度能夠自定,錨點的實際定位的是這個輔助節點
完整代碼:https://codepen.io/yangyang11...
關鍵代碼:性能
<div class="btn-container"> <a class="btn" href="#anchor1">錨點1</a> <a class="btn" href="#anchor2">錨點2</a> <a class="btn" href="#anchor3">錨點3</a> </div> <div class="anchor-con anchor1"> <!--實際上定位的是這個輔助節點--> <div id="anchor1" class="assist-div"></div> anchor1 </div> <div class="anchor-con anchor2"> <div id="anchor2" class="assist-div"></div> anchor2 </div> <div class="anchor-con anchor3"> <div id="anchor3" class="assist-div"></div> anchor3 </div> 輔助節點的css: .assist-div { width: 1px; height: 1px; position: absolute; top: -100px; // 這裏能夠設任意高度 對應錨點最後離窗口頂端的距離 left: 0; }
這個方法的優勢:
(一)輔助節點能夠絕對定位 不影響佈局
(二)改變輔助節點的top值 能夠實現錨點定位到窗口任意位置
最後效果截圖:(點擊了「錨點2「按鈕)
測試
正當我美滋滋的交付任務,坐等1h以後的聚餐的時候,PM來找我說,不行,移動端打開的時候,我切換點了幾下懸浮的按鈕以後,要點不少下返回鍵才能退出頁面。
我:對啊由於每點一次按鈕就在瀏覽器記錄裏面添加一條記錄
PM:這不行 須要解決掉
。。。
這是個問題,須要用戶點擊不少下才能退出頁面體驗確實很差,若是想要用戶點擊一次就退出頁面,就得始終保持history只有一條記錄,可是a標籤跳轉的話自動往history加一條記錄,我也不能對此作什麼。
。。。
這時候不得不使用js了,
我盯着錨點看了會兒(實際上看了半小時:) )發現:動畫
例如http://shili.com/Demo.html#content1 這樣的url,是能夠直接定位到http://shili.com/Demo.html 這個頁面的id爲content1的節點處的,這樣的話,我不使用a標籤,直接使用js去動態改變url後面的#id 的id,也能夠實現定位的效果,而且還能實現瀏覽器只保存一條記錄。
完整代碼:https://codepen.io/yangyang11...
關鍵代碼:
去除a標籤,改成使用div,並添加click: <div class="btn-container"> <div class="btn" onclick="goToAnchor('#anchor1')">錨點1</div> <div class="btn" onclick="goToAnchor('#anchor2')">錨點2</div> <div class="btn" onclick="goToAnchor('#anchor3')">錨點3</div> </div> function goToAnchor(anchorId) { // 使用replace方法能夠保證前一次瀏覽不會在瀏覽器中保留記錄 window.location.replace(window.location.href.split('#')[0] + anchorId); }
至此,需求就完成了。
可是就頁面定位到指定位置其實還有更好的辦法,就是使用js去獲取指定位置的offsetTop,這樣的話還能夠加滑動動畫,使定位的這個過程比較平滑。我沒有使用這個方法是由於,一我開始就一心想使用錨點結果只能遇坑填坑,二個人頁面中有不少摺疊的部分(相似於手風琴效果),因此每次的offsetTop均可能是不同的,點擊時都須要去獲取offsetTop的值再移動,比較麻煩並且耗性能。(emmm雖然我一開始就抗拒使用js去解決,最後仍是使用了,可是抉擇之下仍是使用性能消耗小的比較好
這裏也丟一下采用上面這個方法的關鍵代碼
document.getElementById('content').scrollTop = document.getElementById(anchorId).offsetTop - 100;
2019.3.26日更新
使用js去實現的話,還有一種方法,使用:Element.scrollIntoView方法,我試了下,這個方法也很好用,還能夠自定義滑動方式,性能上,相較於上面的js方法要好,代碼以下:
<!DOCTYPE html> <html> <head> <title>測試</title> <style type="text/css"> html, body { width: 100%; height: 100% } </style> </head> <body> <div style="width: 100%;height: 100%;background: red" onclick="scrollToView()"></div> <div id="scroll" style="width: 100%;height: 100px;background: blue;"></div> <div style="width: 100%;height: 100%;background: red"></div> <script type="text/javascript"> function scrollToView () { document.getElementById('scroll').scrollIntoView({ block: 'start', inline: 'nearest', behavior: 'smooth' }) } </script> </body> </html>