Javascript ScrollIntoView() 导致整个页面移动
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11039885/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ScrollIntoView() causing the whole page to move
提问by imhere
I am using ScrollIntoView() to scroll the highlighted item in a list into view. When I scroll downwards ScrollIntoView(false) works perfectly. But when I scroll upwards, ScrollIntoView(true) is causing the whole page to move a little which I think is intended. Is there a way to avoid the whole page move when using ScrollIntoView(true)?
我正在使用 ScrollIntoView() 将列表中突出显示的项目滚动到视图中。当我向下滚动时 ScrollIntoView(false) 工作得很好。但是当我向上滚动时, ScrollIntoView(true) 导致整个页面移动了一点,我认为这是有意的。使用 ScrollIntoView(true) 时有没有办法避免整个页面移动?
Here is the structure of my page -
这是我的页面结构 -
#listOfDivs {
position:fixed;
top:100px;
width: 300px;
height: 300px;
overflow-y: scroll;
}
<div="container">
<div="content">
<div id="listOfDivs">
<div id="item1"> </div>
<div id="item2"> </div>
<div id="itemn"> </div>
</div>
</div>
</div>
listOfDivs is coming from ajax call. Using mobile safari.
listOfDivs 来自 ajax 调用。使用移动Safari。
Thanks for your help in advance!
提前感谢您的帮助!
回答by Brilliand
You could use scrollTop
instead of scrollIntoView()
:
您可以使用scrollTop
代替scrollIntoView()
:
var target = document.getElementById("target");
target.parentNode.scrollTop = target.offsetTop;
jsFiddle: http://jsfiddle.net/LEqjm/
jsFiddle:http: //jsfiddle.net/LEqjm/
If there's more than one scrollable element that you want to scroll, you'll need to change the scrollTop
of each one individually, based on the offsetTop
s of the intervening elements. This should give you the fine-grained control to avoid the problem you're having.
如果要滚动的可滚动元素不止一个,则需要scrollTop
根据offsetTop
中间元素的s分别更改每个元素的s。这应该给你细粒度的控制,以避免你遇到的问题。
EDIT: offsetTop isn't necessarily relative to the parent element - it's relative to the first positioned ancestor. If the parent element isn't positioned (relative, absolute or fixed), you may need to change the second line to:
编辑: offsetTop 不一定相对于父元素 - 它相对于第一个定位的祖先。如果父元素未定位(相对、绝对或固定),您可能需要将第二行更改为:
target.parentNode.scrollTop = target.offsetTop - target.parentNode.offsetTop;
回答by jfrohn
Fixed it with:
修复它:
element.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' })
see: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
见:https: //developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
回答by dipole_moment
var el = document.querySelector("yourElement");
window.scroll({top: el.offsetTop, behavior: 'smooth'});
回答by Jesco
Play around with scrollIntoViewIfNeeded()
... make sure it's supported by the browser.
试试看scrollIntoViewIfNeeded()
……确保浏览器支持它。
回答by Michal Tsadok
I've added a way to display the imporper behavior of the ScrollIntoView - http://jsfiddle.net/LEqjm/258/[it should be a comment but I don't have enough reputation]
我添加了一种方法来显示 ScrollIntoView 的不正当行为 - http://jsfiddle.net/LEqjm/258/[它应该是一个评论,但我没有足够的声誉]
$("ul").click(function() {
var target = document.getElementById("target");
if ($('#scrollTop').attr('checked')) {
target.parentNode.scrollTop = target.offsetTop;
} else {
target.scrollIntoView(!0);
}
});
回答by Robert Koritnik
jQuery plugin scrollintoview()
increases usability
jQuery 插件scrollintoview()
提高了可用性
Instead of default DOM implementation you can use a plugin that animates movement and doesn't have any unwanted effects. Here's the simplest way of using it with defaults:
代替默认的 DOM 实现,您可以使用一个插件来为运动设置动画并且没有任何不需要的效果。这是使用默认值的最简单方法:
$("yourTargetLiSelector").scrollintoview();
Anyway head over to this blog postwhere you can read all the details and will eventually get you to GitHub source codeof the plugin.
无论如何,请转到这篇博客文章,您可以在其中阅读所有详细信息,并最终将让您获得该插件的GitHub 源代码。
This plugin automatically searches for the closest scrollable ancestor element and scrolls it so that selected element is inside its visible view port. If the element is already in the view port it doesn't do anything of course.
此插件会自动搜索最近的可滚动祖先元素并滚动它,以便所选元素位于其可见视口内。如果元素已经在视口中,它当然不会做任何事情。
回答by paddotk
I had this problem too, and spent many hours trying to deal with it. I hope my resolution may still help some people.
我也遇到了这个问题,并花了很多时间试图解决它。我希望我的决心仍然可以帮助一些人。
My fix ended up being:
我的修复最终是:
- For Chrome: changing
.scrollIntoView()
to.scrollIntoView({block: 'nearest'})
(thanks to @jfrohn). - For Firefox: apply
overflow: -moz-hidden-unscrollable;
on the container element that shifts. - Not tested in other browsers.
- 对于 Chrome:更改
.scrollIntoView()
为.scrollIntoView({block: 'nearest'})
(感谢 @jfrohn)。 - 对于 Firefox:应用于
overflow: -moz-hidden-unscrollable;
移动的容器元素。 - 未在其他浏览器中测试。
回答by Yash
Adding more information to @Jesco
post.
添加更多信息以@Jesco
发布。
Element.scrollIntoViewIfNeeded()
non-standard WebKit method
for Chrome, Opera, Safari browsers.
If the element is already within the visible area of the browser window, then no scrolling takes place.Element.scrollIntoView()
method scrolls the element on which it's called into the visible area of the browser window.
Element.scrollIntoViewIfNeeded()
non-standard WebKit method
适用于 Chrome、Opera、Safari 浏览器。
如果元素已经在浏览器窗口的可见区域内,则不会发生滚动。Element.scrollIntoView()
方法将调用它的元素滚动到浏览器窗口的可见区域。
Try the below code in mozilla.org
scrollIntoView()
link. Post to identify Browser
在mozilla.org
scrollIntoView()
链接中尝试以下代码。发布以识别浏览器
var xpath = '//*[@id="Notes"]';
ScrollToElement(xpath);
function ScrollToElement(xpath) {
var ele = $x(xpath)[0];
console.log( ele );
var isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);
if (isChrome) { // Chrome
ele.scrollIntoViewIfNeeded();
} else {
var inlineCenter = { behavior: 'smooth', block: 'center', inline: 'start' };
ele.scrollIntoView(inlineCenter);
}
}
回答by KungPhoo
Using Brilliant's idea, here's a solution that only (vertically) scrolls if the element is NOT currently visible. The idea is to get the bounding box of the viewport and the element to be displayed in browser-window coordinate space. Check if it's visible and if not, scroll by the required distance so the element is shown at the top or bottom of the viewport.
使用 Brilliant 的想法,这是一个仅在元素当前不可见时(垂直)滚动的解决方案。这个想法是获取视口的边界框和要在浏览器窗口坐标空间中显示的元素。检查它是否可见,如果不可见,滚动所需的距离,以便元素显示在视口的顶部或底部。
function ensure_visible(element_id)
{
// adjust these two to match your HTML hierarchy
var element_to_show = document.getElementById(element_id);
var scrolling_parent = element_to_show.parentElement;
var top = parseInt(scrolling_parent.getBoundingClientRect().top);
var bot = parseInt(scrolling_parent.getBoundingClientRect().bottom);
var now_top = parseInt(element_to_show.getBoundingClientRect().top);
var now_bot = parseInt(element_to_show.getBoundingClientRect().bottom);
// console.log("Element: "+now_top+";"+(now_bot)+" Viewport:"+top+";"+(bot) );
var scroll_by = 0;
if(now_top < top)
scroll_by = -(top - now_top);
else if(now_bot > bot)
scroll_by = now_bot - bot;
if(scroll_by != 0)
{
scrolling_parent.scrollTop += scroll_by; // tr.offsetTop;
}
}
回答by yael kfir
i had the same problem, i fixed it by removing the transform:translateY
CSS i placed on the footer
of the page.
我遇到了同样的问题,我通过删除transform:translateY
放置在footer
页面上的 CSS 来修复它。