如何使父元素滚动到特定位置,而子元素在父元素内部滚动?

3

编辑:

这里是一个新的代码片段,更好地说明了我的需求:https://jsfiddle.net/gta4eo3L/3/

请注意,在查看所有子元素内容时,您需要滚动两次。第一次是为了使父级完全显示;第二次是为了滚动父级中的内容。我的问题是如何使此过程无缝?换句话说,我该如何使第一次滚动的“惯性”传递到第二次滚动中。

原始内容:

enter image description here

如何实现这种无缝的滚动行为?父元素高度是固定的,我可以使用position: sticky来保持其位置;但是与overflow: scroll属性结合在一起时,子元素将在父元素到达停止点之前滚动。

在这里查看我的代码片段:https://jsfiddle.net/xzo1teaw/11/

它有点奏效,但在父元素滚动和子元素在父元素内滚动之间没有平稳的过渡。


1
你目前尝试了什么?有任何代码可以分享吗? - Christoph Lütjen
@ChristophLütjen 我做了一个示例: https://jsfiddle.net/xzo1teaw/11/ (同时更新了我的问题) - Jake Xia
1
父级定义的停止点在哪里/是什么? - petern0691
1
谢谢。但是,现在再次查看您上面的图表,我认为根据定义,不可能将子元素滚动到超出其父元素的范围之外。这可以通过两个独立的元素和JS来模拟效果来实现。 - petern0691
1
你为什么要实现这种行为呢?看起来非常不切实际。这样做以前从未尝试过,可能是有原因的。我见过的唯一类似的解决方案是在顶部有一个水平菜单,在滚动时减小以留出内容空间。 - Rickard Elimää
显示剩余8条评论
3个回答

2

一旦你理解了一个重要的事情,这就相对容易实现了。
子元素不必是父元素的子代
+ 你可以使用CSS Grid在同一位置放置多个元素
+ 使用z-index将元素放置在sticky元素上方

body {
/*  some space to scroll  */
  height: 500vh;
/*  some space to scroll  */
  padding-top: 50vh;
}

.container {
  display: grid;
  grid-template-areas: "only";
  justify-items: center;
}

.parent {
  grid-area: only;
  background: grey;
  position: sticky;
  top: 10vh;
  width: 90%;
/*  one screen height  */
  height: 90vh;
}

.child {
/*  offset for parent  */
  margin-top: 200px;
  height: 200vh;
  grid-area: only;
  background: linear-gradient(
    0deg,
    rgba(131, 58, 180, 1) 0%,
    rgba(253, 29, 29, 1) 50%,
    rgba(252, 176, 69, 1) 100%
  );
  z-index: 2;
  width: 80%;
}

body * {
  display: inline-block;
  border: 1px solid black;
}
 <div class="container">
   Container
   <div class="parent">Parent</div>
   <div class="child">Child</div>
</div>


1

有点用

! 元素是兄弟关系而非父子关系

声明:在 iPhone 上进行了黑客攻击和测试

<div id="p"></div>
<div id="c">child
</div>

#p {
user-select: none;
pointer-events: none;
position: absolute;
top: 300px;
left: 0;
right: 0;
height: calc(100vh - 45px);
border: groove 1em cyan;
border-radius: 2em;
}

#p.scrolled {
position: fixed;
top: 0;
}

#c {
margin: 300px 1em 45px;
white-space: pre;
}

c.textContent = Array(100).join(c.textContent);

addEventListener('scroll', () =>
  p.className = scrollY > 300
    ? 'scrolled'
    : '');

0
请看下面的代码片段:

window.onscroll = function() {
  scrollFunction()
};
var parent = document.getElementById('parent');
var child = document.getElementById('child');

function scrollFunction() {
  if (document.body.scrollTop > 200 || document.documentElement.scrollTop > 200) {
    parent.classList.add('overflow-scroll');
    child.classList.add('top-child');
  } else {
    parent.classList.remove('overflow-scroll');
    child.classList.remove('top-child');
  }
}
body {
  margin: 0px;
  padding: 0px;
  scroll-snap-type: y mandatory;
}

.background {
  background: skyblue;
  height: 90vh;
  width: 100%;
  position: sticky;
  top: 0;
  z-index: -1;
  margin-bottom: -16px;
}

.parent {
  position: relative;
  margin-top: -35px;
  background: white;
  border-top-left-radius: 24px;
  border-top-right-radius: 24px;
  -webkit-box-shadow: 0 0 32px 4px rgba(0, 0, 0, 0.25);
  -moz-box-shadow: 0 0 32px 4px rgba(0, 0, 0, 0.25);
  box-shadow: 0 0 32px 4px rgba(0, 0, 0, 0.25);
  padding: 32px 8px;
  height: calc(100vh - 100px);
  overflow: hidden;
  width: 98%;
}

.child {
  background: rgb(131, 58, 180);
  background: linear-gradient(0deg, rgba(131, 58, 180, 1) 0%, rgba(253, 29, 29, 1) 50%, rgba(252, 176, 69, 1) 100%);
  height: 200vh;
  margin: 16px;
  position: relative;
  top: -30vh;
}

.parent,
.child {
  -ms-overflow-style: none;
  /* Internet Explorer 10+ */
  scrollbar-width: none;
  /* Firefox */
}

.parent::-webkit-scrollbar,
.child::-webkit-scrollbar {
  display: none;
  /* Safari and Chrome */
}

.overflow-scroll {
  overflow: scroll;
  position: fixed;
  top: 30vh;
}

.top-child {
  top: 30vh;
  /*100px minus margin (14px)*/
}
<div class="background">
  Background
</div>
<div id="parent" class="parent">
  Parent

  <p>
    the parent looks like a card that slides over the background
  </p>

</div>
<div class="child" id="child">
  the child element does not have a defined height and can be very long
  <br/> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eget nibh rutrum, porta quam ac, rutrum erat. Donec ultricies, dolor vel iaculis rutrum, nunc tellus pulvinar ante, a malesuada erat sapien at lectus. In quis ligula augue. Aliquam
  auctor nulla nec mattis viverra. Aliquam eget felis velit. Nulla euismod lectus eu sapien aliquam convallis dapibus ut sem. Nullam vestibulum ante non lacinia finibus. Donec lacinia ultricies arcu id sollicitudin. Aliquam a venenatis arcu, et congue
  justo. Etiam vitae augue tortor. Etiam sed nulla dui. Vestibulum elementum euismod eleifend. In eu aliquam mauris. Sed sit amet tempor quam. Mauris in mi lacus. Pellentesque vestibulum vehicula blandit. Phasellus consectetur iaculis libero, maximus
  euismod tortor ultrices nec. Duis eget lacinia quam. Vivamus sit amet tincidunt neque. Maecenas sed mauris dignissim, consequat justo ac, mollis arcu. Etiam aliquet enim at orci dapibus, ac aliquam diam aliquet. Nulla quis magna sit amet ante interdum
  iaculis. Duis pharetra erat sit amet mi interdum pharetra. Maecenas interdum tortor leo, ac vehicula odio consectetur quis. Ut vitae tincidunt quam. Donec purus ipsum, commodo eget rutrum vitae, aliquam molestie diam. Sed rutrum, tortor vel iaculis
  fermentum, urna quam lacinia libero, a pulvinar lacus arcu pharetra ligula. Sed lacus tortor, dictum quis luctus et, eleifend commodo erat. Sed non metus at leo blandit posuere et in nisi. Duis ornare scelerisque ultricies. Ut vestibulum maximus imperdiet.
  Praesent egestas tristique sem. Curabitur est quam, auctor quis auctor a, placerat porttitor nisi. Pellentesque tristique, tellus vitae porttitor consequat, massa diam lacinia est, at rhoncus arcu nulla et lectus. Donec libero nibh, hendrerit at elementum
  sit amet, gravida vel leo. Aenean vitae nibh at massa tempus scelerisque at eu quam. Nulla facilisi. Nulla vel ligula convallis, consectetur magna sit amet, euismod eros. Aenean et ullamcorper diam. Donec ultricies felis eget venenatis viverra. Ut ut
  risus sit amet libero tincidunt volutpat. Cras dui libero, vehicula sollicitudin bibendum et, dictum eu ex. Sed et magna sem. Sed fermentum diam quis sapien posuere consectetur. Integer vulputate ex sed imperdiet faucibus. Etiam at accumsan nisl. Cras
  semper aliquam tortor, vel semper nulla luctus eu. Duis porta urna eget ex luctus, a pellentesque enim pulvinar. Aliquam neque mauris, cursus vel consectetur nec, blandit id diam. Phasellus vel erat erat.
</div>

编辑:看看这个:https://jsfiddle.net/iorgu/ts6dqr8o/57/

第二次编辑:我的第三个版本:https://jsfiddle.net/iorgu/ts6dqr8o/86/


不完全正确。我制作了这个fiddle(受到你js部分的启发)来更好地说明我的意图:https://jsfiddle.net/gta4eo3L/2/。在我的fiddle中,您需要滚动两次才能查看所有子内容。一次使父级到达末尾,然后再次滚动子级。如何使这个过程无缝?这可能吗? - Jake Xia
你的意思是说,你希望在你做的这个小工具中只有一个滚动条? - iorgv
当父级无法滚动时,我希望第一个滚动的动量能够传递到内部滚动(在父级内部)。 - Jake Xia
我对上面的内容进行了一些更改。尽管有些滞后,这是您要找的吗?https://jsfiddle.net/iorgu/ts6dqr8o/57/ - iorgv
抱歉如果不太清楚;子元素应该被父元素剪裁。它不能“超出”卡片。 - Jake Xia
新版本:https://jsfiddle.net/iorgu/ts6dqr8o/86/ - iorgv

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