jQuery - 使用锚链接将元素滚动到屏幕中间而不是顶部

Posted

技术标签:

【中文标题】jQuery - 使用锚链接将元素滚动到屏幕中间而不是顶部【英文标题】:jQuery - Scroll element to the middle of the screen instead of to the top with an anchor link 【发布时间】:2013-08-11 14:04:27 【问题描述】:

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

我使用这个标记进行导航:

<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's jQuery Smooth Scroll plugin 来平滑滚动。我是这样发起的:

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

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

我需要它:

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

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

有人知道怎么做吗?

【问题讨论】:

我不熟悉这个插件,但 offset 属性看起来很有希望.. 我打算使用offset 属性,但我需要帮助来动态计算它的值。这就是我要问的。 没有什么比页面强制平滑滚动导航更烦人了,即使我在浏览器中关闭了它。 【参考方案1】:

这可以通过使用 scrollIntoView 的 vanilla JS 来完成:

document.getElementById('myID').scrollIntoView(
    behavior: 'auto',
    block: 'center',
    inline: 'center'
);

【讨论】:

我认为我们需要的是解释而不是代码转储。此帖子被标记为低质量。 @enkor 不过,这是正确的解决方案。 +1 简约优雅,魅力十足developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView【参考方案2】:

这是一个可靠的方法

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

    $window.scrollTop(scrollIt);

【讨论】:

【参考方案3】:

这是我最终使用的解决方案。如果您有一个可滚动的父容器,该容器包含单击时需要居中的所有元素,则效果很好。

请随意运行代码 sn-p 来看看它的实际效果!

$('#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>

【讨论】:

【参考方案4】:

下面是使用 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

【讨论】:

我运气不好,$(window).height() 的文档比屏幕大。相反,我使用 window.innerHeight 来获取视口的高度。见这里:***.com/questions/8794338/… 这里要注意如果window是滚动div,计算offset分两步达到目的: 1.滚动到目标元素的顶部; 2. 向上滚动一半大小。 $(el).offset().top - $(window).offset().top + $(window).scrollTop() - $(window).height()/2 + $(el).height()/2 @TerrenceSun 谢谢你的这个公式!!我需要将所选项目置于水平滚动的 div 中。我用可滚动的 div 替换了窗口,将 tops 替换为 lefts,将 heights 替换为 widths,它可以完美运行。【参考方案5】:

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;
);

【讨论】:

太棒了!我试图创建一个与此类似的 onclick 事件,但它需要两次单击才能获得正确的值。这可能是因为我没有意识到我不必将它绑定到元素。谢谢!

以上是关于jQuery - 使用锚链接将元素滚动到屏幕中间而不是顶部的主要内容,如果未能解决你的问题,请参考以下文章

使用jQuery滚动到锚链接[重复]

使用jQuery滚动到锚链接[重复]

Android Studio 如何在 LinearLayout 元素中实现锚链接?

停用平滑滚动元素

单击锚链接时平滑滚动

jQuery滚动到元素的底部而不是顶部