【问题标题】:Right fixed sidebar inside scrollcontainer滚动容器内的右侧固定侧边栏
【发布时间】:2018-10-03 00:19:00
【问题描述】:

这听起来可能已经被问过一百万次了,但我还没有找到真正解决我试图解决的所有问题的方法。有了这个免责声明,这就是我想要实现的目标:

  1. 侧边栏,固定在右侧
  2. 内容区域,可以滚动
  3. 内容区的滚动条需要在侧边栏的右边
  4. 应该可以显示叠加层
  5. 叠加层也应该是可滚动的
  6. 虽然覆盖层可见,但底层内容区域不应滚动
  7. 显示带有滚动条的叠加层应该导致底层内容区域的重新布局,例如因为overflow: hidden

所有这些要求的组合破坏了我尝试过的每个解决方案。

我现在有两个解决方案,它们很接近但仍然不够好:
解决方案 1 不能解决需求 7。
解决方案 2 在叠加层可见时有两个滚动条。

解决方案 1:

function showOverlay() {
  var style = document.body.style;
  style.overflow = 'hidden';
  document.getElementById('overlay').style.display = 'block';
}

function closeOverlay() {
  var style = document.body.style;
  style['overflow-y'] = 'scroll';
  document.getElementById('overlay').style.display = 'none';
}
* {
  margin: 0;
  box-sizing: border-box
}
html {
}
body {
  position: relative;
  width: 100%;
  overflow-y: scroll;
}

.content {
  position: relative;
  display: block;
  background-color: lightblue;
  border: 2px solid white;
  width: calc(100% - 60px)
}

.fixed {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 1000;
  background-color: lightgreen;
  width: 60px;
  border: 2px solid black;
  text-align: right;
}

#overlay {
  display: none;
  position: fixed;
  z-index: 10000;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  background-color: rgba(32,32,32,0.5);
  overflow-y: scroll;
}

.overlay-content {
  margin: 50px auto;
  height: 1000px;
  width: 80%;
  background-color: yellow;
}
<div class="content">
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    <button onclick="showOverlay()">show overlay</button>
  </div>
<div class="fixed">A<br/>B<br/>C</div>
<div id="overlay">
  <div class="overlay-content">
    <button onclick="closeOverlay()">Close overlay</button>
  </div>
</div>

解决方案2:

function showOverlay() {
  var style = document.body.style;
  style.top = '-' + document.documentElement.scrollTop + 'px';
  style.position = 'fixed';
  document.getElementById('overlay').style.display = 'block';
}

function closeOverlay() {
  var style = document.body.style;
  style.position = 'relative';
  style.top = 0;
  document.getElementById('overlay').style.display = 'none';
}
* {
  margin: 0;
  box-sizing: border-box
}
html {
}
body {
  position: relative;
  width: 100%;
  overflow-y: scroll;
}

.content {
  position: relative;
  display: block;
  background-color: lightblue;
  border: 2px solid white;
  width: calc(100% - 60px)
}

.fixed {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 1000;
  background-color: lightgreen;
  width: 60px;
  border: 2px solid black;
  text-align: right;
}

#overlay {
  display: none;
  position: fixed;
  z-index: 10000;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  background-color: rgba(32,32,32,0.5);
  overflow-y: scroll;
}

.overlay-content {
  margin: 50px auto;
  height: 1000px;
  width: 80%;
  background-color: yellow;
}
<div class="content">
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    Body<br/>
    <button onclick="showOverlay()">show overlay</button>
  </div>
<div class="fixed">A<br/>B<br/>C</div>
<div id="overlay">
  <div class="overlay-content">
    <button onclick="closeOverlay()">Close overlay</button>
  </div>
</div>

我认为解决方案 1 是两者中更好的一个,但是否有可能阻止重新布局的发生?

请注意,我正在尝试找到一个不使用 Javascript 来检测滚动条宽度的解决方案。

【问题讨论】:

  • relayout 是什么意思?显示叠加层前后有何不同?
  • 检查右侧的边栏。它将部分移动到覆盖的滚动条下方,使字母 ABC 不再可见
  • 所以你想让滚动条不可见?让我们暂时忽略技术限制,您将如何解决设计问题?
  • 相反:我希望叠加层的滚动条可见。我不想要的是内容区的滚动条消失了。
  • 换句话说:即使显示叠加层,内容区域的宽度也应该保持不变。

标签: html css


【解决方案1】:

解决方法是将内容和修复部分包裹起来,防止从body滚动。

此外,您使用position: absolute 包装器包装修复部分。不同之处在于不同的positions 如何处理right: 0absolute 相对于父级(position: relative),fixed 始终相对于窗口。

此时浏览器将阻止您在侧边栏上的鼠标滚轮事件(因为position: fixed),因此我们将添加.fixed-innerpointer-events: auto 以允许用户与侧边栏内容进行交互。

我只在最新的 Chrome 上测试过。

function showOverlay() {
  //  var style = document.body.style;
  //  style.overflow = 'hidden';
  document.getElementById('overlay').style.display = 'block';
}

function closeOverlay() {
  //  var style = document.body.style;
  //  style['overflow-y'] = 'scroll';
  document.getElementById('overlay').style.display = 'none';
}
* {
  margin: 0;
  box-sizing: border-box
}

html,
body {
  position: relative;
  height: 100%;
  overflow-y: hidden;
}

.wrapper {
  overflow-y: auto;
  position: relative;
  height: 100%;
}

.content {
  position: relative;
  display: block;
  background-color: lightblue;
  border: 2px solid white;
  width: calc(100% - 60px)
}

.fixed-wrapper {
  position: absolute;
  top: 0;
  right: 0;
  width: 60px;
  height: 100%;
}

.fixed {
  position: fixed;
  z-index: 1000;
  background-color: lightgreen;
  width: 60px;
  border: 2px solid black;
  text-align: right;
  height: 100%;
  top: 0;
  pointer-events: none;
}

.fixed .fixed-inner {
  pointer-events: auto;
}

#overlay {
  display: none;
  position: fixed;
  z-index: 10000;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  background-color: rgba(32, 32, 32, 0.5);
  overflow-y: scroll;
}

.overlay-content {
  margin: 50px auto;
  height: 1000px;
  width: 80%;
  background-color: yellow;
}
<div class="wrapper">
  <div class="content">
    Body<br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/> Body
    <br/>
    <button onclick="showOverlay()">show overlay</button>
  </div>
  <div class="fixed-wrapper">
    <div class="fixed">
      <div class="fixed-inner">
        <a href="https://google.com">A</a>
        <br/>B<br/>C
      </div>
    </div>
  </div>
</div>
<div id="overlay">
  <div class="overlay-content">
    <button onclick="closeOverlay()">Close overlay</button>
  </div>
</div>

【讨论】:

  • 哇,太好了。因为固定的 div 没有明确的左或右,它是相对于它的父级的?我试图实现类似的目标,但无法实现,因为我总是将权限设置为 0。侧边栏上没有滚动条很烂
  • 我们不能阻止侧边栏处理该事件吗?
  • 认为是“固定”部分阻止了内容部分的事件。我想这不是一个选项,但如果侧边栏中的内容仅用于演示(不是链接或其他内容),您可以将 pointer-events: none 添加到侧边栏。
  • 太棒了。即使有链接,这也是解决方案。我们可以简单地将pointer-events: auto 添加到侧边栏中的链接中。因此,当鼠标悬停在链接上时,滚动仍然不起作用,但它适用于侧边栏的其余部分。
  • 这对我来说是新的 :) 我从未尝试在 pointer-events: none 中使用 pointer-events: auto,因为我认为它不会生效。生活充满惊喜 :) 我为下一代更新了我的答案..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-13
  • 1970-01-01
相关资源
最近更新 更多