滚动容器内的右侧固定侧栏

时间:2018-10-02 12:39:48

标签: html css

这听起来好像已经被问了一百万遍了,但是我还没有找到能真正解决我要解决的所有问题的东西。有了这个免责声明,这就是我想要实现的目标:

  1. 侧边栏,固定在右侧
  2. 可能会滚动的内容区域
  3. 内容区域的滚动条必须位于侧边栏的
  4. 应该可以显示叠加层
  5. 叠加层也应可滚动
  6. 当覆盖层可见时,底层内容区域不应滚动
  7. 用滚动条显示覆盖图应该 not 导致底层内容区域的重新布局,例如由于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即可检测滚动条宽度的解决方案。

1 个答案:

答案 0 :(得分:2)

解决方案是包装内容和修复部分,并防止滚动body

此外,您还用position: absolute包装器包装了固定零件。区别在于不同的position处理right: 0的方式。 absolute相对于父级(带有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>