css页面滚动,联动滚动

125 阅读3分钟

源于沸点求助

原文: 求助一个问题,如果我想让页面横向滚动时,div1和div3固定,div2和div4绑定在一起移动,纵向滚动时,div1和div2固定,div3和div4绑定在一起滚动

image.png

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>固定行列滚动布局</title>
    <style>
        /* --- 基础页面样式 --- */
        body {
            margin: 0;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
            /* 禁止 body 自身的滚动条,所有滚动都在 grid 容器内处理 */
            overflow: hidden;
        }

![image.png](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/8322361840074d2a854ddeb32e2c365e~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5ouc5peg5b-n:q75.awebp?rk3s=f64ab15b&x-expires=1774589872&x-signature=DpYHNtRWfDxpmX4Q1pRlm8kMhHI%3D)
        /* --- 主要网格容器 --- */
        .grid-container {
            /* 使用 CSS Grid 来创建一个 2x2 的布局 */
            display: grid;
            
            /* 定义网格布局:
              - grid-template-columns: 定义两列。第一列固定宽度 150px,第二列占据剩余所有空间 (1fr)。
              - grid-template-rows: 定义两行。第一行固定高度 60px,第二行占据剩余所有空间 (1fr)。
            */
            grid-template-columns: 150px 1fr;
            grid-template-rows: 60px 1fr;
            
            /* 让网格容器占满整个视口 */
            width: 100vw;
            height: 100vh;
        }

        /* --- 所有四个 div 的通用样式 --- */
        .grid-item {
            border-right: 1px solid #dcdcdc;
            border-bottom: 1px solid #dcdcdc;
            box-sizing: border-box; /* 确保边框和内边距不会增加元素的尺寸 */
        }
        
        .content-wrapper {
             display: flex;
             align-items: center;
             justify-content: center;
        }

        /* --- 四个区域的特定样式和行为 --- */
        
        /* div1: 左上角固定区域 */
        #div1 {
            background-color: #f5f5f5;
            z-index: 3; /* z-index 最高,确保它显示在所有滚动内容的上面 */
            font-weight: bold;
        }

        /* div2: 顶部标题行 (只横向滚动) */
        #div2 {
            background-color: #f0f0f0;
            /* 隐藏自身的滚动条,它的滚动将由 JavaScript 控制 */
            overflow: hidden; 
            z-index: 2;
        }

        /* div3: 左侧标题列 (只纵向滚动) */
        #div3 {
            background-color: #f0f0f0;
            /* 同样隐藏自身的滚动条 */
            overflow: hidden; 
            z-index: 2;
        }

        /* div4: 主要内容区域 (双向滚动) */
        #div4 {
            background-color: #ffffff;
            /* 开启滚动条,这是驱动所有滚动的核心元素 */
            overflow: scroll; 
            z-index: 1;
        }

        /* --- 用于创建可滚动内容的内部容器 --- */
        
        /* div2 的内部容器,设置一个很大的宽度来产生横向滚动条 */
        #div2 .content-wrapper {
            width: 2000px;
            height: 100%;
            justify-content: space-around; /* 简单排版一下内容 */
            font-weight: bold;
        }

        /* div3 的内部容器,设置一个很大的高度来产生纵向滚动条 */
        #div3 .content-wrapper {
            width: 100%;
            height: 1500px;
            flex-direction: column; /* 内容垂直排列 */
            justify-content: space-around;
            font-weight: bold;
        }

        /* div4 的内部容器,同时设置很大的宽度和高度 */
        #div4 .content-wrapper {
            width: 2000px;
            height: 1500px;
            /* 添加网格背景,方便观察滚动效果 */
            background: 
                linear-gradient(90deg, rgba(0,0,0,0.05) 1px, transparent 1px),
                linear-gradient(rgba(0,0,0,0.05) 1px, transparent 1px);
            background-size: 100px 50px;
        }
    </style>
</head>
<body>

    <div class="grid-container">
        <!-- div1: 左上角固定角 -->
        <div id="div1" class="grid-item content-wrapper">
            固定角
        </div>

        <!-- div2: 顶部行,随内容区横向滚动 -->
        <div id="div2" class="grid-item">
            <div class="content-wrapper">
                <span>列标题 1</span><span>列标题 2</span><span>列标题 3</span><span>列标题 4</span><span>列标题 5</span><span>列标题 6</span><span>列标题 7</span><span>列标题 8</span>
            </div>
        </div>

        <!-- div3: 左侧列,随内容区纵向滚动 -->
        <div id="div3" class="grid-item">
            <div class="content-wrapper">
                <span>行标题 A</span><span>行标题 B</span><span>行标题 C</span><span>行标题 D</span><span>行标题 E</span><span>行标题 F</span><span>行标题 G</span><span>行标题 H</span><span>行标题 I</span><span>行标题 J</span>
            </div>
        </div>

        <!-- div4: 主要内容区域,可以双向滚动 -->
        <div id="div4" class="grid-item">
            <div class="content-wrapper">
                <!-- 这里是您的主要数据内容 -->
            </div>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            // 获取需要同步滚动的三个元素
            const div2 = document.getElementById('div2'); // 顶部标题行
            const div3 = document.getElementById('div3'); // 左侧标题列
            const div4 = document.getElementById('div4'); // 主要内容区

            // --- 核心逻辑 ---
            // 监听主要内容区 (div4) 的滚动事件
            div4.addEventListener('scroll', function() {
                // 1. 同步横向滚动
                // 将 div4 的水平滚动距离 (scrollLeft) 赋值给顶部标题行 (div2)
                // 这样,当内容区向左滚动时,顶部标题行也一起向左滚动
                div2.scrollLeft = this.scrollLeft;

                // 2. 同步纵向滚动
                // 将 div4 的垂直滚动距离 (scrollTop) 赋值给左侧标题列 (div3)
                // 这样,当内容区向上滚动时,左侧标题列也一起向上滚动
                div3.scrollTop = this.scrollTop;
            });
        });
    </script>

</body>
</html>