html - 滚动容器内的右侧固定侧边栏
问题描述
听起来这可能已经被问过一百万次了,但我还没有找到真正解决我试图解决的所有问题的任何东西。有了这个免责声明,这就是我想要实现的目标:
- 侧边栏,固定在右侧
- 一个内容区域,可能是可滚动的
- 内容区的滚动条需要在侧边栏的右侧
- 应该可以显示覆盖
- 叠加层也应该是可滚动的
- 虽然覆盖层是可见的,但底层内容区域不应该是可滚动的
- 显示带有滚动条的覆盖不应导致底层内容区域的重新布局,例如,因为
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 来检测滚动条宽度的解决方案。
解决方案
解决办法是把内容和修复部分包裹起来,防止从body
.
此外,您使用包装器包装修复部分position: absolute
。不同之处在于不同position
的 s 处理方式right: 0
。是相对于absolute
父级(带有position: relative
),并且fixed
总是相对于窗口。
此时浏览器将阻止您在侧边栏上的鼠标滚轮事件(因为position: fixed
),因此我们将添加.fixed-inner
withpointer-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>
推荐阅读
- sql - T-SQL 传递给 LEFT 或 SUBSTRING 函数的长度参数无效
- c++ - 是否可以使用变换反馈来检索由 OpenGL 顶点几何着色器生成的三角形?
- django - 在Django中将变量从API传递到模板
- python - Python MQTT 订阅响应/确认以使用 json 发布
- r - 如何在ggplot中放置和包装图例
- python - 我正在为 Discord 机器人编写一个空白数据库,在正确的时间调用函数存在问题
- c# - C# - 当我选择一个单元格时更改行颜色
- powershell - 如何将参数传递给通过 Start-Job 调用的 PS 脚本?
- javascript - 如何在 js 文件中导入 Nuxt 模块
- android - AppBarLayout 无法转换为 androidx.appcompat.widget.Toolbar