【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、执行结果

相关推荐
ywf12151 小时前
前端的dist包放到后端springboot项目下一起打包
前端·spring boot·后端
恋猫de小郭1 小时前
2026,Android Compose 终于支持 Hot Reload 了,但是收费
android·前端·flutter
hpoenixf7 小时前
2026 年前端面试问什么
前端·面试
还是大剑师兰特7 小时前
Vue3 中的 defineExpose 完全指南
前端·javascript·vue.js
泯泷8 小时前
阶段一:从 0 看懂 JSVMP 架构,先在脑子里搭出一台最小 JSVM
前端·javascript·架构
mengchanmian8 小时前
前端node常用配置
前端
华洛9 小时前
利好打工人,openclaw不是企业提效工具,而是个人助理
前端·javascript·产品经理
xkxnq9 小时前
第六阶段:Vue生态高级整合与优化(第93天)Element Plus进阶:自定义主题(变量覆盖)+ 全局配置与组件按需加载优化
前端·javascript·vue.js
A黄俊辉A10 小时前
vue css中 :global的使用
前端·javascript·vue.js
小码哥_常10 小时前
被EdgeToEdge适配折磨疯了,谁懂!
前端