锚点定位

1,608 阅读3分钟

概念

前端常见的锚点定位说白了就是让滚动条滚动到自己想要的位置,通过点击操作或者是别的事件来让页面滚动到自己想要的地方。

分类

根据常见的需求一般分为以下两种页面滚动方式。

  1. 目录型滚动 这种滚动方式就像页面中有一个目录,用户点击了对应的索引就跳转到索引所在的位置。常见的有页面中的回到顶部,直达底部以及目录跳转等等。

  2. 视窗顶部和底部 这种滚动方式是通过一个事件,来将页面中的一个元素移动到视窗的顶部或底部。比较常见的就是页面中所出现的由26个字母所组成的侧边栏索引,例如微信通讯录、携程的出行地址选择等。点击了对应的字母,页面就会滚动到以那个字母为首的地方。

实现方式

实现之前有一点需要特别注意,那就是以下的所有操作都是建立在你想让页面滚动到什么位置的基础上,如果你的页面都不能滚动,那么下面的一切都不会生效。

实现方式通常有以下两种:

  1. 借助<a href="#id"></a>标签的锚点特性 当a标签的href属性添加的不是链接而是一个html元素的id值的时候(前面要加#),当点击这个a标签页面会自动滚动到这个id所指定的页面位置,并且这个id所映射的元素处于视窗的最顶部。

  2. 借助htmlElement.scrollIntoView()方法 这个方法存在于每一个htmlElement之上,当相对应的htmlElement元素的.scrollIntoView()方法被调用了,那么页面就会滚动到以这个htmlElement元素为视窗最顶部的位置。

两种方法都可以实现上述的两种需求,但是第二种相比第一种兼容性更好。因为第一种必须要通过a标签的href属性绑定id才可以实现,而第二种无论你是什么元素,只要你点击了这个元素调用了你想置顶元素的scrollIntoView()方法,就可以达到这个效果。

除此之外第二种方法还可以通过传递一个false来达到置底的效果,即调用htmlElement.scrollIntoView(false)方法使页面滚动到以htmlElement元素为视窗最底部的位置,这个元素的最底部与视窗最底部相对齐。

同时这种方法还可以传递一个对象,用来控制在页面滚动过程中的速度,以下是他的详细参数,详情可见MDN:developer.mozilla.org/zh-CN/docs/…

  • alignToTop可选

    一个[Boolean]值:

    • 如果为true,元素的顶端将和其所在滚动区的可视区域的顶端对齐。相应的 scrollIntoViewOptions: {block: "start", inline: "nearest"}。这是这个参数的默认值。
    • 如果为false,元素的底端将和其所在滚动区的可视区域的底端对齐。相应的scrollIntoViewOptions: {block: "end", inline: "nearest"}
  • scrollIntoViewOptions 可选 Experimental

    • 一个包含下列属性的对象:
      • behavior 可选

        定义动画过渡效果, "auto"或 "smooth" 之一。默认为 "auto"

      • block 可选

        定义垂直方向的对齐, "start""center""end", 或 "nearest"之一。默认为 "start"

      • inline 可选

        定义水平方向的对齐, "start""center""end", 或 "nearest"之一。默认为 "nearest"

但是这种方法也存在一个弊端,那就是取决于其它元素的布局情况,此元素可能不会完全滚动到顶端或底端,这一点在使用中需要注意。

自己的demo示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html, body { width: 100%; height: 100%;}
        div {
            width: 90%; height: 300px; display: flex; justify-content: center; align-items: center;
            margin:0 auto 30px;
        }
        a { margin-right: 30px; display: block}
    </style>
</head>
<body>
    <div>
        <a href="#box3">跳转到3</a>
        <a href="#box4">跳转到4</a>
        <a href="#box5">跳转到5</a>
        <a href="#box6">跳转到6</a>
        <a href="#box7">跳转到7</a>
    </div>
    <div id='box1' style='background-color: red;'>1</div>
    <div id='box2' style='background-color: orange;'>2</div>
    <div id='box3' style='background-color: yellow;'>3</div>
    <div id='box4' style='background-color: green;'>4</div>
    <div id='box5' style='background-color: aqua;'>5</div>
    <div id='box6' style='background-color: blue;'>6</div>
    <div id='box7' style='background-color: purple;'>7</div>
    <a href="#box1">回到顶部</a>
    <p id='p1'>跳转到1</p>
    <p id='p2'>跳转到2</p>
    <p id='p3'>跳转到3</p>
    <p id='p4'>跳转到4</p>
    <script>
        // setTimeout(() => {
            // 该方法必须在页面完全加载之后才可以使用,如果不生效可以尝试加延时
            for (let i = 1; i < 5; i++) {
                const pElement = document.getElementById(`p${i}`);
                pElement.onclick = () => {
                    const boxElement = document.getElementById(`box${i}`);
                    if(i % 2 === 0) {
                        boxElement.scrollIntoView(false);
                    } else { 
                        boxElement.scrollIntoView(true);
                    }
                }
            }
        // }, 200)
    </script>
</body>
</html>