Javascript scrolIintoview平滑滚动和偏移

Tim*_*jma 10 javascript

我的网站有这个代码

function clickMe() {
   var element = document.getElementById('about');
   element.scrollIntoView({
       block: "start",
       behavior: "smooth",
   });
}
Run Code Online (Sandbox Code Playgroud)

这工作得很好,但我有一个固定的标题,所以当代码滚动到元素时,标题是阻碍.

有没有办法有一个偏移,使其顺利滚动?

lak*_*tak 62

您可以scrollIntoView()在您的示例中使用类似的方法

function clickMe() {
  var element = document.getElementById('about');
  element.scrollIntoView({
    block: 'start',
    behavior: 'smooth',
  });
}
Run Code Online (Sandbox Code Playgroud)

如果将scroll-margin标题的高度添加到目标元素 ( about):

.about {
  scroll-margin: 100px;
}
Run Code Online (Sandbox Code Playgroud)

不需要其他任何东西。所有现代浏览器都scroll-margin支持。

  • 这是一个比上面的解决方案简单得多的解决方案,最好的部分是,它有效! (7认同)
  • 这是最好的答案 - 最干净的解决方案。完美谢谢! (2认同)

Mos*_*e L 42

如果元素的高度很小(比视口短),简单而优雅的解决方案:

element.scrollIntoView({ behavior: 'instant', block: 'center' });
Run Code Online (Sandbox Code Playgroud)

block: center将滚动元件,因此元件的中心是在视口的垂直中心,所以顶部集流管将不包括它。

  • 最好和简单的答案在这里 (7认同)
  • 哦哇,大开眼界! (3认同)

ekf*_*ann 22

SørenD.Ptæus的回答让我走上了正确的轨道,但是getBoundingClientRect()当我不在最顶层的时候我遇到了问题window.

我的解决方案为他增加了一点,以便getBoundingClientRect()更加一致地使用更多功能.我使用了这里概述的方法并实现它以使其按预期工作.

const element = document.getElementById('targetElement');
const offset = 45;
const bodyRect = document.body.getBoundingClientRect().top;
const elementRect = element.getBoundingClientRect().top;
const elementPosition = elementRect - bodyRect;
const offsetPosition = elementPosition - offset;

window.scrollTo({
  top: offsetPosition,
  behavior: 'smooth'
});
Run Code Online (Sandbox Code Playgroud)

Codepen示例

在实施时请记住包含polyfill!

  • 最佳答案在这里 (2认同)

Sør*_*æus 21

有没有办法有一个偏移,使其顺利滚动?

是的,但没有使用scrollIntoView()

scrollIntoViewOptionsElement.scrollIntoView()不会允许你使用的偏移量.当您想要滚动到元素的确切位置时,它非常有用.

但是,您可以使用带有选项的Window.scrollTo()来滚动到偏移位置并顺利地执行此操作.

如果您的标题高度30px为例如,您可以执行以下操作:

function scrollToTargetAdjusted(){
    var element = document.getElementById('targetElement');
    var headerOffset = 45;
    var elementPosition = element.getBoundingClientRect().top;
    var offsetPosition = elementPosition - headerOffset;

    window.scrollTo({
         top: offsetPosition,
         behavior: "smooth"
    });
}
Run Code Online (Sandbox Code Playgroud)

这将平滑地滚动到您的元素,以便它不会被标题阻止查看.

注意:您要减去偏移量,因为要在元素上滚动标题之前要停止.

看到它在行动

您可以在下面的代码段中比较这两个选项.

<script type="text/javascript">
  function scrollToTarget() {

    var element = document.getElementById('targetElement');
    element.scrollIntoView({
      block: "start",
      behavior: "smooth",
    });
  }

  function scrollToTargetAdjusted() {
    	var element = document.getElementById('targetElement');
      var headerOffset = 45;
    	var elementPosition = element.getBoundingClientRect().top;
      var offsetPosition = elementPosition - headerOffset;
      
      window.scrollTo({
          top: offsetPosition,
          behavior: "smooth"
      });   
  }

  function backToTop() {
    window.scrollTo(0, 0);
  }
</script>

<div id="header" style="height:30px; width:100%; position:fixed; background-color:lightblue; text-align:center;"> <b>Fixed Header</b></div>

<div id="mainContent" style="padding:30px 0px;">

  <button type="button" onclick="scrollToTarget();">element.scrollIntoView() smooth, header blocks view</button>
  <button type="button" onclick="scrollToTargetAdjusted();">window.scrollTo() smooth, with offset</button>

  <div style="height:1000px;"></div>
  <div id="targetElement" style="background-color:red;">Target</div>
  <br/>
  <button type="button" onclick="backToTop();">Back to top</button>
  <div style="height:1000px;"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

  • `getBoundingClientRect().top` 指的是元素与视口顶部之间的距离。当您希望使用相对于当前位置滚动的“scrollBy”时,这比使用绝对位置的“scrollTo”更有用。如果该元素不在相对定位的父元素中,请考虑使用“offsetTop”。否则,您需要将“window.pageYOffset”添加到“getBoundingClientRect().top”以获取“scrollTo”的正确值。 (27认同)
  • @coreyward +1 表示“window.pageYOffset”提示 (2认同)
  • 您的解决方案确实会滚动到随机位置,具体取决于视图现在的位置。 (2认同)

Fel*_*uez 9

我尝试了其他解决方案,但出现了一些奇怪的行为。但是,这对我有用。

function scrollTo(id) {
    var element = document.getElementById(id);
    var headerOffset = 60;
    var elementPosition = element.offsetTop;
    var offsetPosition = elementPosition - headerOffset;
    document.documentElement.scrollTop = offsetPosition;
    document.body.scrollTop = offsetPosition; // For Safari
}
Run Code Online (Sandbox Code Playgroud)

和风格:

html {
    scroll-behavior: smooth;
}
Run Code Online (Sandbox Code Playgroud)


The*_*ool 9

还有滚动边距和滚动填充。

对我来说,滚动填充对于这类东西最有用。

/* Keyword values */
scroll-padding-top: auto;

/* <length> values */
scroll-padding-top: 10px;
scroll-padding-top: 1em;
scroll-padding-top: 10%;

/* Global values */
scroll-padding-top: inherit;
scroll-padding-top: initial;
scroll-padding-top: unset;
Run Code Online (Sandbox Code Playgroud)

此外,您可以通过将滚动行为设置为平滑来使用平滑滚动。

/* Keyword values */
scroll-behavior: auto;
scroll-behavior: smooth;

/* Global values */
scroll-behavior: inherit;
scroll-behavior: initial;
scroll-behavior: revert;
scroll-behavior: unset;
Run Code Online (Sandbox Code Playgroud)

不过,它可能与 Internet Explorer 不兼容。


Mad*_*gon 8

以防止任何元素与固定顶部相交。实际上有很多方法可以做到这一点。最近我在CSS文件中使用scroll-padding-top。

* {
    scroll-behavior: smooth;
    scroll-padding-top: 100px; /* this pixel should match fixed header height */
  }
Run Code Online (Sandbox Code Playgroud)

平滑滚动是什么意思?只需添加scroll-behavior: smooth;CSS 即可。

如果您想要打开一个新页面然后平滑滚动,那么这是一种不同的方法。你可以在这里查看我的回答

如果您要查找的是检查元素是否在视口中,那么那就是另一个故事了。我不确定您要找哪一个。如果是这个,请确认,我会花更多时间为您总结答案。我遇到了这个问题,我终于解决了。


yan*_*-io 7

Søren D. Ptæus的几乎是正确的,但它仅在用户处于顶部时才有效。这是因为 getBoundingClientRect 将始终为我们获取相对高度,而使用具有相对高度的 window.scrollTo 不起作用。

ekfuhrmann通过从 body 元素获取总高度并计算实际高度改进答案。但是,我认为它可以比这更容易,我们可以简单地使用相对位置并使用 window.scrollBy。

注意:主要区别是 window.scrollBy

const HEADER_HEIGHT = 45;

function scrollToTargetAdjusted(){
    const element = document.getElementById('targetElement');
    const elementPosition = element.getBoundingClientRect().top;
    const offsetPosition = elementPosition - HEADER_HEIGHT;

    window.scrollBy({
         top: offsetPosition,
         behavior: "smooth"
    });
}
Run Code Online (Sandbox Code Playgroud)


Yul*_*ian 6

我知道这是一个 hack 并且绝对是您应该谨慎使用的东西,但您实际上可以在元素中添加一个padding和一个否定margin。我不能保证它对你有用,因为我没有你的标记和代码,但我有一个类似的问题并使用这个解决方法来解决它。

假设您的标头是30px并且您想要偏移量15px,然后:

  #about {
     padding-top: 45px; // this will allow you to scroll 15px below your 30px header
     margin-top: -45px; // and this will make sure that you don't change your layout because of it
  }
Run Code Online (Sandbox Code Playgroud)