我有这个输入元素:

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

然后我还有一些其他元素,比如其他标签的&<textarea>标签等等。。。

当用户点击<input id=“#subject”>时,页面应该滚动到页面的最后一个元素,并且应该使用一个漂亮的动画(应该滚动到底部而不是顶部)。

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

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

动画不应该太快,应该是流畅的。

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


当前回答

在大多数情况下,最好使用插件。认真地我要在这里兜售我的。当然还有其他的。但请检查他们是否真的避免了那些你首先想要插件的陷阱——并不是所有人都这样做。

我写过在其他地方使用插件的原因。简而言之,这里大多数答案的基础是一行

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

是糟糕的用户体验。

动画不会响应用户操作。即使用户单击、轻击或尝试滚动,它也会继续。如果动画的起点接近目标元素,则动画会非常缓慢。如果目标元素位于页面底部附近,则无法滚动到窗口顶部。然后,滚动动画在中间运动时突然停止。

为了处理这些问题(以及其他一些问题),您可以使用我的插件jQuery.scrollable

$( window ).scrollTo( targetPosition );

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

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

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

即使在html元素上设置了边框,这也能正常工作。

其他回答

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

$(函数){//可在任何地方使用的通用选择器$(“.js滚动到”).click(函数(e){//动态获取hrefvar destination=$(this).attr('href');//阻止href=“#”链接更改URL哈希(可选)e.预防违约();//动画滚动到目的地$('html,body').animate({scrollTop:$(destination).offset().top}, 500);});});<!-- 固定导航菜单示例--><ul class=“nav”><li><a href=“#section-1”class=“nav item js scroll to”>项目1</a></li><li><a href=“#section-2”class=“nav item js scroll to”>项目2</a></li><li><a href=“#section-3”class=“nav item js scroll to”>项目3</a></li></ul>

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

我设置了一个模块滚动元素npm安装滚动元素。它的工作原理如下:

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帖子的帮助下编写:

没有jquery的元素的顶部偏移量不带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 }
}

使用此解决方案,您不需要任何插件,并且除了在关闭</body>标记之前放置脚本外,不需要进行任何设置。

$("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哈希的链接(例如#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();

如果您对平滑滚动效果不太感兴趣,而只是对滚动到特定元素感兴趣,则不需要使用jQuery函数。Javascript已涵盖您的案例:

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

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

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

更新

现在可以通过滚动选项滚动动画(参见MDN)。您甚至可以控制块的位置。除了Safari,它似乎有很大的支持

$("selector").get(0).scrollIntoView({behavior: 'smooth'});