scrollIntoView Scrolls just too far

前端 未结 21 1917
盖世英雄少女心
盖世英雄少女心 2020-12-07 10:08

I have a page where a scroll bar containing table rows with divs in them is dynamically generated from the database. Each table row acts like a link, sort of like you\'d see

相关标签:
21条回答
  • 2020-12-07 10:53

    I solved this problem by using,

    element.scrollIntoView({ behavior: 'smooth', block: 'center' });
    

    This makes the element appear in the center after scrolling, so I don't have to calculate yOffset.

    Hope it helps...

    0 讨论(0)
  • 2020-12-07 10:53

    UPD: I've created an npm package that works better than the following solution and easier to use.

    My smoothScroll function

    I've taken the wonderful solution of Steve Banton and wrote a function that makes it more convenient to use. It'd be easier just to use window.scroll() or even window.scrollBy(), as I've tried before, but these two have some problems:

    • Everything becomes junky after using them with a smooth behavior on.
    • You can't prevent them anyhow and have to wait till the and of the scroll. So I hope my function will be useful for you. Also, there is a lightweight polyfill that makes it work in Safari and even IE.

    Here is the code

    Just copy it and mess up with it how ever you want.

    import smoothscroll from 'smoothscroll-polyfill';
    
    smoothscroll.polyfill();
    
    const prepareSmoothScroll = linkEl => {
      const EXTRA_OFFSET = 0;
    
      const destinationEl = document.getElementById(linkEl.dataset.smoothScrollTo);
      const blockOption = linkEl.dataset.smoothScrollBlock || 'start';
    
      if ((blockOption === 'start' || blockOption === 'end') && EXTRA_OFFSET) {
        const anchorEl = document.createElement('div');
    
        destinationEl.setAttribute('style', 'position: relative;');
        anchorEl.setAttribute('style', `position: absolute; top: -${EXTRA_OFFSET}px; left: 0;`);
    
        destinationEl.appendChild(anchorEl);
    
        linkEl.addEventListener('click', () => {
          anchorEl.scrollIntoView({
            block: blockOption,
            behavior: 'smooth',
          });
        });
      }
    
      if (blockOption === 'center' || !EXTRA_OFFSET) {
        linkEl.addEventListener('click', () => {
          destinationEl.scrollIntoView({
            block: blockOption,
            behavior: 'smooth',
          });
        });
      }
    };
    
    export const activateSmoothScroll = () => {
      const linkEls = [...document.querySelectorAll('[data-smooth-scroll-to]')];
    
      linkEls.forEach(linkEl => prepareSmoothScroll(linkEl));
    };
    

    To make a link element just add the following data attribute:

    data-smooth-scroll-to="element-id"
    

    Also you can set another attribute as an addtion

    data-smooth-scroll-block="center"
    

    It represents the block option of the scrollIntoView() function. By default, it's start. Read more on MDN.

    Finally

    Adjust the smoothScroll function to your needs.

    For example, if you have some fixed header (or I call it with the word masthead) you can do something like this:

    const mastheadEl = document.querySelector(someMastheadSelector);
    
    // and add it's height to the EXTRA_OFFSET variable
    
    const EXTRA_OFFSET = mastheadEl.offsetHeight - 3;
    

    If you don't have such a case, then just delete it, why not :-D.

    0 讨论(0)
  • 2020-12-07 10:54

    This works for me in Chrome (With smooth scrolling and no timing hacks)

    It just moves the element, initiates the scroll, then moves it back.

    There is no visible "popping" if the element is already on the screen.

    pos = targetEle.style.position;
    top = targetEle.style.top;
    targetEle.style.position = 'relative';
    targetEle.style.top = '-20px';
    targetEle.scrollIntoView({behavior: 'smooth', block: 'start'});
    targetEle.style.top = top;
    targetEle.style.position = pos;
    
    0 讨论(0)
  • 2020-12-07 10:54

    I've got this and it works brilliantly for me:

    // add a smooth scroll to element
    scroll(el) {
    el.scrollIntoView({
      behavior: 'smooth',
      block: 'start'});
    
    setTimeout(() => {
    window.scrollBy(0, -40);
    }, 500);}
    

    Hope it helps.

    0 讨论(0)
  • 2020-12-07 10:54

    So, perhaps this is a bit clunky but so far so good. Im working in angular 9.

    file .ts

    scroll(el: HTMLElement) {
      el.scrollIntoView({ block: 'start',  behavior: 'smooth' });   
    }
    

    file .html

    <button (click)="scroll(target)"></button>
    <div  #target style="margin-top:-50px;padding-top: 50px;" ></div>
    

    I adjust the offset with margin and padding top.

    Saludos!

    0 讨论(0)
  • 2020-12-07 10:55

    I add this css tips for those who not resolved this issue with solutions above :

    #myDiv::before {
      display: block;
      content: " ";
      margin-top: -90px; // adjust this with your header height
      height: 90px; // adjust this with your header height
      visibility: hidden;
    }
    
    0 讨论(0)
提交回复
热议问题