使用 HTML 和 CSS 创建动态大小的固定侧边栏

Avatar of Ryan Mulligan
Ryan Mulligan 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

创建页面内容,使其在滚动时固定在视口中,例如跳转到锚点菜单或章节标题,从未如此简单。在您的 CSS 规则集中添加一个 position: sticky,设置方向偏移量(例如 top: 0),您就可以毫不费力地给您的团队留下深刻印象。查看 这篇 CSS-Tricks 文章,了解一些真正花哨的固定定位用例。

但是固定定位可能会有点棘手,尤其是在涉及高度以及隐藏无法滚动到的位置中的内容的危险情况下。让我设置场景,向您展示问题以及我如何解决它。

我最近在一个我们都熟悉的桌面布局上工作:一个主要内容区域,旁边有一个侧边栏。此侧边栏包含与主要内容相关的操作项和筛选器。当页面部分滚动时,此组件保持固定在视口中,并且可以上下文访问。

布局样式的实现就像我之前提到的那样简单。但有一个问题:组件的高度会根据其内容而变化。我可以使用 max-height 对其进行限制,并设置 overflow-y: auto 使组件内容可滚动。这在我的笔记本电脑屏幕和我的典型视口高度上运行良好,但在垂直空间较小的较小视口中,侧边栏的高度会超出视口。

当固定侧边栏的高度大于视口时,其某些内容将无法访问,直到到达容器底部,此时元素不再固定。

事情变得棘手了。

思考解决方案

我最初考虑使用媒体查询。也许我可以使用媒体查询删除固定定位,并让组件相对于侧边栏容器的顶部放置。这将允许访问其所有内容。否则,当滚动页面时,固定组件的内容会在视口底部被截断,直到我到达其父部分的末尾。

然后我记起固定组件的高度是动态的。

我可以在媒体查询中使用什么神奇的值来处理这样的事情?也许我可以编写一个 JavaScript 函数来检查组件在页面加载时是否超出视口边界?然后我可以更新组件的高度……

这是一种可能性。

但是如果用户调整窗口大小呢?我应该在调整大小事件处理程序中使用相同的函数吗?这感觉不对。一定有更好的方法来构建它。

事实证明有,它涉及一些 CSS 技巧来完成这项工作!

设置页面部分

我从主元素上的 flex 显示开始。为侧边栏设置了一个 flex-basis 值,用于固定桌面宽度。然后文章元素填充了剩余的可用水平视口空间。

如果您好奇我如何在没有媒体查询的情况下让这两个容器在较小的视口中堆叠,请查看 Flexbox 神圣信天翁 技巧。

我向侧边栏添加了 align-self: start,以便其高度不会随着主要文章(stretch 是默认值)而拉伸。这使我的定位属性能够发挥其魔力

.sidebar {
  --offset: var(--space);
  /* ... */
  position: sticky;
  top: var(--offset);
}

看看!使用这两个 CSS 属性,侧边栏元素会固定在视口顶部,并带有一个偏移量以提供一些呼吸空间。请注意,top 值设置为 作用域 CSS 自定义属性。现在,--offset 变量可以在侧边栏内的任何子元素上重复使用。这在稍后设置固定侧边栏组件的最大高度时会派上用场。

您可以在 CodePen 演示中找到全局 CSS 变量声明的列表,包括在 :root 规则集中用于偏移值的 --space 变量。

固定侧边栏

请记住,组件本身不是固定的;是侧边栏本身固定。通用布局和定位通常应由父级处理。这使组件更具灵活性,并使其更易于在应用程序的其他区域中使用。

让我们深入了解此组件的结构。在 演示中,我已删除了以下装饰性属性,以专注于布局样式

.component {
  display: grid;
  grid-template-rows: auto 1fr auto;
}


.component .content {
  max-height: 500px;
  overflow-y: auto;
}
  • 此组件使用 CSS Grid 和来自 1-Line Layouts煎饼堆栈理念来配置此模板的行。标题和页脚(auto)都调整为其子元素的高度,而内容(1fr,或一个 分数单位)填充剩余的开放垂直空间。
  • 内容上的 max-height 限制了组件在较大屏幕尺寸上的增长。如果希望组件拉伸以填充视口高度,则无需此操作。
  • overflow-y: auto 允许在必要时滚动内容。

当组件在侧边栏中使用时,需要 max-height 以使其不超过视口高度。之前作用域到 .sidebar 类的 --offset 加倍以在元素底部创建与固定侧边栏顶部偏移量匹配的边距

.sidebar .component {
  max-height: calc(100vh - var(--offset) * 2);
}

至此,这个固定侧边栏组件的组装就完成了!应用了一些装饰性样式后,此原型便可以进行测试和审查。试一试!在 CodePen 中打开演示,然后点击网格项将其添加到侧边栏。调整浏览器窗口大小以查看组件如何在视口中灵活变化,同时在您滚动主要内容部分时保持可见。


此布局可能在桌面浏览器上运行良好,但对于较小的设备或视口宽度并不完全理想。但是,此处的代码提供了一个坚实的基础,可以轻松地对 UI 进行改进。

一个简单的想法:一个按钮可以固定到视口窗口,单击时,页面会跳转到侧边栏内容。另一个想法:侧边栏可以隐藏在屏幕外,一个切换按钮可以将其从左侧或右侧滑入。迭代和用户测试将帮助将此体验引导到正确的方向。