【Web APIs】元素滚动 scroll 系列属性 ② ( 右侧固定侧边栏 )

文章目录

  • [一、元素滚动 scroll 系列属性案例 - 右侧固定侧边栏](#一、元素滚动 scroll 系列属性案例 - 右侧固定侧边栏)
    • 1、需求说明
    • [2、HTML 结构](#2、HTML 结构)
    • 3、右侧固定侧边栏解析
      • [① 相关代码](#① 相关代码)
      • [② 绝对定位](#② 绝对定位)
      • [③ 位置设置](#③ 位置设置)
    • [4、window.pageYOffset 属性](#4、window.pageYOffset 属性)
      • [① window.pageYOffset 属性简介](#① window.pageYOffset 属性简介)
      • [② scroll 滚动事件监听](#② scroll 滚动事件监听)
      • [③ 向下滚动 侧边栏 由 绝对定位 -> 固定定位](#③ 向下滚动 侧边栏 由 绝对定位 -> 固定定位)
      • [④ 向上滚动 侧边栏 由 固定定位 -> 绝对定位](#④ 向上滚动 侧边栏 由 固定定位 -> 绝对定位)
      • [⑤ 判断 返回顶部 按钮 显示 / 隐藏](#⑤ 判断 返回顶部 按钮 显示 / 隐藏)
  • 二、代码示例

一、元素滚动 scroll 系列属性案例 - 右侧固定侧边栏


1、需求说明

在右侧 显示 固定侧边栏 ,

右侧固定侧边栏 一开始是 绝对定位 , 刚开始 向下滑动 时 , 随着 banner 一起滑动 ,

当 banner 区域 向上滑动 开始有隐藏区域 时 , 此时 将 右侧固定侧边栏 设置为 固定定位 , 其位置 固定在 浏览器 中的固定位置 ,

继续向下滑动 , 当 主体部分 开始有 隐藏区域 时 , 右侧固定侧边栏 内部 显示 返回顶部 文本 ,

滚动到底部后 , 开始向上滚动 ,

当 主体部分 的 顶部 显示出来时 , 右侧固定侧边栏 内部 隐藏 返回顶部 文本 ,

继续向上滚动 , 当 banner 区域 顶部 显示出来 时 , 将 右侧固定侧边栏 设置为 绝对定位 , 恢复到最初状态 ;

2、HTML 结构

上述 HTML 结构如下 :

html 复制代码
<body>
    <!-- 侧边滑块容器 , 用于承载返回顶部按钮 -->
    <div class="slider-bar">
        <!-- 返回顶部按钮元素 , 默认通过 CSS 隐藏 , 滚动到指定位置显示 -->
        <span class="goBack">返回顶部</span>
    </div>
    <!-- 页面头部区域 , 应用 w 类 实现 1200px 固定宽度 + 水平居中 -->
    <div class="header w">头部区域</div>
    <!-- 页面横幅区域 , 应用 w 类 实现 1200px 固定宽度 + 水平居中 -->
    <div class="banner w">banner区域</div>
    <!-- 页面主体内容区域 , 应用 w 类 实现 1200px 固定宽度 + 水平居中 , 高度较高产生滚动 -->
    <div class="main w">主体部分</div>
</body>

显示结构如下 :

3、右侧固定侧边栏解析

① 相关代码

右侧固定侧边栏

html 复制代码
    <!-- 侧边滑块容器 , 用于承载返回顶部按钮 -->
    <div class="slider-bar">
        <!-- 返回顶部按钮元素 , 默认通过 CSS 隐藏 , 滚动到指定位置显示 -->
        <span class="goBack">返回顶部</span>
    </div>

对应的样式如下 :

css 复制代码
        .slider-bar {
            /* 定义类名为 slider-bar 的元素样式 ( 侧边滑块/悬浮栏 )  */
            /* 定位方式 : 绝对定位 , 脱离正常文档流 , 可通过 left/top 精准定位 */
            position: absolute;
            /* 左侧定位 : 距离包含块 ( 默认是 body ) 左边缘 50% 的位置 */
            left: 50%;
            /* 顶部定位 : 距离包含块上边缘 300 像素 */
            top: 300px;
            /* 左外边距 : 向右偏移 600 像素 , 微调绝对定位元素的最终水平位置 */
            margin-left: 600px;
            /* 设置滑块宽度为 45 像素 */
            width: 45px;
            /* 设置滑块高度为 130 像素 */
            height: 130px;
            /* 设置滑块背景颜色为粉色 , 用于可视化区分 */
            background-color: pink;
        }

子容器 span 对应的 样式如下 :

css 复制代码
        span {
            /* 定义所有span标签的样式 ( 滑块内的子元素 , 如 按钮/提示文字 )  */
            /* 显示方式 : 隐藏 ( 默认不显示 , 通常通过 JS 控制显示/隐藏 )  */
            display: none;
            /* 定位方式 : 绝对定位 , 相对于最近的已定位父元素 ( .slider-bar ) 定位 */
            position: absolute;
            /* 核心修改1:垂直方向定位到父容器50%位置(基于span的左上角) */
            top: 50%;
            /* 核心修改2:水平方向定位到父容器50%位置(基于span的左上角) */
            left: 50%;
            /* 核心修改3:将span自身向左、向上平移50%,使span的中心点对齐父容器中心点 */
            transform: translate(-50%, -50%);
        }

② 绝对定位

右侧侧边栏 slider-bar 使用了绝对定位 , 按照 " 子绝父相 " 的 定位规则 , 它本应 基于 最近的 相对定位 父容器定位 , 但它的 父容器 body 并没有设置相对定位 ;

" 子绝父相 " 的核心是 : 绝对定位 元素 优先以 最近的 已定位 祖先元素 为基准 , 无则以 视口 为基准 ;

  • 绝对定位 position: absolute 的元素会 脱离 正常 文档流 , 其定位基准是 最近的 已定位 祖先元素 , " 已定位 " 指 position 值为 relative、absolute、fixed、sticky , 而非默认的 static ;
  • 如果没有找到任何 已定位 的 祖先元素 , 绝对定位 元素会以 初始包含块 作为定位基准 , 初始包含块 通常等价于 浏览器视口 可视区域 , 该区域 一般 与 body 元素的 视觉范围 基本重合 ;

body 默认的定位模式是 position: static , 这里有布局上的隐患 , 建议 给 body 添加 position: relative 样式 ;

③ 位置设置

右侧固定侧边栏 设置为了 绝对定位 , 这是 以 父容器 body 为基准 的 绝对定位 ,

设置了 left: 50% , 这是将 容器 的 左侧 设置在了 body 正中心位置 ,

然后 又设置了 margin-left: 600px 左侧外边距 , 向右偏移 600 像素 , 结合上面的 中心位置 , 这里说明 容器左侧 设置在了 中心偏右 600 像素距离 ;

css 复制代码
            /* 定位方式 : 绝对定位 , 脱离正常文档流 , 可通过 left/top 精准定位 */
            position: absolute;
            /* 左侧定位 : 距离包含块 ( 默认是 body ) 左边缘 50% 的位置 */
            left: 50%;
            /* 顶部定位 : 距离包含块上边缘 300 像素 */
            top: 300px;
            /* 左外边距 : 向右偏移 600 像素 , 微调绝对定位元素的最终水平位置 */
            margin-left: 600px;

4、window.pageYOffset 属性

① window.pageYOffset 属性简介

window.pageYOffset 属性 是 BOM 中 window 对象的只读属性 , 该属性 用于 返回 当前文档 在垂直方向上 已经滚动的 像素值 , 简单说就是 页面 向下滚动的距离 ;

把网页看作一张 超长的纸 , 浏览器窗口是一个 " 取景框 " , window.pageYOffset 属性 就是这个 取景框 相对于 纸张顶部 向下移动的像素数 , 页面没滚动时 , 该属性的值是 0 , 向下滚动 200px , 该属性的值就是 200 ;

window.pageYOffset 属性 有一个别名 window.scrollY , 二者 功能完全等价 , scrollY 是更现代的写法 , pageYOffset 属性 兼容性 更好 ;

window.pageYOffset 属性 对应的 水平滚动距离 属性 是 window.pageXOffset , 对应的 别名 scrollX 属性 ;

② scroll 滚动事件监听

为整个 HTML 文档绑定 滚动事件 scroll 监听器 , 当你滚动页面时,传入的匿名回调函数会被持续触发(每滚动一小段距离就会执行一次)。这是实现所有 "滚动交互效果" 的基础,比如导航吸顶、回到顶部按钮、滚动加载等。

javascript 复制代码
        // 2. 为文档添加滚动事件监听 : 页面滚动时持续触发回调函数
        document.addEventListener('scroll', function() {})

document.addEventListener('scroll', function() {})window.addEventListener('scroll', function() {}) 效果几乎完全一致 , 因为 页面滚动 的本质是 window 的滚动 , 日常开发中两种写法都很常见 ;

回调函数默认会接收一个 事件对象 , 通常命名为 e , 但 document 和 window 对象的 滚动事件 中 一般用不到 event 事件 , 可省略 ;

③ 向下滚动 侧边栏 由 绝对定位 -> 固定定位

向下滚动页面 , 开始时 " 右侧固定侧边栏 " 跟随 banner 滑动 , 当 banner 开始隐藏时 , 由 绝对定位 变为 固定定位 ;

在 文档页面 滚动时 触发回调函数 , 使用 window.pageYOffset 属性 获取 页面垂直方向 被卷去的 头部距离 , 根据这个距离 判定 " 右侧固定侧边栏 " 的 样式设置 ;

" 右侧固定侧边栏 " 初始状态 是 绝对定位 ;

当 页面滚动距离 ≥ banner 顶部距离时 , 切换 " 右侧固定侧边栏 " 为 固定定位 ;

同时设置 固定定位 的 top 值 , 保证 " 右侧固定侧边栏 " 滑块位置 与 原 绝对定位 时对齐 ;

javascript 复制代码
 			// 3. 判断 : 当页面滚动距离 ≥ banner 顶部距离时 , 切换滑块为固定定位
            if (window.pageYOffset >= bannerTop) {
                // 将 滑块 定位方式改为 固定定位 ( fixed )  , 脱离文档流 , 固定在可视区域
                sliderbar.style.position = 'fixed';
                // 设置 固定定位 的 top 值 , 保证滑块位置与原绝对定位时对齐 , 不偏移
                sliderbar.style.top = sliderbarTop + 'px';
            }

计算 " 右侧固定侧边栏 " 滑块 固定定位 时的 top 值 : " 右侧固定侧边栏 " 滑块 初始 top 值 - banner 顶部距离 , 保证 固定定位 后位置与原 绝对定位 对齐 ;

banner 顶部距离 可以 通过 banner 元素 获取 距离文档顶部 的距离 , 也就是 banner.offsetTop , 该值是 只读属性 , 不随滚动变化 ;

javascript 复制代码
        // banner.offsetTop : 获取 banner 元素 距离文档顶部 的 初始距离 ( 只读 , 不随滚动变化 )  , 必须写在滚动事件外
        var bannerTop = banner.offsetTop;
        // 计算滑块 固定定位 时的 top 值 : 滑块初始 top 值 - banner 顶部距离 , 保证 固定定位 后位置与原 绝对定位 对齐
        var sliderbarTop = sliderbar.offsetTop - bannerTop;

④ 向上滚动 侧边栏 由 固定定位 -> 绝对定位

向上滚动页面 , 开始时 " 右侧固定侧边栏 " 是固定定位 , 当页面向上滚动时 , 主体部分刚显示时 , 由 固定定位 变为 绝对定位 ;

banner 顶部刚刚显示出来时 , 恢复 " 右侧固定侧边栏 " 滑块的 绝对定位 , 同时 恢复 绝对定位 的 初始 top 值 , 也就是 " 右侧固定侧边栏 " 滑块的 绝对定位 时 在 css 样式中设置的值 ;

javascript 复制代码
            // 3. 判断 : 当页面滚动距离 ≥ banner 顶部距离时 , 切换滑块为固定定位
            if (window.pageYOffset >= bannerTop) {
            	
            } else {
                // banner 顶部刚刚显示出来时 , 恢复滑块的绝对定位 ( absolute ) 
                sliderbar.style.position = 'absolute';
                // 恢复 绝对定位 的 初始 top 值 ( 与 CSS 中设置的 300px 一致 ) 
                sliderbar.style.top = '300px';
            }

这个 " 右侧固定侧边栏 " 滑块 初始 绝对定位时 , 样式如下 , 上面 恢复 绝对定位 top 值 sliderbar.style.top = '300px'; 时 的 300px 就在此处 ;

css 复制代码
        .slider-bar {
            /* 定义类名为 slider-bar 的元素样式 ( 侧边滑块/悬浮栏 )  */
            /* 定位方式 : 绝对定位 , 脱离正常文档流 , 可通过 left/top 精准定位 */
            position: absolute;
            /* 左侧定位 : 距离包含块 ( 默认是 body ) 左边缘 50% 的位置 */
            left: 50%;
            /* 顶部定位 : 距离包含块上边缘 300 像素 */
            top: 300px;
            /* 左外边距 : 向右偏移 600 像素 , 微调绝对定位元素的最终水平位置 */
            margin-left: 600px;
            /* 设置滑块宽度为 45 像素 */
            width: 45px;
            /* 设置滑块高度为 130 像素 */
            height: 130px;
            /* 设置滑块背景颜色为粉色 , 用于可视化区分 */
            background-color: green;
            /* 核心:设置文本为白色 */
            color: white;
        }

⑤ 判断 返回顶部 按钮 显示 / 隐藏

向下滚动 , 直到 主体部分 开始隐藏 , 此时 显示 " 返回顶部 " 按钮 ,

再次向上滚动时 , 主体部分 顶部 显示出来时 , 隐藏 " 返回顶部 " 按钮 ,

当页面滚动距离 ≥ main 顶部距离时 , 显示 返回顶部 按钮 , 设置 display 属性为 block , 即可见的 块级显示方式 ;

未滚动到 main 位置 , 隐藏 返回 顶部按钮 , 设置 display 属性为 none ;

javascript 复制代码
            // 4. 判断 : 当页面滚动距离 ≥ main 顶部距离时 , 显示返回顶部按钮
            if (window.pageYOffset >= mainTop) {
                // 显示 返回顶部 按钮 ( block 为可见的 块级显示方式 ) 
                goBack.style.display = 'block';
            } else {
                // 未滚动到 main 位置 , 隐藏 返回顶部按钮 ( none 为完全隐藏 , 不占空间 ) 
                goBack.style.display = 'none';
            }

二、代码示例


1、代码示例

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>右侧固定侧边栏</title>
    <style>
        .slider-bar {
            /* 定义类名为 slider-bar 的元素样式 ( 侧边滑块/悬浮栏 )  */
            /* 定位方式 : 绝对定位 , 脱离正常文档流 , 可通过 left/top 精准定位 */
            position: absolute;
            /* 左侧定位 : 距离包含块 ( 默认是 body ) 左边缘 50% 的位置 */
            left: 50%;
            /* 顶部定位 : 距离包含块上边缘 300 像素 */
            top: 300px;
            /* 左外边距 : 向右偏移 600 像素 , 微调绝对定位元素的最终水平位置 */
            margin-left: 600px;
            /* 设置滑块宽度为 45 像素 */
            width: 45px;
            /* 设置滑块高度为 130 像素 */
            height: 130px;
            /* 设置滑块背景颜色为粉色 , 用于可视化区分 */
            background-color: green;
            /* 核心:设置文本为白色 */
            color: white;
        }
        
        .w {
            /* 定义 通用容器类 w 的样式 ( 统一页面主体宽度和居中 )  */
            /* 设置容器固定宽度为 1200 像素 ( PC 端常用的页面主体宽度 )  */
            width: 1200px;
            /* 外边距 : 上下10像素 , 左右自动分配 ( 实现元素水平居中 )  */
            margin: 10px auto;
        }
        
        .header {
            /* 定义类名为 header 的页面头部区域样式 */
            /* 设置头部区域高度为 150 像素 */
            height: 150px;
            /* 设置背景颜色为紫色 , 便于区分页面区块 */
            background-color: blue;
            /* 文本水平居中 */
            text-align: center;
            /* 设置文本为白色 */
            color: white;
        }
        
        .banner {
            /* 定义类名为 banner 的页面横幅区域样式 */
            /* 设置横幅区域高度为 250 像素 */
            height: 250px;
            /* 设置背景颜色为天蓝色 , 便于区分页面区块 */
            background-color: red;
            /* 文本水平居中 */
            text-align: center;
            /* 设置文本为白色 */
            color: white;
        }
        
        .main {
            /* 定义类名为 main 的页面主体内容区域样式 */
            /* 设置主体区域高度为 1000 像素 , 该高度 足够高 以产生页面滚动条  */
            height: 1000px;
            /* 设置背景颜色为黄绿色 , 便于区分页面区块 */
            background-color: purple;
            /* 文本水平居中 */
            text-align: center;
            /* 设置文本为白色 */
            color: white;
        }
        
        span {
            /* 定义所有span标签的样式 ( 滑块内的子元素 , 如 按钮/提示文字 )  */
            /* 显示方式 : 隐藏 ( 默认不显示 , 通常通过 JS 控制显示/隐藏 )  */
            display: none;
            /* 定位方式 : 绝对定位 , 相对于最近的已定位父元素 ( .slider-bar ) 定位 */
            position: absolute;
            /* 核心修改1:垂直方向定位到父容器50%位置(基于span的左上角) */
            top: 50%;
            /* 核心修改2:水平方向定位到父容器50%位置(基于span的左上角) */
            left: 50%;
            /* 核心修改3:将span自身向左、向上平移50%,使span的中心点对齐父容器中心点 */
            transform: translate(-50%, -50%);
        }
    </style>
</head>

<body>
    <!-- 侧边滑块容器 , 用于承载返回顶部按钮 -->
    <div class="slider-bar">
        <!-- 返回顶部按钮元素 , 默认通过 CSS 隐藏 , 滚动到指定位置显示 -->
        <span class="goBack">返回顶部</span>
    </div>
    <!-- 页面头部区域 , 应用 w 类 实现 1200px 固定宽度 + 水平居中 -->
    <div class="header w">头部区域</div>
    <!-- 页面横幅区域 , 应用 w 类 实现 1200px 固定宽度 + 水平居中 -->
    <div class="banner w">banner 区域</div>
    <!-- 页面主体内容区域 , 应用 w 类 实现 1200px 固定宽度 + 水平居中 , 高度较高产生滚动 -->
    <div class="main w">主体部分</div>

    <script>
        // 1. 获取页面元素 ( 提前获取避免滚动事件内重复查询 DOM , 优化性能 ) 
        // 获取侧边滑块容器的 DOM 元素
        var sliderbar = document.querySelector('.slider-bar');
        // 获取 banner 区域的 DOM 元素
        var banner = document.querySelector('.banner');
        // 获取 main主体区域 的 DOM 元素
        var main = document.querySelector('.main');
        // 获取 返回顶部按钮 的 DOM 元素
        var goBack = document.querySelector('.goBack');

        // banner.offsetTop : 获取 banner 元素 距离文档顶部 的 初始距离 ( 只读 , 不随滚动变化 )  , 必须写在滚动事件外
        var bannerTop = banner.offsetTop;
        // 计算滑块 固定定位 时的 top 值 : 滑块初始 top 值 - banner 顶部距离 , 保证 固定定位 后位置与原 绝对定位 对齐
        var sliderbarTop = sliderbar.offsetTop - bannerTop;

        // 获取 main 元素 距离 文档顶部 的初始距离 , 用于判断 显示 返回顶部 按钮的时机
        var mainTop = main.offsetTop;

        // 2. 为文档添加滚动事件监听 : 页面滚动时持续触发回调函数
        document.addEventListener('scroll', function() {
            // window.pageYOffset : 获取页面垂直方向被卷去的头部距离 ( 滚动距离 ) 

            // 3. 判断 : 当页面滚动距离 ≥ banner 顶部距离时 , 切换滑块为固定定位
            if (window.pageYOffset >= bannerTop) {
                // 将 滑块 定位方式改为 固定定位 ( fixed )  , 脱离文档流 , 固定在可视区域
                sliderbar.style.position = 'fixed';
                // 设置 固定定位 的 top 值 , 保证滑块位置与原绝对定位时对齐 , 不偏移
                sliderbar.style.top = sliderbarTop + 'px';
            } else {
                // banner 顶部刚刚显示出来时 , 恢复滑块的绝对定位 ( absolute ) 
                sliderbar.style.position = 'absolute';
                // 恢复绝对定位的初始 top 值 ( 与 CSS 中设置的 300px 一致 ) 
                sliderbar.style.top = '300px';
            }

            // 4. 判断 : 当页面滚动距离 ≥ main 顶部距离时 , 显示返回顶部按钮
            if (window.pageYOffset >= mainTop) {
                // 显示 返回顶部 按钮 ( block 为可见的 块级显示方式 ) 
                goBack.style.display = 'block';
            } else {
                // 未滚动到 main 位置 , 隐藏 返回顶部按钮 ( none 为完全隐藏 , 不占空间 ) 
                goBack.style.display = 'none';
            }

        })
    </script>
</body>

</html>

2、执行结果

相关推荐
珑墨2 小时前
【浏览器】页面加载原理详解
前端·javascript·c++·node.js·edge浏览器
FreeBuf_2 小时前
Next.js 发布扫描工具:检测并修复受 React2Shell 漏洞(CVE-2025-66478)影响的应用
开发语言·javascript·ecmascript
LYFlied2 小时前
在AI时代,前端开发者如何构建全栈开发视野与核心竞争力
前端·人工智能·后端·ai·全栈
用户47949283569152 小时前
我只是给Typescript提个 typo PR,为什么还要签协议?
前端·后端·开源
馬致远2 小时前
Vue -组件入门
javascript·vue.js·ecmascript
程序员爱钓鱼2 小时前
Next.js SSR 项目生产部署全攻略
前端·next.js·trae
程序员爱钓鱼2 小时前
使用Git 实现Hugo热更新部署方案(零停机、自动上线)
前端·next.js·trae
御形封灵3 小时前
基于原生table实现单元格合并、增删
开发语言·javascript·ecmascript
颜颜yan_3 小时前
DevUI + Vue 3 入门实战教程:从零构建AI对话应用
前端·vue.js·人工智能