jQuery滚动到元素


2322

我有这个input元素:

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

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

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

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

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

动画不应太快且应流畅。

我正在运行最新的jQuery版本。我更喜欢不安装任何插件,而是使用默认的jQuery功能来实现此目的。



scrollTo由于chrome插件而被我禁用了,不确定是哪个。
杰克逊(Jacksonkr)

Answers:


4019

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

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

我从文章平稳地滚动到没有jQuery插件的元素中获得了代码。我已经在下面的示例中对其进行了测试。

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


24
这并非在所有情况下都有效。见stackoverflow.com/questions/2905867/...
亚尼斯Elmeris

7
@BarryChapman不完全是。谷歌搜索后,我发现,所以如果您不想每种浏览器类型都具有额外的逻辑,则需要两个标签。
s3m3n

72
如果您不想使用动画,而是想立即跳转到该元素,请使用.scrollTop(…)代替.animate({scrollTop: …}, …)
罗里·奥肯

11
除了解决方案(效果很好)之外,您还可以添加on complete函数,该函数将#标签添加到url。在这种情况下,它不会滚动,因为scrollTo已经滚动到了正确的位置,并且如果用户复制了URL,它将自动捕捉到页面上的正确位置。
桑德2014年

10
如果您在动画制作完成后使用回调来运行,并且注意到此解决方案触发了两次回调,请尝试使用“ $('html body')。animate(...”而不是“ $('html,body') .animate(...”逗号创建了两个生命的事件,一个是HTML,一个身体,你真的只是想一个HTML正文感谢@TJ克劳德。stackoverflow.com/questions/8790752/...
BoatCode

526

jQuery .scrollTo()方法

jQuery .scrollTo():查看-演示,API,源

我写了这个轻量级的插件,以使页面/元素滚动更加容易。在可以传递目标元素或指定值的地方,它很灵活。也许这可能是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:动画完成后调用的函数。


2
它一直有效,直到最近更新了chrome。我有一个当前可以在memoryboxweddings.com/photography-posts上使用的版本(如果您想尝试一下)。修复后,我将发布更新。
蒂莫西·佩雷斯

已修复,事实证明它实际上是jquery.com的JS文件,已将其杀死。如果您尝试过,现在应该可以使用。
蒂莫西·佩雷斯

4
@TimothyPerez:我确定这意味着允许商业用途吗?我确定有很多人只想在其网站的任何地方使用该代码段,这将有助于他们晚上入睡更轻松一些?也许像MIT许可证这样的东西可能适合您的需求?en.wikipedia.org/wiki/MIT_License
罗伯特·马塞利

13
$('body')在FF中不起作用,因此尝试了$('html,body')起作用。
kiranvj 2013年

5
如果有人需要的这个脚本源,那么在这里你可以得到它flesler.com/jquery/scrollTo/js/jquery.scrollTo-min.js
Arturs

370

如果您对平滑滚动效果不太感兴趣,而仅对滚动到特定元素感兴趣,则不需要为此使用某些jQuery函数。Javascript已解决您的问题:

https://developer.mozilla.org/zh-CN/docs/Web/API/element.scrollIntoView

因此,您需要做的就是: $("selector").get(0).scrollIntoView();

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


12
您还可以使用$(selector)[0]吗?
RobW 2014年

16
RobW,是的,您只能使用[0],但是get(0)可以防止未定义的索引或负索引。参见来源: james.padolsey.com/jquery/#v=1.10.2&fn=jQuery.fn.get
corbacho 2014年

21
如果您根本不想使用jQuery,请使用document.getElementById('#elementID').scrollIntoView()。加载一个大约100k的库只是为了选择一个元素,然后将其转换为常规JavaScript是没有用的。
加文

62
@Gavin我确定你的意思是:document.getElementById('elementID').scrollIntoView()
Brian

3
凉。但是在使用之前,请确保浏览器支持此功能。根据Mozilla的“这是一项实验技术”
Tejasvi Hegde

48

使用这个简单的脚本

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

将进行某种排序,如果在URL中找到一个哈希标记,则scrollTo会为该ID设置动画。如果未找到哈希标记,则忽略脚本。


$(window.location.hash)不适用于无法满足jQuery的正则表达式ID检测的哈希。例如,包含数字的哈希。这也有点危险;输入的格式应经过验证,这样您就不必最终选择其他元素。
dchacke

35

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>


1
为了使其更加通用并消除在浏览器链接窗口中不必要的主题标签放置,我只是对代码进行了如下调整: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); }); });
bubencode

31

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

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

例如:

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

22

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

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

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

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


21

这就是我做到的方式。

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>

文件


6
很短很甜。需要注意的一件事-我认为这只会将其滚动到视图中(可能在视口的底部),而不是像设置scrollTop一样将其滚动到视口的顶部。
OG肖恩

20

我知道没有jQuery的方法:

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

编辑:已经两年了,我仍然从这个帖子中随机获得声誉


18

如果仅处理滚动到输入元素,则可以使用focus()。例如,如果要滚动到第一个可见输入,请执行以下操作:

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

或具有class的容器中的第一个可见输入.error

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

感谢Tricia Ball指出了这一点!


17

使用此解决方案,您不需要任何插件,除了将脚本放在结束标记之前,不需要任何设置</body>

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

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

加载时,如果地址中有哈希,我们将滚动至该哈希。

并且-每当您单击a带有href哈希的链接(例如)时#top,我们都会滚动到该链接。


这可能应该> 1代替0,只是因为/#导致此脚本中断
Tallboy

从技术上讲,您不应该以空的哈希URL结尾,除非链接的结构不良,但TY。(尽管我自己的代码版本已经包含了此补丁^^)
Jonathan

此代码有一个抖动,但是很容易解决。您需要return false;在on click事件结束时防止发生默认操作-立即滚动到锚点。
roncli '16

2
@roncli好点-或者您也可以e.preventDefault();
Jonathan

e.preventDefault()但是在点击时不会更新网址中的哈希,它始终是没有哈希的网址
jayasurya_j

8

在大多数情况下,最好使用插件。说真的 我要在这里兜风。当然也有其他人。但是请检查它们是否真的避免了您首先想要插件的陷阱-并非所有人都愿意。

我已经写过其他地方使用插件的原因。简而言之,这是支撑大多数答案的一种方法

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

是糟糕的UX。

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

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

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

要处理这些问题(以及其他问题),可以使用我的插件jQuery.scrollable。然后,呼叫变为

$( window ).scrollTo( targetPosition );

就是这样。当然,还有更多选择

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

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

即使在html元素上设置了边框,该方法也有效。


8

动画:

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

8

如果要在溢出容器中滚动(而不是$('html, body')上面的回答),并且还可以使用绝对定位,则可以这样做:

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

container.animate({
  scrollTop: pos
}


6

这是我使用通用类选择器抽象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>


6

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

像这样:<a scroll="#product">Click me</a>。可以在任何元素上使用。

(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>

4
var scrollTo = function($parent, $element) {
    var topDiff = $element.position().top - $parent.position().top;

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

4

$('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
Alex Podworny17年

添加断字:全力以赴;遇到麻烦的CSS元素。Android / iOS网络视图jQuery.animate({scrollTop:y})位置不正确。medium.com/@ellery.leung/…–
daliaessam


3
$('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);

3

当用户使用#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>

3

我设置了一个模块scroll-element npm 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帖子的帮助下撰写:

这是代码:

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 }
}

2

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

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

2

我编写了一个通用函数,该函数可以滚动到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);
};

2

对于它的价值,这是我设法通过滚动可以在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();

2

这为我工作:

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

2

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>


2

ONELINER

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


1
它完美地工作!
jjoselon

1

截至2019年的更新答案:

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

您应该使用以下选择器作为主体:[document.documentElement,document.body] AND不需要方程式中的主体偏移。$('#subject')。offset()。top就足够了。
ali6p
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.