使用JavaScript的position:sticky使div超出父元素

4
我有一个左侧菜单,希望它始终保持粘性,我正在使用JavaScript来支持IE11。
我的问题是右侧的div在粘性时会移到左侧,不能保持位置。第二个问题是当右侧div处于粘性状态时,.content div的宽度会增加。
对于JavaScript部分,我不知道如何使右侧div在到达页脚时停止。
编辑:
我成功解决了第二个问题,代码已更新。我还尝试为右侧div添加一个right值,以使其保持初始垂直位置,但由于屏幕大小改变时位置会改变,所以这种方法不起作用。
我该如何解决这个问题?
编辑2:
对于JavaScript问题,我找到了这篇文章,帮助我解决了问题: Make sticky/fixed element stop at footer

var sticky = document.getElementsByClassName("sticky-element")[0];
var stickyAnchor = sticky.parentNode;
var state = false;

function getAnchorOffset() {
    return stickyAnchor.getBoundingClientRect().top;
}

updateSticky = function (e) {
    if (!state && (getAnchorOffset() < 0)) {
      sticky.classList.add("is-sticky");
      sticky.parentElement.classList.add("has-sticky");
      state = true;
    } else if (state && (getAnchorOffset() >=0 )) {
      sticky.classList.remove("is-sticky");
      sticky.parentElement.classList.remove("has-sticky");
      state = false;
    }
}

window.addEventListener('scroll', updateSticky);
window.addEventListener('resize', updateSticky);

updateSticky();
.main-wrapper {
    margin: 48px 48px 0 48px;
    max-width: 1366px;
}

.wrapper {
    width: 100%;
    display: flex;
    justify-content: space-between;
    position: relative;
}

.wrapper.has-sticky .content{
    margin-right: calc(199px + 72px);
}

.content {
    flex: 0 1 1040px;
    width: calc(1040px - 72px);
    min-width: 1%;
    margin-right: 72px;
    height: 1200px;
    background-color: #e6e9f0;
}

.nav-menu {
    position: static;
    flex: 0 1 199px;
    width: 199px;
    min-width: 199px;
    color: white;
    height: 300px;
    background-color: #04246a;
    right: 10%;
}

footer {
  background-color: yellow;
  height: 300px;
  margin-top: 50px;
}

.is-sticky {
    top: 0;
    position: fixed;
}
<div class="main-wrapper">
  <div class="wrapper">
    <div class="content">
      Main content
    </div>
    <div class="nav-menu sticky-element">
      <nav>
        Side content
      </nav>
    </div>
  </div>
  <footer>
    Footer content
  </footer>
</div>


position: sticky 就像 position: absolute 一样,意味着该元素将从其初始位置移除,以便其他元素填充该空位。同样适用于宽度,在开始时有两个元素共享宽度,但是一旦一个元素具有 position: sticky,它将被移除,因此其他元素将完全使用整个宽度。 - Why u do dis
你正在使用百分比作为宽度,这可能会根据元素数量而改变。如果你想要元素有固定的宽度,请使用像素(px)来指定宽度。例如:width:50px。 - Why u do dis
值得一看 - position:sticky;overflow 真的不太兼容。在使用 sticky 时,这个问题已经让我遇到了几次:https://dev59.com/9FcP5IYBdhLWcg3w39o-#47878455。你可能需要查找整个 DOM 树以找到罪魁祸首。虽然听起来不像是你的问题,但最好再检查一下。 - serraosays
@serraosays 如果没有IE11的话,使用position: sticky会节省我很多时间 xD - Renaud is Not Bill Gates
2个回答

3

您正在寻找这个吗?

您的代码问题在于当您将右侧div的position设置为fixed时,它会查找其相对父元素并跳转到父元素内的左上位置。在您的情况下,父div是.wrapper,这就是为什么它一直跳向左侧并覆盖主内容div的原因。

我为.nav-menu添加了一个父容器,因此在滚动时它将保持在相同的位置。通过这样做,您的.nav-menu元素将不会使用.wrapper作为其主要父元素。这将创建平稳的滚动,而不会注意到任何位置的更改。

编码愉快!

var sticky = document.getElementsByClassName('sticky-element')[0];
var stickyAnchor = sticky.parentNode;
var state = false;

function getAnchorOffset() {
  return stickyAnchor.getBoundingClientRect().top;
}

updateSticky = function (e) {
  if (!state && getAnchorOffset() < 0) {
    sticky.classList.add('is-sticky');
    state = true;
  } else if (state && getAnchorOffset() >= 0) {
    sticky.classList.remove('is-sticky');
    state = false;
  }
};

window.addEventListener('scroll', updateSticky);
window.addEventListener('resize', updateSticky);

updateSticky();
.main-wrapper {
  margin: 48px 48px 0 48px;
  max-width: 80%;
}

.wrapper {
  width: 100%;
  display: flex;
  justify-content: space-between;
  position: relative;
}

.content {
  flex: 0 1 80%;
  width: calc(80% - 24px);
  min-width: 1%;
  margin-right: 24px;
  height: 1200px;
  background-color: #e6e9f0;
}

.nav-container {
  flex-grow: 1;
  width: 20%;
  min-width: 200px;
  position: relative;
  display: block;
}

.nav-menu {
  color: white;
  width: 100%;
  min-width: inherit;
  height: 300px;
  background-color: #04246a;
}

.is-sticky {
  top: 0;
  position: fixed;
  width: calc(20% - 97px);
}
<div class="main-wrapper">
  <div class="wrapper">
    <div class="content">Main content</div>
    <div class="nav-container">
      <div class="nav-menu sticky-element">
        <nav>Side content</nav>
      </div>
    </div>
  </div>
</div>


0

var sticky = document.getElementsByClassName("sticky-element")[0];
var stickyAnchor = sticky.parentNode;
var state = false;

function getAnchorOffset() {
    return stickyAnchor.getBoundingClientRect().top;
}

updateSticky = function (e) {
    if (!state && (getAnchorOffset() < 0)) {
      sticky.classList.add("is-sticky");
      state = true;
    } else if (state && (getAnchorOffset() >=0 )) {
      sticky.classList.remove("is-sticky");
      state = false;
    }
}

window.addEventListener('scroll', updateSticky);
window.addEventListener('resize', updateSticky);

updateSticky();
.main-wrapper {
    margin: 48px 48px 0 48px;
    max-width: 80%;
}

.wrapper {
    width: 100%;
    display: flex;
    justify-content: space-between;
    position: relative;
}

.content {
    flex: 0 1 80%;
    width: calc(80% - 24px);
    min-width: 1%;
    margin-right: 24px;
    height: 1200px;
    background-color: #e6e9f0;
}

.nav-menu {
    position: static;
    flex: 0 1 20%;
    width: 20%;
    min-width: 20%;
    color: white;
    height: 300px;
    background-color: #04246a;
}

.is-sticky {
    top: 0;
    right:5%;
    position: fixed;
}
<div class="main-wrapper">
  <div class="wrapper">
    <div class="content">
      Main content
    </div>
    <div class="nav-menu sticky-element">
      <nav>
        Side content
      </nav>
    </div>
  </div>
</div>


玩弄正确的.is-sticky百分比,直到符合您的需求。另外,如我上面提到的,将.content类的宽度更改为px。 - Why u do dis
谢谢,但如果视口很宽,则右侧%并不起作用,侧边导航会到达屏幕边缘。 - Renaud is Not Bill Gates
你能帮我检查一下我的第二次尝试吗?问题出在计算侧边 div 的 right 上,如果你调整窗口大小,你会注意到这个问题,但是我希望侧边 div 在调整窗口大小时始终保持相同的垂直位置。 - Renaud is Not Bill Gates
看一下我的解决方案 @RenaudisNotBillGates - Techuila

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接