5种回到顶部的写法从实现到增强 - 小火柴的蓝色理想 - 博客园


难度 中等

前面的话

  本文先详细介绍回到顶部的5种写法,然后对其实现功能增加,最后得到最终实现

写法

【1】锚点

  使用锚点链接是一种简单的返回顶部的功能实现。该实现主要在页面顶部放置一个指定名称的锚点链接,然后在页面下方放置一个返回到该锚点的链接,用户点击该链接即可返回到该锚点所在的顶部位置

  [注意]关于锚点的详细信息移步至此

<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
    <span><</span><span>div </span><span>id</span><span>="topAnchor"</span><span>></</span><span>div</span><span>></span>
    <span><</span><span>a </span><span>href</span><span>="#topAnchor"</span><span> style</span><span>="position:fixed;right:0;bottom:0"</span><span>></span>回到顶部<span></</span><span>a</span><span>></span>
<span></</span><span>body</span><span>></span>

【2】scrollTop

  scrollTop属性表示被隐藏在内容区域上方的像素数。元素未滚动时,scrollTop的值为0,如果元素被垂直滚动了,scrollTop的值大于0,且表示元素上方不可见内容的像素宽度

  由于scrollTop是可写的,可以利用scrollTop来实现回到顶部的功能

  [注意]关于页面的scrollTop的兼容问题详细内容移步至此

复制代码

<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
    <span><</span><span>button </span><span>id</span><span>="test"</span><span> style</span><span>="position:fixed;right:0;bottom:0"</span><span>></span>回到顶部<span></</span><span>button</span><span>></span>
    <span><</span><span>script</span><span>></span><span>
        test.onclick </span><span>=</span> <span>function</span><span>(){
            document.body.scrollTop </span><span>=</span><span> document.documentElement.scrollTop </span><span>=</span> <span>0</span><span>;
        }
    </span><span></</span><span>script</span><span>></span>
<span></</span><span>body</span><span>></span>

复制代码

【3】scrollTo()

  scrollTo(x,y)方法滚动当前window中显示的文档,让文档中由坐标x和y指定的点位于显示区域的左上角

  设置scrollTo(0,0)可以实现回到顶部的效果

复制代码

<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
    <span><</span><span>button </span><span>id</span><span>="test"</span><span> style</span><span>="position:fixed;right:0;bottom:0"</span><span>></span>回到顶部<span></</span><span>button</span><span>></span>
    <span><</span><span>script</span><span>></span><span>
        test.onclick </span><span>=</span> <span>function</span><span>(){
            scrollTo(</span><span>0</span><span>,</span><span>0</span><span>);
        }
    </span><span></</span><span>script</span><span>></span>
<span></</span><span>body</span><span>></span>

复制代码

【4】scrollBy()

  scrollBy(x,y)方法滚动当前window中显示的文档,x和y指定滚动的相对量

  只要把当前页面的滚动长度作为参数,逆向滚动,则可以实现回到顶部的效果

复制代码

<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
    <span><</span><span>button </span><span>id</span><span>="test"</span><span> style</span><span>="position:fixed;right:0;bottom:0"</span><span>></span>回到顶部<span></</span><span>button</span><span>></span>
    <span><</span><span>script</span><span>></span><span>
        test.onclick </span><span>=</span> <span>function</span><span>(){
            </span><span>var</span><span> top </span><span>=</span><span> document.body.scrollTop </span><span>||</span><span> document.documentElement.scrollTop
            scrollBy(</span><span>0</span><span>,</span><span>-</span><span>top);
        }
    </span><span></</span><span>script</span><span>></span>
<span></</span><span>body</span><span>></span>

复制代码

【5】scrollIntoView()

  Element.scrollIntoView方法滚动当前元素,进入浏览器的可见区域 

  该方法可以接受一个布尔值作为参数。如果为true,表示元素的顶部与当前区域的可见部分的顶部对齐(前提是当前区域可滚动);如果为false,表示元素的底部与当前区域的可见部分的尾部对齐(前提是当前区域可滚动)。如果没有提供该参数,默认为true

  使用该方法的原理与使用锚点的原理类似,在页面最上方设置目标元素,当页面滚动时,目标元素被滚动到页面区域以外,点击回到顶部按钮,使目标元素重新回到原来位置,则达到预期效果

复制代码

<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
    <span><</span><span>div </span><span>id</span><span>="target"</span><span>></</span><span>div</span><span>></span>
    <span><</span><span>button </span><span>id</span><span>="test"</span><span> style</span><span>="position:fixed;right:0;bottom:0"</span><span>></span>回到顶部<span></</span><span>button</span><span>></span>
    <span><</span><span>script</span><span>></span><span>
        test.onclick </span><span>=</span> <span>function</span><span>(){
            target.scrollIntoView();
        }
    </span><span></</span><span>script</span><span>></span>
<span></</span><span>body</span><span>></span>

复制代码

增强

  下面对回到顶部的功能进行增强

【1】显示增强

  使用CSS画图,将“回到顶部”变成可视化的图形(如果兼容IE8-浏览器,则用图片代替)

  使用CSS伪元素及伪类hover效果,当鼠标移动到该元素上时,显示回到顶部的文字,移出时不显示  

复制代码

<span><</span><span>style</span><span>></span><span>
.box</span><span>{</span><span>
    position</span><span>:</span><span>fixed</span><span>;</span><span>
    right</span><span>:</span><span>10px</span><span>;</span><span>
    bottom</span><span>:</span><span> 10px</span><span>;</span><span>
    height</span><span>:</span><span>30px</span><span>;</span><span>
    width</span><span>:</span><span> 50px</span><span>;</span><span>    
    text-align</span><span>:</span><span>center</span><span>;</span><span>
    padding-top</span><span>:</span><span>20px</span><span>;</span><span>    
    background-color</span><span>:</span><span> lightblue</span><span>;</span><span>
    border-radius</span><span>:</span><span> 20%</span><span>;</span><span>
    overflow</span><span>:</span><span> hidden</span><span>;</span>
<span>}</span><span>
.box:hover:before</span><span>{</span><span>
    top</span><span>:</span><span>50%
</span><span>}</span><span>
.box:hover .box-in</span><span>{</span><span>
    visibility</span><span>:</span><span> hidden</span><span>;</span>
<span>}</span><span>
.box:before</span><span>{</span><span>
    position</span><span>:</span><span> absolute</span><span>;</span><span>
    top</span><span>:</span><span> -50%</span><span>;</span><span>
    left</span><span>:</span><span> 50%</span><span>;</span><span>
    transform</span><span>:</span><span> translate(-50%,-50%)</span><span>;</span><span>
    content</span><span>:</span><span>'回到顶部'</span><span>;</span><span>
    width</span><span>:</span><span> 40px</span><span>;</span><span>
    color</span><span>:</span><span>peru</span><span>;</span><span>
    font-weight</span><span>:</span><span>bold</span><span>;</span>

<span>}</span><span>    
.box-in</span><span>{</span><span>
    visibility</span><span>:</span><span> visible</span><span>;</span><span>
    display</span><span>:</span><span>inline-block</span><span>;</span><span>
    height</span><span>:</span><span>20px</span><span>;</span><span>
    width</span><span>:</span><span> 20px</span><span>;</span><span>
    border</span><span>:</span><span> 3px solid black</span><span>;</span><span>
    border-color</span><span>:</span><span> white transparent transparent white</span><span>;</span><span>
    transform</span><span>:</span><span>rotate(45deg)</span><span>;</span>
<span>}</span>
<span></</span><span>style</span><span>></span>

<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
<span><</span><span>div </span><span>id</span><span>="box"</span><span> class</span><span>="box"</span><span>></span>
    <span><</span><span>div </span><span>class</span><span>="box-in"</span><span>></</span><span>div</span><span>></span>
<span></</span><span>div</span><span>></span>    
<span></</span><span>body</span><span>></span>

复制代码

【2】动画增强

  为回到顶部增加动画效果,滚动条以一定的速度回滚到顶部

  动画有两种:一种是CSS动画,需要有样式变化配合transition;一种是javascript动画,使用定时器来实现  

  在上面的5种实现中,scrollTop、scrollTo()和scrollBy()方法可以增加动画,且由于无样式变化,只能增加javascript动画

  定时器又有setInterval、setTimeout和requestAnimationFrame这三种可以使用,下面使用性能最好的定时器requestAnimationFrame来实现

  [注意]IE9-浏览器不支持该方法,可以使用setTimeout来兼容

  1、增加scrollTop的动画效果

  使用定时器,将scrollTop的值每次减少50,直到减少到0,则动画完毕

复制代码

<span><</span><span>script</span><span>></span>
<span>var</span><span> timer  </span><span>=</span> <span>null</span><span>;
box.onclick </span><span>=</span> <span>function</span><span>(){
    cancelAnimationFrame(timer);
    timer </span><span>=</span><span> requestAnimationFrame(</span><span>function</span><span> fn(){
        </span><span>var</span><span> oTop </span><span>=</span><span> document.body.scrollTop </span><span>||</span><span> document.documentElement.scrollTop;
        </span><span>if</span><span>(oTop </span><span>></span> <span>0</span><span>){
            document.body.scrollTop </span><span>=</span><span> document.documentElement.scrollTop </span><span>=</span><span> oTop </span><span>-</span> <span>50</span><span>;
            timer </span><span>=</span><span> requestAnimationFrame(fn);
        }</span><span>else</span><span>{
            cancelAnimationFrame(timer);
        }    
    });
}
</span><span></</span><span>script</span><span>></span>

复制代码

 【时间版运动】

  但是,上面的代码有一个问题,就是当页面内容较多时,回到顶部的动画效果将持续很长时间。因此,使用时间版的运动更为合适,假设回到顶部的动画效果共运动500ms,则代码如下所示

复制代码

<span><</span><span>body </span><span>style</span><span>="height: 2000px;"</span><span>></span>
<span><</span><span>button </span><span>id</span><span>="test"</span><span> style</span><span>="position:fixed;right:10px;bottom:10px;"</span><span>></span>回到顶部<span></</span><span>button</span><span>></span>
<span><</span><span>script</span><span>></span>
<span>var</span><span> timer  </span><span>=</span> <span>null</span><span>;
test.onclick </span><span>=</span> <span>function</span><span>(){
    cancelAnimationFrame(timer);
    </span><span>//</span><span>获取当前毫秒数</span>
    <span>var</span><span> startTime </span><span>=</span> <span>+</span><span>new</span><span> Date();     
    </span><span>//</span><span>获取当前页面的滚动高度</span>
    <span>var</span><span> b </span><span>=</span><span> document.body.scrollTop </span><span>||</span><span> document.documentElement.scrollTop;
    </span><span>var</span><span> d </span><span>=</span> <span>500</span><span>;
    </span><span>var</span><span> c </span><span>=</span><span> b;
    timer </span><span>=</span><span> requestAnimationFrame(</span><span>function</span><span> func(){
        </span><span>var</span><span> t </span><span>=</span><span> d </span><span>-</span><span> Math.max(</span><span>0</span><span>,startTime </span><span>-</span><span> (</span><span>+</span><span>new</span><span> Date()) </span><span>+</span><span> d);
        document.documentElement.scrollTop </span><span>=</span><span> document.body.scrollTop </span><span>=</span><span> t </span><span>*</span><span> (</span><span>-</span><span>c) </span><span>/</span><span> d </span><span>+</span><span> b;
        timer </span><span>=</span><span> requestAnimationFrame(func);
        </span><span>if</span><span>(t </span><span>==</span><span> d){
          cancelAnimationFrame(timer);
        }
    });
}
</span><span></</span><span>script</span><span>></span>
<span></</span><span>body</span><span>></span>

复制代码

  2、增加scrollTo()动画效果

  将scrollTo(x,y)中的y参数通过scrollTop值获取,每次减少50,直到减少到0,则动画完毕

复制代码

<span><</span><span>script</span><span>></span>
<span>var</span><span> timer  </span><span>=</span> <span>null</span><span>;
box.onclick </span><span>=</span> <span>function</span><span>(){
    cancelAnimationFrame(timer);
    timer </span><span>=</span><span> requestAnimationFrame(</span><span>function</span><span> fn(){
        </span><span>var</span><span> oTop </span><span>=</span><span> document.body.scrollTop </span><span>||</span><span> document.documentElement.scrollTop;
        </span><span>if</span><span>(oTop </span><span>></span> <span>0</span><span>){
            scrollTo(</span><span>0</span><span>,oTop</span><span>-</span><span>50</span><span>);
            timer </span><span>=</span><span> requestAnimationFrame(fn);
        }</span><span>else</span><span>{
            cancelAnimationFrame(timer);
        }    
    });
}
</span><span></</span><span>script</span><span>></span>

复制代码

  3、增加scrollBy()动画效果

  将scrollBy(x,y)中的y参数设置为-50,直到scrollTop为0,则回滚停止

复制代码

<span><</span><span>script</span><span>></span>
<span>var</span><span> timer  </span><span>=</span> <span>null</span><span>;
box.onclick </span><span>=</span> <span>function</span><span>(){
    cancelAnimationFrame(timer);
    timer </span><span>=</span><span> requestAnimationFrame(</span><span>function</span><span> fn(){
        </span><span>var</span><span> oTop </span><span>=</span><span> document.body.scrollTop </span><span>||</span><span> document.documentElement.scrollTop;
        </span><span>if</span><span>(oTop </span><span>></span> <span>0</span><span>){
            scrollBy(</span><span>0</span><span>,</span><span>-</span><span>50</span><span>);
            timer </span><span>=</span><span> requestAnimationFrame(fn);
        }</span><span>else</span><span>{
            cancelAnimationFrame(timer);
        }    
    });
}
</span><span></</span><span>script</span><span>></span>

复制代码

实现

  由于scrollTop、scrollBy()和scrollTo()方法,都以scrollTop值是否减少为0作为动画停止的参照,且三个动画的原理和实现都基本相似,性能也相似。最终,以最常用的scrollTop属性实现动画增强效果

  当然,如果觉得500ms的时间不合适,可以根据实际情况进行调整

复制代码

<span><!</span><span>DOCTYPE html</span><span>></span>
<span><</span><span>html </span><span>lang</span><span>="en"</span><span>></span>
<span><</span><span>head</span><span>></span>
<span><</span><span>meta </span><span>charset</span><span>="UTF-8"</span><span>></span>
<span><</span><span>title</span><span>></span>Document<span></</span><span>title</span><span>></span>
<span><</span><span>style</span><span>></span><span>
.box</span><span>{</span><span>
    position</span><span>:</span><span>fixed</span><span>;</span><span>
    right</span><span>:</span><span>10px</span><span>;</span><span>
    bottom</span><span>:</span><span> 10px</span><span>;</span><span>
    height</span><span>:</span><span>30px</span><span>;</span><span>
    width</span><span>:</span><span> 50px</span><span>;</span><span>    
    text-align</span><span>:</span><span>center</span><span>;</span><span>
    padding-top</span><span>:</span><span>20px</span><span>;</span><span>    
    background-color</span><span>:</span><span> lightblue</span><span>;</span><span>
    border-radius</span><span>:</span><span> 20%</span><span>;</span><span>
    overflow</span><span>:</span><span> hidden</span><span>;</span>
<span>}</span><span>
.box:hover:before</span><span>{</span><span>
    top</span><span>:</span><span>50%
</span><span>}</span><span>
.box:hover .box-in</span><span>{</span><span>
    visibility</span><span>:</span><span> hidden</span><span>;</span>
<span>}</span><span>
.box:before</span><span>{</span><span>
    position</span><span>:</span><span> absolute</span><span>;</span><span>
    top</span><span>:</span><span> -50%</span><span>;</span><span>
    left</span><span>:</span><span> 50%</span><span>;</span><span>
    transform</span><span>:</span><span> translate(-50%,-50%)</span><span>;</span><span>
    content</span><span>:</span><span>'回到顶部'</span><span>;</span><span>
    width</span><span>:</span><span> 40px</span><span>;</span><span>
    color</span><span>:</span><span>peru</span><span>;</span><span>
    font-weight</span><span>:</span><span>bold</span><span>;</span>

<span>}</span><span>    
.box-in</span><span>{</span><span>
    visibility</span><span>:</span><span> visible</span><span>;</span><span>
    display</span><span>:</span><span>inline-block</span><span>;</span><span>
    height</span><span>:</span><span>20px</span><span>;</span><span>
    width</span><span>:</span><span> 20px</span><span>;</span><span>
    border</span><span>:</span><span> 3px solid black</span><span>;</span><span>
    border-color</span><span>:</span><span> white transparent transparent white</span><span>;</span><span>
    transform</span><span>:</span><span>rotate(45deg)</span><span>;</span>
<span>}</span>
<span></</span><span>style</span><span>></span>
<span></</span><span>head</span><span>></span>
<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
<span><</span><span>div </span><span>id</span><span>="box"</span><span> class</span><span>="box"</span><span>></span>
    <span><</span><span>div </span><span>class</span><span>="box-in"</span><span>></</span><span>div</span><span>></span>
<span></</span><span>div</span><span>></span>    
<span><</span><span>script</span><span>></span>
<span>var</span><span> timer  </span><span>=</span> <span>null</span><span>;
box.onclick </span><span>=</span> <span>function</span><span>(){
    cancelAnimationFrame(timer);
    </span><span>//</span><span>获取当前毫秒数</span>
    <span>var</span><span> startTime </span><span>=</span> <span>+</span><span>new</span><span> Date();     
    </span><span>//</span><span>获取当前页面的滚动高度</span>
    <span>var</span><span> b </span><span>=</span><span> document.body.scrollTop </span><span>||</span><span> document.documentElement.scrollTop;
    </span><span>var</span><span> d </span><span>=</span> <span>500</span><span>;
    </span><span>var</span><span> c </span><span>=</span><span> b;
    timer </span><span>=</span><span> requestAnimationFrame(</span><span>function</span><span> func(){
        </span><span>var</span><span> t </span><span>=</span><span> d </span><span>-</span><span> Math.max(</span><span>0</span><span>,startTime </span><span>-</span><span> (</span><span>+</span><span>new</span><span> Date()) </span><span>+</span><span> d);
        document.documentElement.scrollTop </span><span>=</span><span> document.body.scrollTop </span><span>=</span><span> t </span><span>*</span><span> (</span><span>-</span><span>c) </span><span>/</span><span> d </span><span>+</span><span> b;
        timer </span><span>=</span><span> requestAnimationFrame(func);
        </span><span>if</span><span>(t </span><span>==</span><span> d){
          cancelAnimationFrame(timer);
        }
    });
}
</span><span></</span><span>script</span><span>></span>
<span></</span><span>body</span><span>></span>
<span></</span><span>html</span><span>></span>

复制代码

  欢迎交流


  目录
分类导航
随笔3 AI29 计算机基础13 算法1 博客搭建7 ChatGPT2 集群63 计算机通信1 数据库59 数据库深入93 数据库93 Docker11 DPDK26 编辑工具4 Elasticsearch4 FAQ1 Go Web1 hometown2 编程语言16 人生11 网络9 Linux38 OPC1 openGauss4 页面12 PostgreSQL54 程序员自我修养1 协议11 stock1 存储5 成长之路1 工具20 视频作品1 VPP18 Vue13 Web1 代码示例11 BenchmarkSQL1 PostgreSQL 源码修炼之路14
最热文章
1
PostgreSQL 逻辑复制全链路:以一个真实事务为例,从 `INSERT` 到 `apply` 的源码级旅程
数据库🔥 2162
2
PostgreSQL 逻辑复制 Stream 执行逻辑源码级拆解:从 reorderbuffer 触发到订阅端落盘回放
数据库🔥 1765
3
PostgreSQL 行锁机制源码级深度拆解:4 种锁模式 + xmax + MultiXact 的完整链路
数据库🔥 1656
4
PostgreSQL reorderbuffer.c 函数级源码全集:5615 行 / 95 个函数的逐函数解析
数据库深入🔥 1650
5
PostgreSQL 目录快照源码级深度拆解:系统表读取的 MVCC 真相与失效机制
数据库🔥 1604
6
13 逻辑复制深入
数据库深入🔥 1570
7
0 Postgresql存储、索引及系统优化、主备切换
PostgreSQL🔥 1495
8
PostgreSQL 读一行数据源码级深度拆解:MVCC 在每个环节的落点
数据库🔥 1464
9
PostgreSQL WAL 记录类型完全指南:21 个 RMGR × 80+ 种记录的源码级拆解
数据库🔥 1431
10
一文读懂openguass dcf网络模块
集群🔥 1420
11
PostgreSQL 元数据存储机制:从磁盘文件到内存缓存,`pg_class` 撑起的整个系统表体系
数据库🔥 1411
12
openGauss 并行解码设计原理深度拆解:reader + 多 worker + CSN 三层架构的源码级剖析
数据库深入🔥 1344
13
逻辑复制源码分析
数据库深入🔥 1327
14
PostgreSQL 逻辑复制:catalog 改动、可见性判定与 xmin/xmax 推进全景
数据库深入🔥 1317
15
自托管服务全家桶:从原文方案到可复制实操手册
人生🔥 1278
16
PostgreSQL CREATE_REPLICATION_SLOT 端到端源码分析:从 SQL 到 snapbuild 状态机的完整链路(每个函数每个参数)
数据库深入🔥 1277
17
PostgreSQL syscache 模块源码深度拆解:CatCache 数据结构、LRU 哈希表、cache invalidation 全链路
数据库深入🔥 1216
18
PostgreSQL 18 内核数据结构全景:RangeVar 与 20+ 个核心数据结构源码级拆解
数据库🔥 1158
19
PostgreSQL 逻辑复制里 `RUNNING_XACTS` 写入机制与快照 `xmin / xmax / xip` 的演化:源码级深度拆解
数据库🔥 1119
20
PostgreSQL 分区表:从一行 `PARTITION BY` 到路由热路径的全链路拆解
数据库🔥 1094