我有一个页面,其中一个滚动条包含从数据库动态生成的带有div的表行。每个表行就像一个链接,有点像你在视频播放器旁边看到的YouTube播放列表。
当用户访问页面时,他们所在的选项应该会转到滚动div的顶部。这个功能正在工作。问题是,这有点太过分了。比如他们的选项高了10像素。因此,页面被访问,url被用来识别选择了哪个选项,然后将该选项滚动到滚动div的顶部。注意:这不是窗口的滚动条,这是一个带有滚动条的div。
我正在使用这段代码,使它移动选中的选项到div的顶部:
var pathArray = window.location.pathname.split( '/' );
var el = document.getElementById(pathArray[5]);
el.scrollIntoView(true);
它将它移动到div的顶部,但大约10个像素太高了。
有人知道怎么解决吗?
假设你想滚动到DOM中相同级别的div,并且类名为“scroll-with-offset”,那么这个CSS将解决这个问题:
.scroll-with-offset {
padding-top: 100px;
margin-bottom: -100px;
}
与页面顶部的偏移量为100px。它只会像block: 'start'那样工作:
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
所发生的事情是div的顶部在正常位置,但它们的内部内容开始低于正常位置100px。这就是padding-top:100px的作用。margin-bottom: -100px用来抵消下面div的额外边距。
为了使解决方案完整,还添加了这个CSS来抵消最顶部和最底部div的边距/填充:
.top-div {
padding-top: 0;
}
.bottom-div {
margin-bottom: 0;
}
我的主要想法是在我们想要滚动到的视图上方创建一个tempDiv。它在我的项目中工作得很好,没有滞后。
scrollToView = (element, offset) => {
var rect = element.getBoundingClientRect();
var targetY = rect.y + window.scrollY - offset;
var tempDiv;
tempDiv = document.getElementById("tempDiv");
if (tempDiv) {
tempDiv.style.top = targetY + "px";
} else {
tempDiv = document.createElement('div');
tempDiv.id = "tempDiv";
tempDiv.style.background = "#F00";
tempDiv.style.width = "10px";
tempDiv.style.height = "10px";
tempDiv.style.position = "absolute";
tempDiv.style.top = targetY + "px";
document.body.appendChild(tempDiv);
}
tempDiv.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
示例使用
onContactUsClick = () => {
this.scrollToView(document.getElementById("contact-us"), 48);
}
希望能有所帮助
我试着使用上面的一些答案,但滚动不起作用。经过一番研究,我注意到滚动位置实际上非常奇怪(甚至是负值),这是由Angular在路由器出口中渲染页面的方式引起的。
我的解决方案是从页面顶部开始计算元素的滚动位置。我在模板的开头放置了一个id为start-of-page的元素,通过减去目标片段位置来获得滚动量。
ngAfterViewInit(): void {
this.route.fragment.subscribe(fragment => {
try {
// @ts-ignore
// document.querySelector('#hero').scrollIntoView({behavior:smooth, block: "start", inline: "start"});
// @ts-ignore
// document.querySelector('#' + fragment).scrollIntoView({behavior:smooth, block: "start", inline: "start"});
this._scrollTo('#' + fragment,0);
} catch (e) { };
});
}
private _scrollTo(selector: any, yOffset = 0){
const base = document.querySelector('#start-of-page');
const el = document.querySelector(selector);
// @ts-ignore
const y = el.getBoundingClientRect().top - base.getBoundingClientRect().top;
window.scrollTo({top: y, behavior: 'smooth'});
}
基于之前的答案,我在一个Angular5项目中这样做。
开始:
// el.scrollIntoView(true);
el.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
window.scrollBy(0, -10);
但这样会产生一些问题,需要为scrollBy()设置timeout,如下所示:
//window.scrollBy(0,-10);
setTimeout(() => {
window.scrollBy(0,-10)
}, 500);
它在MSIE11和Chrome 68+中工作完美。我没有在FF测试过。500毫秒是我敢说的最短延迟。向下走有时会失败,因为平滑的滚动还没有完成。根据您自己的项目进行调整。
+1到Fred727为这个简单而有效的解决方案。
用绝对法定位锚
另一种方法是将锚定位在页面上想要的位置,而不是依赖于按偏移量滚动。我发现它可以更好地控制每个元素(例如。如果你想对某些元素有不同的偏移量),并且可能对浏览器API的变化/差异更有抵抗力。
<div id="title-element" style="position: relative;">
<div id="anchor-name" style="position: absolute; top: -100px; left: 0"></div>
</div>
现在相对于元素的偏移量被指定为-100px。创建一个函数来创建这个锚,以便代码重用,或者如果你正在使用一个现代的JS框架,比如React,通过创建一个渲染锚的组件来实现,并传入锚的名称和每个元素的对齐方式,这些元素可能相同,也可能不相同。
然后使用:
const element = document.getElementById('anchor-name')
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
平滑滚动,偏移量为100px。