Home > other >  Scroll child div while parent div is position sticky in vue JS
Scroll child div while parent div is position sticky in vue JS

Time:11-04

I have a use case for my landing page, where when user enters one of the <section> of the page, the section becomes fixed but the elements inside that <div> starts scrolling. Once the inner div is done scrolling the parent <section> should start scrolling as a normal section and should go away to the top with a scroll.

I've created a similar structure in the jsFiddle below. But not able to achieve the desired feature.

enter image description here

HTML


... Other sections before

    <section ref="stickyDiv" >
      <div >
        <div ref="wrapper" @scroll="scrollerListener" >
          <div >
            <h3 >Access to all the exclusive opportunities</h3>
            <div >
              <img 
                   src="https://res.cloudinary.com/stack-finance/image/upload/v1663728853/app-assets/v2/mask_group_590_e5gbgr.png"
              >
            </div>
          </div>
          <div >
            <h3 >Access to all the exclusive opportunities</h3>
            <div >
              <img 
                   src="https://res.cloudinary.com/stack-finance/image/upload/v1663728853/app-assets/v2/mask_group_590_e5gbgr.png"
              >
            </div>
          </div>
          <div >
            <h3 >Access to all the exclusive opportunities</h3>
            <div >
              <img 
                   src="https://res.cloudinary.com/stack-finance/image/upload/v1663728853/app-assets/v2/mask_group_590_e5gbgr.png"
              >
            </div>
          </div>
        </div>
      </div>
    </section>

... Other sections in the bottom

Vuejs

  methods: {
    ...
    listenBodyScroll(e) {
      if (this.isMobile) {
        return;
      }

      const stickyDiv = this.$refs.stickyDiv;
      const wrapper = this.$refs.wrapper;
      const dim = stickyDiv.getBoundingClientRect();
      console.log(dim.y, dim.height, '---scrollTop');

      if (dim.y <= 0) {
        if (Math.ceil(dim.height) <= Math.abs(dim.y)) {
          stickyDiv.style.position = 'relative';
          stickyDiv.style.top = 'auto';
          stickyDiv.style.height = 'auto';
          wrapper.style.overflowY = 'hidden';
          wrapper.scrollTop = wrapper.scrollHeight;
          return;
        }

        wrapper.focus();
        stickyDiv.style.position = 'sticky';
        stickyDiv.style.top = '100px';
        stickyDiv.style.height = '100vh';
        wrapper.style.overflowY = 'auto';
      }
    },
    scrollerListener({ target: { scrollTop, offsetHeight, scrollHeight, style } }) {
      if (this.isMobile) {
        return;
      }

      const stickyDiv = this.$refs.stickyDiv;

      if ((Math.ceil(scrollTop)   offsetHeight) >= scrollHeight) {
        stickyDiv.style.position = 'relative';
        stickyDiv.style.top = 'auto';
        stickyDiv.style.height = 'auto';
        style.overflowY = 'hidden';
        console.log('bottom!');
      }
    }
  }

Vue direction v-scroll


Vue.directive('scroll', {
  inserted(el, binding) {
    const f = function(evt) {
      if (binding.value(evt, el)) {
        window.removeEventListener('scroll', f);
      }
    };
    window.addEventListener('scroll', f);
  }
});

CodePudding user response:

There are no secret techniques in web development. Use your browser's inspect tool and check the website's HTML/CSS and see exactly how it works for yourself.

I did this myself and took some of the website's HTML and CSS and recreated a simple version you can see in this codesandbox

Basically, there are two divs of 50% width side by side that exist within the same parent div forcing them to be the same (very large) height. Once you scroll the parent div into view, the image container with position: sticky keeps it in the same relative screen position until you get to the bottom of its parent div where it will then scroll away with the rest of the parent div content.

  • Related