scrollIntoView Scrolls just too far

2019-03-08 07:16发布

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 on a YouTube playlist next to the video player.

When a user visits the page, the option they are on is supposed to go to the top of the scrolling div. This functionality is working. The issue is that it goes just a tad too far. Like the option they are on is about 10px too high. So, the page is visited, the url is used to identify which option was selected and then scrolls that option to the top of the scrolling div. Note: This is not the scroll bar for the window, it is a div with a scrollbar.

I am using this code to make it move the selected option to the top of the div:

var pathArray = window.location.pathname.split( '/' );

var el = document.getElementById(pathArray[5]);

el.scrollIntoView(true);

It moves it to the top of the div but about 10 pixels too far up. Anyone know how to fix that?

8条回答
仙女界的扛把子
2楼-- · 2019-03-08 07:50

If it's about 10px, then I guess you could simply manually adjust the containing div's scroll offset like that:

el.scrollIntoView(true);
document.getElementById("containingDiv").scrollTop += 10;
查看更多
老娘就宠你
3楼-- · 2019-03-08 07:50

Position Anchor By Absolute Method

Another way do do this is to position your anchors exactly where you want on the page rather than relying on scrolling by offset. I find it allows better control for each element (eg. if you want a different offset for certain elements), and may also be more resistant to browser API changes/differences.

<div id="title-element" style="position: relative;">
  <div id="anchor-name" style="position: absolute; top: -100px; left: 0" />
</div>

Now the offset is specified as -100px relative to the element. Create a function to create this anchor for code reuse, or if you are using a modern JS framework such as React do this by creating a component that renders your anchor, and pass in the anchor name and alignment for each element, which may or may not be the same.

Then just use :

const element = document.getElementById('anchor-name')
element.scrollIntoView({ behavior: 'smooth', block: 'start' });

For smooth scrolling with an offset of 100px.

查看更多
家丑人穷心不美
4楼-- · 2019-03-08 07:52

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;
查看更多
Juvenile、少年°
5楼-- · 2019-03-08 08:05

Assuming you want to scroll to the divs that are all at the same level in DOM and have class name "scroll-with-offset", then this CSS will solve the issue:

.scroll-with-offset {    
  padding-top: 100px;
  margin-bottom: -100px;
}

The offset from the top of the page is 100px. It will only work as intended with block: 'start':

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

What's happening is that the divs' top point is at the normal location but their inner contents start 100px below the normal location. That's what padding-top:100px is for. margin-bottom: -100px is to offset the below div's extra margin. To make the solution complete also add this CSS to offset the margins/paddings for the top-most and bottom-most divs:

.top-div {
  padding-top: 0;
}
.bottom-div {
  margin-bottom: 0;
}
查看更多
该账号已被封号
6楼-- · 2019-03-08 08:10

Building on an earlier answer, I am doing this in an Angular5 project.

Started with:

// el.scrollIntoView(true);
el.scrollIntoView({
   behavior: 'smooth',
   block: 'start'
});
window.scrollBy(0, -10); 

But this gave some problems and needed to setTimeout for the scrollBy() like this:

//window.scrollBy(0,-10);
setTimeout(() => {
  window.scrollBy(0,-10)
  }, 500);

And it works perfectly in MSIE11 and Chrome 68+. I have not tested in FF. 500ms was the shortest delay I would venture. Going lower sometimes failed as the smooth scroll had not yet completed. Adjust as required for your own project.

+1 to Fred727 for this simple but effective solution.

查看更多
闹够了就滚
7楼-- · 2019-03-08 08:13

You can do it in two steps :

el.scrollIntoView(true);
window.scrollBy(0, -10); // Adjust scrolling with a negative value here
查看更多
登录 后发表回答