使用 jQuery 滚动到一个元素

Posted

技术标签:

【中文标题】使用 jQuery 滚动到一个元素【英文标题】:Scroll to an element with jQuery 【发布时间】:2011-10-04 08:34:46 【问题描述】:

我有这个input 元素:

<input type="text" class="textfield" value="" id="subject" name="subject">

然后我还有一些其他元素,比如其他文本输入、文本区域等。

当用户点击input#subject 时,页面应该滚动到页面的最后一个元素,并带有漂亮的动画。它应该是滚动到底部而不是顶部。

页面的最后一项是带有#submitsubmit 按钮:

<input type="submit" class="submit" id="submit" name="submit" value="Ok, Done.">

动画不能太快,应该流畅。

我正在运行最新的 jQuery 版本。我宁愿不安装任何插件,而是使用默认的 jQuery 功能来实现这一点。

【问题讨论】:

developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView scrollTo 被我禁用了,因为 chrome 插件,不确定是哪个。 ***.com/a/53873376/2968762 是最好的答案(因为也使用了javascript标签)。不知道为什么它被不必要地阻止了。 【参考方案1】:

假设您有一个 ID 为 button 的按钮,请尝试以下示例:

$("#button").click(function() 
    $([document.documentElement, document.body]).animate(
        scrollTop: $("#elementtoScrollToID").offset().top
    , 2000);
);

我从文章 Smoothly scroll to an element without a jQuery plugin 中获得了代码。我已经在下面的示例中对其进行了测试。

<html>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
    <script>
        $(document).ready(function ()
            $("#click").click(function ()
                $('html, body').animate(
                    scrollTop: $("#div1").offset().top
                , 2000);
            );
        );
    </script>
    <div id="div1" style="height: 1000px; width 100px">
        Test
    </div>
    <br/>
    <div id="div2" style="height: 1000px; width 100px">
        Test 2
    </div>
    <button id="click">Click me</button>
</html>

【讨论】:

这并不适用于所有情况。见***.com/questions/2905867/… 如果您不想要动画,而是想立即跳转到元素,请使用.scrollTop(…) 而不是.animate(scrollTop: …, …) 如果你想阅读那篇文章,这里有一个工作链接:Smoothly scroll to an element without a jQuery plugin【参考方案2】:

jQuery .scrollTo(): View - Demo, API, Source

我编写了这个轻量级插件来使页面/元素滚动更容易。它很灵活,您可以传入目标元素或指定值。或许这会成为 jQuery 下一个正式版本的一部分,你觉得呢?


示例用法:

$('body').scrollTo('#target'); // Scroll screen to target element

$('body').scrollTo(500); // Scroll screen 500 pixels down

$('#scrollable').scrollTo(100); // Scroll individual element 100 pixels down

选项:

scrollTarget:指示所需滚动位置的元素、字符串或数字。

offsetTop:定义滚动目标上方额外间距的数字。

duration:一个字符串或数字,确定动画将运行多长时间。

easing:一个字符串,指示用于过渡的缓动函数。

complete:动画完成后调用的函数。

【讨论】:

$('body') 在 FF 中不起作用,所以尝试了 $('html, body') ,它起作用了。 如果有人需要这个脚本源,那么在这里你可以得到它flesler.com/jquery/scrollTo/js/jquery.scrollTo-min.js【参考方案3】:

如果您对平滑滚动效果不太感兴趣,而只是对滚动到特定元素感兴趣,那么您不需要一些 jQuery 函数。 Javascript 已经涵盖了您的情况:

https://developer.mozilla.org/en-US/docs/Web/API/element.scrollIntoView

所以你需要做的就是:$("selector").get(0).scrollIntoView();

使用.get(0) 是因为我们要检索 JavaScript 的 DOM 元素,而不是 JQuery 的 DOM 元素。

【讨论】:

你也可以使用$(selector)[0]吗? RobW,是的,您可以只使用 [0],但 get(0) 可以保护您免受未定义或负索引的影响。见源:james.padolsey.com/jquery/#v=1.10.2&fn=jQuery.fn.get 如果您根本不想使用 jQuery,只需使用document.getElementById('#elementID').scrollIntoView()。加载大约 100k 的库只是为了选择一个元素然后将其转换为常规 JavaScript 是没有用的。 @Gavin 我确定你的意思是:document.getElementById('elementID').scrollIntoView()【参考方案4】:

这在没有 jQuery 的情况下是可以实现的:

document.getElementById("element-id").scrollIntoView();

【讨论】:

请停止编辑您的问题以引入无关的闲聊。 数百万 的答案答案仍在“多年后”为其作者提供代表。我们不需要指出这一点,它不会为问题或网站增加任何价值。【参考方案5】:

使用这个简单的脚本

if($(window.location.hash).length > 0)
        $('html, body').animate( scrollTop: $(window.location.hash).offset().top, 1000);

如果在 url 中找到哈希标记,则将 scrollTo 动画到 ID。如果未找到哈希标签,则忽略该脚本。

【讨论】:

【参考方案6】:

jQuery(document).ready(function($) 
  $('a[href^="#"]').bind('click.smoothscroll',function (e) 
    e.preventDefault();
    var target = this.hash,
        $target = $(target);

    $('html, body').stop().animate( 
      'scrollTop': $target.offset().top-40
    , 900, 'swing', function () 
      window.location.hash = target;
     );
   );
 );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<ul role="tablist">
  <li class="active" id="p1"><a href="#pane1" role="tab">Section 1</a></li>
  <li id="p2"><a href="#pane2" role="tab">Section 2</a></li>
  <li id="p3"><a href="#pane3" role="tab">Section 3</a></li>
</ul>

<div id="pane1"></div>
<div id="pane2"></div>
<div id="pane3"></div>

【讨论】:

为了使其更通用并删除不必要的标签放置到浏览器链接窗口中,我只是调整了以下代码:jQuery(document).ready(function($) $(document).on( "click", 'a[href^="#"]', function( e ) e.preventDefault(); var target = this.hash, $target = $(target); $('html, body').stop().animate( scrollTop: $target.offset().top - 100, 1000); ); );【参考方案7】:

史蒂夫和彼得的解决方案效果很好。

但在某些情况下,您可能必须将值转换为整数。奇怪的是,$("...").offset().top 的返回值有时在float。 使用:parseInt($("....").offset().top)

例如:

$("#button").click(function() 
    $('html, body').animate(
        scrollTop: parseInt($("#elementtoScrollToID").offset().top)
    , 2000);
);

【讨论】:

【参考方案8】:

我就是这样做的。

document.querySelector('scrollHere').scrollIntoView( behavior: 'smooth' )

适用于任何浏览器。

它可以很容易地包装成一个函数

function scrollTo(selector) 
    document.querySelector(selector).scrollIntoView( behavior: 'smooth' )

这是一个工作示例

$(".btn").click(function() 
  document.getElementById("scrollHere").scrollIntoView( behavior: "smooth" )
)
.btn margin-bottom: 500px;
.middle display: block; margin-bottom: 500px; color: red;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button class="btn">Scroll down</button>

<h1 class="middle">You see?</h1>

<div id="scrollHere">Arrived at your destination</div>

Docs

【讨论】:

很短很甜美。需要注意的一件事 - 我认为这只会将其滚动到视图中(可能位于视口的底部),而不是像设置 scrollTop 那样将其滚动到视口的顶部。 我也使用了这个解决方案,但至少 Chrome 版本 92 出于某种原因默认禁用了平滑滚动,所以这个解决方案不再起作用(截至撰写本文时)。实际上相当令人失望。它仍然可以通过为chrome://flags/#smooth-scrolling 配置选择“启用”(而不是“默认”)手动启用。【参考方案9】:

“动画”解决方案的紧凑版本。

$.fn.scrollTo = function (speed) 
    if (typeof(speed) === 'undefined')
        speed = 1000;

    $('html, body').animate(
        scrollTop: parseInt($(this).offset().top)
    , speed);
;

基本用法:$('#your_element').scrollTo();

【讨论】:

【参考方案10】:

使用this solution,您不需要任何插件,并且除了将脚本放在关闭&lt;/body&gt; 标记之前,无需设置

$("a[href^='#']").on("click", function(e) 
  $("html, body").animate(
    scrollTop: $($(this).attr("href")).offset().top
  , 1000);
  return false;
);

if ($(window.location.hash).length > 1) 
  $("html, body").animate(
    scrollTop: $(window.location.hash).offset().top
  , 1000);

加载时,如果地址中有哈希,我们滚动到它。

而且 - 每当您单击带有 href 哈希的 a 链接时,例如#top,我们滚动到它。

##编辑 2020

如果你想要一个纯 JavaScript 解决方案:你也许可以改用类似的东西:

var _scrollToElement = function (selector) 
  try 
    document.querySelector(selector).scrollIntoView( behavior: 'smooth' );
   catch (e) 
    console.warn(e);
  


var _scrollToHashesInHrefs = function () 
  document.querySelectorAll("a[href^='#']").forEach(function (el) 
    el.addEventListener('click', function (e) 
      _scrollToElement(el.getAttribute('href'));
      return false;
    )
  )
  if (window.location.hash) 
    _scrollToElement(window.location.hash);
  


_scrollToHashesInHrefs();

【讨论】:

【参考方案11】:

如果您只处理滚动到输入元素,您可以使用focus()。例如,如果您想滚动到第一个可见输入:

$(':input:visible').first().focus();

或者类.error的容器中的第一个可见输入:

$('.error :input:visible').first().focus();

感谢Tricia Ball 指出这一点!

【讨论】:

【参考方案12】:

如果您想在溢出容器内滚动(而不是上面回答的$('html, body')),同时使用绝对定位,这就是这样做的方法:

var elem = $('#myElement'),
    container = $('#myScrollableContainer'),
    pos = elem.position().top + container.scrollTop() - container.position().top;

container.animate(
  scrollTop: pos

【讨论】:

【参考方案13】:

实现页面滚动到目标div id的简单方法

var targetOffset = $('#divID').offset().top;
$('html, body').animate(scrollTop: targetOffset, 1000);

【讨论】:

【参考方案14】:

动画:

// slide to top of the page
$('.up').click(function () 
    $("html, body").animate(
        scrollTop: 0
    , 600);
    return false;
);

// slide page to anchor
$('.menutop b').click(function()
    //event.preventDefault();
    $('html, body').animate(
        scrollTop: $( $(this).attr('href') ).offset().top
    , 600);
    return false;
);

// Scroll to class, div
$("#button").click(function() 
    $('html, body').animate(
        scrollTop: $("#target-element").offset().top
    , 1000);
);

// div background animate
$(window).scroll(function () 

    var x = $(this).scrollTop();

    // freezze div background
    $('.banner0').css('background-position', '0px ' + x +'px');

    // from left to right
    $('.banner0').css('background-position', x+'px ' +'0px');

    // from right to left
    $('.banner0').css('background-position', -x+'px ' +'0px');

    // from bottom to top
    $('#skills').css('background-position', '0px ' + -x + 'px');

    // move background from top to bottom
    $('.skills1').css('background-position', '0% ' + parseInt(-x / 1) + 'px' + ', 0% ' + parseInt(-x / 1) + 'px, center top');

    // Show hide mtop menu  
    if ( x > 100 ) 
    $( ".menu" ).addClass( 'menushow' );
    $( ".menu" ).fadeIn("slow");
    $( ".menu" ).animate(opacity: 0.75, 500);
     else 
    $( ".menu" ).removeClass( 'menushow' );
    $( ".menu" ).animate(opacity: 1, 500);
    

);

// progres bar animation simple
$('.bar1').each(function(i) 
  var width = $(this).data('width');  
  $(this).animate('width' : width + '%' , 900, function()
    // Animation complete
  );  
);

【讨论】:

【参考方案15】:

在大多数情况下,最好使用插件。严重地。我要去tout mine here。当然,还有其他人。但请检查它们是否真的避免了您首先需要插件的陷阱 - 并非所有人都这样做。

我已经写过使用插件elsewhere 的原因。简而言之,这里支持大多数答案的一个衬里

$('html, body').animate(  scrollTop: $target.offset().top , duration );

是糟糕的用户体验。

动画不响应用户操作。即使用户点击、轻敲或尝试滚动,它也会继续运行。

如果动画的起点靠近目标元素,动画会非常缓慢。

如果目标元素放置在页面底部附近,则无法滚动到窗口顶部。然后滚动动画在中间运动中突然停止。

要处理这些问题(以及bunch of others),您可以使用我的插件jQuery.scrollable。然后调用变为

$( window ).scrollTo( targetPosition );

就是这样。当然还有more options。

关于目标位置,$target.offset().top 在大多数情况下都能胜任。但请注意,返回值不考虑html 元素的边框(see this demo)。如果在任何情况下都需要目标位置准确,最好使用

targetPosition = $( window ).scrollTop() + $target[0].getBoundingClientRect().top;

即使在 html 元素上设置了边框,它仍然有效。

【讨论】:

【参考方案16】:

在找到让我的代码工作的方法之后,我想我应该把事情说清楚: 使用:

$('html, body').animate(
   scrollTop: $("#div1").offset().top
, 2000);

您需要位于页面顶部,因为$("#div1").offset().top 将为您滚动到的不同位置返回不同的数字。如果您已经滚动出顶部,则需要指定确切的 pageY 值(请参阅此处的 pageY 定义:https://javascript.info/coordinates)。

所以现在,问题是计算一个元素的pageY 值。以下是滚动容器为主体的示例:

function getPageY(id) 
    let elem = document.getElementById(id);
    let box = elem.getBoundingClientRect();
    var body = document.getElementsByTagName("BODY")[0];
    return box.top + body.scrollTop; // for window scroll: box.top + window.scrollY;

即使您在某处滚动,上述函数也会返回相同的数字。现在,滚动回该元素:

$("html, body").animate( scrollTop: getPageY('div1') , "slow");

【讨论】:

【参考方案17】:

非常简单易用的自定义 jQuery 插件。只需将属性scroll= 添加到您的可点击元素,并将其值设置为您要滚动到的选择器。

像这样:&lt;a scroll="#product"&gt;Click me&lt;/a&gt;。它可以用于任何元素。

(function($)
    $.fn.animateScroll = function()
        console.log($('[scroll]'));
        $('[scroll]').click(function()
            selector = $($(this).attr('scroll'));
            console.log(selector);
            console.log(selector.offset().top);
            $('html body').animate(
                scrollTop: (selector.offset().top), //- $(window).scrollTop()
                1000
            );
        );
    
)(jQuery);

// RUN
jQuery(document).ready(function($) 
    $().animateScroll();
);

// IN HTML EXAMPLE
// RUN ONCLICK ON OBJECT WITH ATTRIBUTE SCROLL=".SELECTOR"
// <a scroll="#product">Click To Scroll</a>

【讨论】:

【参考方案18】:

这是我使用通用类选择器抽象 ID 和 href 的方法

$(function() 
  // Generic selector to be used anywhere
  $(".js-scroll-to").click(function(e) 

    // Get the href dynamically
    var destination = $(this).attr('href');

    // Prevent href=“#” link from changing the URL hash (optional)
    e.preventDefault();

    // Animate scroll to destination
    $('html, body').animate(
      scrollTop: $(destination).offset().top
    , 500);
  );
);
<!-- example of a fixed nav menu -->
<ul class="nav">
  <li>
    <a href="#section-1" class="nav-item js-scroll-to">Item 1</a>
  </li>
  <li>
    <a href="#section-2" class="nav-item js-scroll-to">Item 2</a>
  </li>
  <li>
    <a href="#section-3" class="nav-item js-scroll-to">Item 3</a>
  </li>
</ul>

【讨论】:

【参考方案19】:
$('html, body').animate(scrollTop: 
  Math.min( 
    $(to).offset().top-margintop, //margintop is the margin above the target
    $('body')[0].scrollHeight-$('body').height()) //if the target is at the bottom
, 2000);

【讨论】:

【参考方案20】:
var scrollTo = function($parent, $element) 
    var topDiff = $element.position().top - $parent.position().top;

    $parent.animate(
        scrollTop : topDiff
    , 100);
;

【讨论】:

【参考方案21】:

这是来自 https://developer.mozilla.org/en-US/docs/Web/API/element.scrollIntoView 的 Atharva 的回答。 只是想添加如果您的文档在 iframe 中,您可以在父框架中选择一个元素以滚动到视图中:

 $('#element-in-parent-frame', window.parent.document).get(0).scrollIntoView();

【讨论】:

【参考方案22】:

$('html, body').animate(...) 不适用于 iPhone、android、Chrome 或 Safari 浏览器。

我必须定位页面的根内容元素。

$('#cotnent').animate(...)

这是我最终得到的结果:

if (navigator.userAgent.match(/(iPod|iPhone|iPad|Android)/)) 
    $('#content').animate(
    scrollTop: $("#elementtoScrollToID").offset().top
   , 'slow');

else
    $('html, body').animate(
    scrollTop: $("#elementtoScrollToID").offset().top
    , 'slow');

所有正文内容都与 #content div 关联

<html>
    ....
    <body>
        <div id="content">
        ...
        </div>
    </body>
</html>

【讨论】:

你真的不应该使用用户代理嗅探。 webaim.org/blog/user-agent-string-history 添加分词:break-all;到有问题的 CSS 元素。 Android/ios webview jQuery.animate(scrollTop: y) 位置不正确。 medium.com/@ellery.leung/…【参考方案23】:

我编写了一个通用函数,可以滚动到 jQuery 对象、CSS 选择器或数值。

示例用法:

// scroll to "#target-element":
$.scrollTo("#target-element");

// scroll to 80 pixels above first element with class ".invalid":
$.scrollTo(".invalid", -80);

// scroll a container with id "#my-container" to 300 pixels from its top:
$.scrollTo(300, 0, "slow", "#my-container");

函数代码:

/**
* Scrolls the container to the target position minus the offset
*
* @param target    - the destination to scroll to, can be a jQuery object
*                    jQuery selector, or numeric position
* @param offset    - the offset in pixels from the target position, e.g.
*                    pass -80 to scroll to 80 pixels above the target
* @param speed     - the scroll speed in milliseconds, or one of the
*                    strings "fast" or "slow". default: 500
* @param container - a jQuery object or selector for the container to
*                    be scrolled. default: "html, body"
*/
jQuery.scrollTo = function (target, offset, speed, container) 

    if (isNaN(target)) 

        if (!(target instanceof jQuery))
            target = $(target);

        target = parseInt(target.offset().top);
    

    container = container || "html, body";
    if (!(container instanceof jQuery))
        container = $(container);

    speed = speed || 500;
    offset = offset || 0;

    container.animate(
        scrollTop: target + offset
    , speed);
;

【讨论】:

【参考方案24】:

当用户点击带有#subject 的输入时,页面应该 使用漂亮的动画滚动到页面的最后一个元素。它 应该是滚动到底部而不是顶部。

页面的最后一项是带有#submit 的提交按钮

$('#subject').click(function()

    $('#submit').focus();
    $('#subject').focus();
);

这将首先向下滚动到#submit,然后将光标恢复到被单击的输入,这模拟了向下滚动,并且适用于大多数浏览器。它也不需要 jQuery,因为它可以用纯 JavaScript 编写。

这种使用focus 函数的方式能否通过链接focus 调用以更好的方式模拟动画。我没有测试过这个理论,但它看起来像这样:

<style>
  #F > *
  
    width: 100%;
  
</style>

<form id="F" >
  <div id="child_1"> .. </div>
  <div id="child_2"> .. </div>
  ..
  <div id="child_K"> .. </div>
</form>

<script>
  $('#child_N').click(function()
  
    $('#child_N').focus();
    $('#child_N+1').focus();
    ..
    $('#child_K').focus();

    $('#child_N').focus();
  );
</script>

【讨论】:

【参考方案25】:

我设置了一个模块scroll-elementnpm install scroll-element。它的工作原理是这样的:

import  scrollToElement, scrollWindowToElement  from 'scroll-element'

/* scroll the window to your target element, duration and offset optional */
let targetElement = document.getElementById('my-item')
scrollWindowToElement(targetElement)

/* scroll the overflow container element to your target element, duration and offset optional */
let containerElement = document.getElementById('my-container')
let targetElement = document.getElementById('my-item')
scrollToElement(containerElement, targetElement)

在以下 SO 帖子的帮助下编写:

offset-top-of-an-element-without-jquery

scrolltop-animation-without-jquery

代码如下:

export const scrollToElement = function(containerElement, targetElement, duration, offset) 
  if (duration == null)  duration = 1000 
  if (offset == null)  offset = 0 

  let targetOffsetTop = getElementOffset(targetElement).top
  let containerOffsetTop = getElementOffset(containerElement).top
  let scrollTarget = targetOffsetTop + ( containerElement.scrollTop - containerOffsetTop)
  scrollTarget += offset
  scroll(containerElement, scrollTarget, duration)


export const scrollWindowToElement = function(targetElement, duration, offset) 
  if (duration == null)  duration = 1000 
  if (offset == null)  offset = 0 

  let scrollTarget = getElementOffset(targetElement).top
  scrollTarget += offset
  scrollWindow(scrollTarget, duration)


function scroll(containerElement, scrollTarget, duration) 
  let scrollStep = scrollTarget / (duration / 15)
  let interval = setInterval(() => 
    if ( containerElement.scrollTop < scrollTarget ) 
      containerElement.scrollTop += scrollStep
     else 
      clearInterval(interval)
    
  ,15)


function scrollWindow(scrollTarget, duration) 
  let scrollStep = scrollTarget / (duration / 15)
  let interval = setInterval(() => 
    if ( window.scrollY < scrollTarget ) 
      window.scrollBy( 0, scrollStep )
     else 
      clearInterval(interval)
    
  ,15)


function getElementOffset(element) 
  let de = document.documentElement
  let box = element.getBoundingClientRect()
  let top = box.top + window.pageYOffset - de.clientTop
  let left = box.left + window.pageXOffset - de.clientLeft
  return  top: top, left: left 

【讨论】:

【参考方案26】:

截至 2019 年的更新答案:

$('body').animate(
    scrollTop: $('#subject').offset().top - $('body').offset().top + $('body').scrollTop()
, 'fast');

【讨论】:

您应该为正文选择此选择器:[document.documentElement, document.body] AND 等式中不需要正文偏移量。 $('#subject').offset().top 就够了。【参考方案27】:

ONELINER

subject.onclick = e=> window.scroll( top: submit.offsetTop, behavior: 'smooth');

subject.onclick = e=&gt; window.scroll(top: submit.offsetTop, behavior: 'smooth');
.box,.footdisplay: flex;background:#fdf;padding:500px 0 .footpadding:250px
<input type="text" class="textfield" value="click here" id="subject" name="subject">

<div class="box">
  Some content
  <textarea></textarea>
</div>

<input type="submit" class="submit" id="submit" name="submit" value="Ok, Done.">

<div class="foot">Some footer</div>

【讨论】:

【参考方案28】:

显示完整的元素(如果当前窗口大小可能的话):

var element       = $("#some_element");
var elementHeight = element.height();
var windowHeight  = $(window).height();

var offset = Math.min(elementHeight, windowHeight) + element.offset().top;
$('html, body').animate( scrollTop: offset , 500);

【讨论】:

【参考方案29】:

对于它的价值,这就是我如何设法为一个可以在带有滚动的 DIV 内的通用元素实现这种行为。在我们的例子中,我们不滚动整个正文,而只是滚动带有溢出的特定元素: auto;在更大的布局中。

它创建一个目标元素高度的假输入,然后将焦点放在它上面,无论您在可滚动层次结构中有多深,浏览器都会处理其余部分。像魅力一样工作。

var $scrollTo = $('#someId'),
inputElem = $('<input type="text"></input>');

$scrollTo.prepend(inputElem);
inputElem.css(
  position: 'absolute',
  width: '1px',
  height: $scrollTo.height()
);
inputElem.focus();
inputElem.remove();

【讨论】:

【参考方案30】:

这对我有用:

var targetOffset = $('#elementToScrollTo').offset().top;
$('#DivParent').animate(scrollTop: targetOffset, 2500);

【讨论】:

以上是关于使用 jQuery 滚动到一个元素的主要内容,如果未能解决你的问题,请参考以下文章

使用 jQuery 滚动到一个元素

使用 jQuery 滚动到一个元素

使用 jQuery 滚动到一个元素

javascript 使用jQuery滚动到一个元素

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

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