You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用CSS实现随头部可见性自适应高度的左侧导航菜单?

问题

我正在构建一个包含顶部滚动Header、左侧Sider菜单和右侧滚动Content的基础布局,右侧Content随主滚动条滚动。需求如下:

  • 左侧Sider中的"TOP SIDER"和"BOTTOM SIDER"始终显示在视口中
  • Sider高度需随Header是否可见动态调整

已知用JS可实现该效果,想了解是否可用纯CSS实现,已耗费数小时仍未解决。

原始示例代码

<html>
<head>
    <style>
        body {
            margin: 0;
            padding: 0;
        }

        .header {
            background-color: red;
        }

        .main {
            background-color: green;
            display: flex;
            flex-direction: row;
        }

        .sider {
            width: 200px;
            background-color: cornflowerblue;
            height: 100vh; /* I think here is the problem */
            position: sticky;
            top:0;
            align-self: flex-start;
        }

        .inner-sider {
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
        }
    </style>
</head>
<body>
<div class="header">Header</div>
<div class="main">
    <div class="sider">
        <div class="inner-sider">
            <div>TOP SIDER</div>
            <div>BOTTOM SIDER</div>
        </div>
    </div>
    <div class="content">
        MAIN CONTENT
<!--        SIMULATE A LAGE CONTENT PAGE-->
        <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
        <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
        <br><br><br><br><br><br><br><br><br>
        END OF MAIN CONTENT
    </div>
</div>
</body>
</html>

补充说明:示例中的两个内层<div>仅用于展示Inner Sider的顶部和底部区域,实际场景中Inner Sider应为全屏高度菜单。


纯CSS实现方案

可以通过CSS滚动驱动动画结合动态计算属性实现,无需JavaScript。以下是优化后的代码及关键说明:

修改后的完整代码

<html>
<head>
    <style>
        body {
            margin: 0;
            padding: 0;
            overflow-x: hidden;
        }

        .header {
            background-color: red;
            padding: 1rem;
            /* 固定Header高度用于计算;若需动态高度,可结合JS同步变量,纯CSS建议固定或用min-height */
            min-height: 52px;
            box-sizing: border-box;
        }

        .main {
            background-color: green;
            display: flex;
            flex-direction: row;
            min-height: calc(100vh - 52px);
        }

        .sider {
            width: 200px;
            background-color: cornflowerblue;
            position: sticky;
            top: 0;
            align-self: flex-start;
            /* 动态计算Sider高度:Header可见时减去Header高度,不可见时占满视口 */
            height: calc(100vh - max(0px, 52px - var(--scroll-top)));
        }

        .inner-sider {
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            padding: 1rem;
            box-sizing: border-box;
        }

        /* 通过滚动驱动动画更新滚动距离变量 */
        @keyframes track-scroll {
            to {
                --scroll-top: 100vh;
            }
        }

        body {
            animation: track-scroll linear;
            animation-timeline: scroll(root);
            animation-range: 0 100vh;
        }
    </style>
</head>
<body>
<div class="header">Header</div>
<div class="main">
    <div class="sider">
        <div class="inner-sider">
            <div>TOP SIDER</div>
            <div>BOTTOM SIDER</div>
        </div>
    </div>
    <div class="content">
        MAIN CONTENT
<!--        SIMULATE A LAGE CONTENT PAGE-->
        <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
        <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
        <br><br><br><br><br><br><br><br><br>
        END OF MAIN CONTENT
    </div>
</div>
</body>
</html>

核心实现逻辑

  1. 滚动距离追踪:利用CSS滚动驱动动画animation-timeline: scroll(root),将页面滚动距离同步到--scroll-top变量。
  2. 动态高度计算:
    • 当Header在视口中(滚动距离 < Header高度),52px - var(--scroll-top)为正数,Sider高度 = 视口高度 - Header高度,确保底部内容不被Header遮挡。
    • 当Header滚出视口(滚动距离 ≥ Header高度),52px - var(--scroll-top)为负数,max(0px, ...)取0,Sider高度自动变为100vh,占满整个视口。
  3. Sticky定位:Sider设置position: sticky; top: 0,确保其始终固定在视口左侧,不会随Content滚动移出视野。

兼容性说明

CSS滚动驱动动画目前已在Chrome、Edge等现代浏览器支持,若需兼容旧版浏览器,可改用position: fixed配合降级方案,但纯CSS下无法完美适配动态Header高度的场景,此时建议结合少量JavaScript同步Header高度变量。


内容的提问来源于stack exchange,提问作者LWlook

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 17:21:07