40

我正在构建一个带有固定位置导航栏的单页网站,该导航栏通过锚链接平滑滚动到不同的部分元素。滚动到元素的默认行为是将其与浏览器窗口的顶部对齐。相反,我想将元素对齐到屏幕的中间。

我使用此标记进行导航:

<nav class="main-nav">
  <a href="#top">Top</a>
  <a href="#section-1">Section 1</a>
  <a href="#section-2">Section 2</a>
  <a href="#section-3">Section 3</a>
  <a href="#section-4">Section 4</a>
  <a href="#section-5">Section 5</a>
</nav>

我使用kswedberg 的 jQuery Smooth Scroll 插件来平滑滚动。我这样启动它:

$('.main-nav a').smoothScroll({
  offset: 0,
  speed: 700
});

我想将偏移量设置为((window).height / 2) - (element height / 2)垂直居中,但我需要帮助来弄清楚如何正确执行它。

我需要它:

  • 获取窗口的高度并将其除以二
  • 获取元素的高度并将其除以二
  • 后者减去前者
  • 如果可能,如果元素高于窗口,则默认将其对齐到顶部

由于有很多锚链接,我假设我需要检查单击的锚链接链接到的元素的高度,或者为每个锚链接启动 smoothScroll。

有人知道怎么做这个吗?

4

5 回答 5

39

这是使用 scrollTo() 使用普通 JQuery 的方法

 $('.main-nav a').on('click', function(e) { 
  var el = $( e.target.getAttribute('href') );
  var elOffset = el.offset().top;
  var elHeight = el.height();
  var windowHeight = $(window).height();
  var offset;

  if (elHeight < windowHeight) {
    offset = elOffset - ((windowHeight / 2) - (elHeight / 2));
  }
  else {
    offset = elOffset;
  }
  var speed = 700;
  $('html, body').animate({scrollTop:offset}, speed);
});

这是 straker 的代码和来自这个问题的代码的组合:jQuery scrollTo - Center Div in Window Vertically

于 2014-02-14T11:49:47.970 回答
35

API 提供了一种执行未绑定到元素的smoothScroll的方法。您需要在锚标记的 onclick 事件中执行此方法,以便您可以访问它的目标。然后,您可以计算到达所需位置所需的条件。由于offset现在是绝对偏移量而不是相对偏移量,因此您需要获取要滚动到的确切位置。

$('.main-nav a').on('click', function(e) { 
  var el = $( e.target.getAttribute('href') );
  var elOffset = el.offset().top;
  var elHeight = el.height();
  var windowHeight = $(window).height();
  var offset;

  if (elHeight < windowHeight) {
    offset = elOffset - ((windowHeight / 2) - (elHeight / 2));
  }
  else {
    offset = elOffset;
  }

  $.smoothScroll({ speed: 700 }, offset);
  return false;
});
于 2013-08-09T16:33:07.480 回答
11

这可以使用 vanilla JS 来完成scrollIntoView

document.getElementById('myID').scrollIntoView({
    behavior: 'auto',
    block: 'center',
    inline: 'center'
});
于 2020-05-27T13:25:39.600 回答
3

这是一个可靠的方法

var $window = $(window),
    $element = $('.my-element'),
    elementTop = $element.offset().top,
    elementHeight = $element.height(),
    viewportHeight = $window.height(),
    scrollIt = elementTop - ((viewportHeight - elementHeight) / 2);

    $window.scrollTop(scrollIt);
于 2019-07-29T09:31:05.633 回答
0

这是我最终使用的解决方案。如果您有一个可滚动的父容器,它包含所有在单击时需要居中的元素,它会非常有用。

随意运行代码片段以查看它的实际效果!

$('#main-nav a').on('click', function(e) { 
  var el = $(this), parentEl = $('#main-nav');
  
  var elOffset = el.offset().top + parentEl.scrollTop();
  var elHeight = el.height();
  var parentHeight = parentEl.height();
  
  var offset = elOffset - ((parentHeight - elHeight) / 2);
 
  parentEl.animate({scrollTop:offset}, 700);
});
#main-nav {
  height: 200px;
  width: 200px;
  outline: 1px solid red;
  overflow: hidden;
}

#main-nav a {
  height: 50px;
  background: blue;
  display: block;
  margin-bottom: 5px;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav id="main-nav">
  <a href="#top">Top</a>
  <a href="#section-1">Section 1</a>
  <a href="#section-2">Section 2</a>
  <a href="#section-3">Section 3</a>
  <a href="#section-4">Section 4</a>
  <a href="#section-5">Section 5</a>
  <a href="#section-6">Section 6</a>
  <a href="#section-7">Section 7</a>
  <a href="#section-8">Section 8</a>
  <a href="#section-9">Section 9</a>
  <a href="#section-10">Section 10</a>
</nav>

于 2019-07-24T23:19:34.220 回答