Плавная прокрутка при нажатии на ссылку

310

У меня есть несколько гиперссылок на моей странице. FAQ, который пользователи будут читать, когда они посещают раздел справки.

Используя привязки привязки, я могу сделать страницу прокруткой к якорю и вести там пользователей.

Есть ли способ сделать эту прокрутку гладкой?

Но обратите внимание, что он использует пользовательскую библиотеку JavaScript. Может быть, jQuery предлагает такие вещи, как этот, испеченный в?

  • 0
    Можете ли вы рассмотреть лучший ответ, может быть? Простое однострочное решение CSS трудно найти среди всех громоздких предложений jquery: stackoverflow.com/a/51588820/1422553
Теги:
hyperlink
scroll
anchor

19 ответов

778
Лучший ответ
$(document).on('click', 'a[href^="#"]', function (event) {
    event.preventDefault();

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top
    }, 500);
});

И вот скрипка: http://jsfiddle.net/9SDLw/


Если ваш целевой элемент не имеет идентификатора, и вы связываетесь с ним его name, используйте это:

$('a[href^="#"]').click(function () {
    $('html, body').animate({
        scrollTop: $('[name="' + $.attr(this, 'href').substr(1) + '"]').offset().top
    }, 500);

    return false;
});

Для повышения производительности вам следует кэшировать селектор $('html, body'), чтобы он не запускался каждый раз, когда нажимается якорь:

var $root = $('html, body');

$('a[href^="#"]').click(function () {
    $root.animate({
        scrollTop: $( $.attr(this, 'href') ).offset().top
    }, 500);

    return false;
});

Если вы хотите, чтобы URL-адрес был обновлен, выполните его в обратном вызове animate:

var $root = $('html, body');

$('a[href^="#"]').click(function() {
    var href = $.attr(this, 'href');

    $root.animate({
        scrollTop: $(href).offset().top
    }, 500, function () {
        window.location.hash = href;
    });

    return false;
});
  • 9
    Кажется, это удаляет #extension из URL, нарушая функцию back. Это можно обойти?
  • 1
    @Fletch - я добавил решение в ответ.
Показать ещё 25 комментариев
140

Правильный синтаксис:

//Smooth scrolling with links
$('a[href*=\\#]').on('click', function(event){     
    event.preventDefault();
    $('html,body').animate({scrollTop:$(this.hash).offset().top}, 500);
});

// Smooth scrolling when the document is loaded and ready
$(document).ready(function(){
  $('html,body').animate({scrollTop:$(location.hash).offset().‌​top}, 500);
});

Упрощение: DRY

function smoothScrollingTo(target){
  $('html,body').animate({scrollTop:$(target).offset().‌​top}, 500);
}
$('a[href*=\\#]').on('click', function(event){     
    event.preventDefault();
    smoothScrollingTo(this.hash);
});
$(document).ready(function(){
  smoothScrollingTo(location.hash);
});

Объяснение href*=\\#:

  • * означает, что он соответствует тому, что содержит # char. Таким образом, соответствуют только привязки. Подробнее о значении этого см. Здесь .
  • \\ заключается в том, что # является специальным char в селекторе css, поэтому нам нужно его избежать.
  • 8
    мне пришлось изменить $('a') на $('a[href*=#]') чтобы обслуживать только URL-адреса привязок
  • 1
    хорошо, почему это не работает? $ ("# menu a [href = '# top']
Показать ещё 9 комментариев
18
$('a[href*=#]').click(function(event){
    $('html, body').animate({
        scrollTop: $( $.attr(this, 'href') ).offset().top
    }, 500);
    event.preventDefault();
});

это сработало идеально для меня

  • 1
    "Event.preventDefault ();" может заменить "вернуть ложь";
5

Я предлагаю вам сделать этот общий код:

$('a[href^="#"]').click(function(){

var the_id = $(this).attr("href");

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

return false;});

Здесь вы можете увидеть очень хорошую статью: jquery-effet-smooth-scroll-defilement-fluide

  • 8
    Это не универсально, это jQuery.
4
$(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });
});

Официальные: http://css-tricks.com/snippets/jquery/smooth-scrolling/

  • 1
    кажется, это работает только для ссылок на внутренние страницы, но ссылки на другие страницы не работают, например, website.com/about-us/#who-we-are
3

Использование JQuery:

$('a[href*=#]').click(function(){
  $('html, body').animate({
    scrollTop: $( $.attr(this, 'href') ).offset().top
  }, 500);
  return false;
});
2

Добавление этого:

function () {
    window.location.hash = href;
}

каким-то образом аннулирует вертикальное смещение

top - 72

в Firefox и IE, но не в Chrome. В принципе, страница прокручивается плавно до точки, в которой она должна останавливаться на основе смещения, но затем переходит к месту, где страница будет идти без смещения.

Он добавляет хэш в конец URL-адреса, но отжатие назад не возвращает вас к вершине, оно просто удаляет хэш из URL-адреса и оставляет окно просмотра, где оно сидит.

Вот полный js, который я использую:

var $root = $('html, body');
$('a').click(function() {
    var href = $.attr(this, 'href');
    $root.animate({
        scrollTop: $(href).offset().top - 120
    }, 500, function () {
        window.location.hash = href;
    });
    return false;
});
1

HTML

<a href="#target" class="smooth-scroll">
    Link
</a>
<div id="target"></div>

или с абсолютным полным URL

<a href="https://somewebsite.com/#target" class="smooth-scroll">
    Link
</a>
<div id="target"></div>

JQuery

$j(function() {
    $j('a.smooth-scroll').click(function() {
        if (
                window.location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '')
            &&  window.location.hostname == this.hostname
        ) {
            var target = $j(this.hash);
            target = target.length ? target : $j('[name=' + this.hash.slice(1) + ']');
            if (target.length) {
                $j('html,body').animate({
                    scrollTop: target.offset().top - 70
                }, 1000);
                return false;
            }
        }
    });
});
1

Приведенный ответ работает, но отключает исходящие ссылки. Ниже версии с добавленной бонусной непринужденностью (качели) и уважает исходящие ссылки.

$(document).ready(function () {
    $('a[href^="#"]').on('click', function (e) {
        e.preventDefault();

        var target = this.hash;
        var $target = $(target);

        $('html, body').stop().animate({
            'scrollTop': $target.offset().top
        }, 900, 'swing', function () {
            window.location.hash = target;
        });
    });
});
  • 0
    +1 для stop() однако крошка URL не работает должным образом: кнопка Назад не возвращает назад, это потому, что когда крошка установлена в URL после завершения анимации. Лучше без крошки в URL, например, так делает airbnb.
1

Это позволит легко разрешить jQuery распознавать хеш-объект и знать, когда и где остановиться.

$('a[href*="#"]').click(function(e) {
    e.preventDefault();
    var target = this.hash;
    $target = $(target);

    $('html, body').stop().animate({
        'scrollTop': $target.offset().top
    }, 900, 'swing', function () {
        window.location.hash = target;
    });
});
1

Это решение также будет работать для следующих URL-адресов, не нарушая привязки ссылок на разные страницы.

http://www.example.com/dir/index.html
http://www.example.com/dir/index.html#anchor

./index.html
./index.html#anchor

и др.

var $root = $('html, body');
$('a').on('click', function(event){
    var hash = this.hash;
    // Is the anchor on the same page?
    if (hash && this.href.slice(0, -hash.length-1) == location.href.slice(0, -location.hash.length-1)) {
        $root.animate({
            scrollTop: $(hash).offset().top
        }, 'normal', function() {
            location.hash = hash;
        });
        return false;
    }
});

Я еще не тестировал это во всех браузерах.

0

В наши дни современные браузеры немного быстрее. Может работать setInterval. Эта функция хорошо работает в Chrome и Firefox в эти дни. (Немного медленная в сафари, не беспокоила IE)

function smoothScroll(event) {
    if (event.target.hash !== '') { //Check if tag is an anchor
        event.preventDefault()
        const hash = event.target.hash.replace("#", "")
        const link = document.getElementsByName(hash) 
        //Find the where you want to scroll
        const position = link[0].getBoundingClientRect().y 
        let top = 0

        let smooth = setInterval(() => {
            let leftover = position - top
            if (top === position) {
                clearInterval(smooth)
            }

            else if(position > top && leftover < 10) {
                top += leftover
                window.scrollTo(0, top)
            }

            else if(position > (top - 10)) {
                top += 10
                window.scrollTo(0, top)
            }

        }, 6)//6 milliseconds is the faster chrome runs setInterval
    }
}
0

Проверенный и проверенный код

<script>
jQuery(document).ready(function(){
// Add smooth scrolling to all links
jQuery("a").on('click', function(event) {

// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
  // Prevent default anchor click behavior
  event.preventDefault();

  // Store hash
  var hash = this.hash;

  // Using jQuery animate() method to add smooth page scroll
  // The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
  jQuery('html, body').animate({
    scrollTop: jQuery(hash).offset().top
  }, 800, function(){

    // Add hash (#) to URL when done scrolling (default click behavior)
    window.location.hash = hash;
  });
} // End if
});
});
</script>
0
$("a").on("click", function(event){
    //check the value of this.hash
    if(this.hash !== ""){
        event.preventDefault();

        $("html, body").animate({scrollTop:$(this.hash).offset().top}, 500);

        //add hash to the current scroll position
        window.location.hash = this.hash;

    }



});
0

Никогда не забывайте, что функция offset() позволяет документировать позицию вашего элемента. Поэтому, когда вам нужно прокрутить элемент по отношению к его родительскому, вы должны использовать это:

    $('.a-parent-div').find('a').click(function(event){
        event.preventDefault();
        $('.scroll-div').animate({
     scrollTop: $( $.attr(this, 'href') ).position().top + $('.scroll-div').scrollTop()
     }, 500);       
  });

Ключевым моментом является получение scrollTop прокрутки-div и добавление его в scrollTop. Если вы не будете делать эту функцию position(), вы всегда будете иметь разные значения позиции.

0

Если у вас есть простая кнопка на странице, чтобы прокрутить вниз до div и хотите, чтобы кнопка назад работала, прыгая вверх, просто добавьте этот код:

$(window).on('hashchange', function(event) {
    if (event.target.location.hash=="") {
        window.scrollTo(0,0);
    }
});

Это можно расширить, чтобы перейти к другим divs, прочитав хэш-значение и прокрутив, как говорит Джозеф Сильберс.

0

Вот решение, которое я реализовал для нескольких ссылок и якорей, для плавного прокрутки:

http://www.adriantomic.se/development/jquery-localscroll-tutorial/ если у вас есть ваши навигационные ссылки, настроенные в навигационном div и объявленные с помощью этой структуры:

<a href = "#destinationA">

и соответствующих назначений тегов привязки как таковые:

<a id = "destinationA">

Затем просто загрузите это в начало документа:

    <!-- Load jQuery -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>

<!-- Load ScrollTo -->
<script src="http://flesler-plugins.googlecode.com/files/jquery.scrollTo-1.4.2-min.js"></script>

<!-- Load LocalScroll -->
<script src="http://flesler-plugins.googlecode.com/files/jquery.localscroll-1.2.7-min.js"></script>

<script type = "text/javascript">
 $(document).ready(function()
    {
        // Scroll the whole document
        $('#menuBox').localScroll({
           target:'#content'
        });
    });
</script>

Благодаря @Adriantomic

0

Я сделал это для обоих "/xxxxx # asdf" и "#asdf" href anchors

$("a[href*=#]").on('click', function(event){
    var href = $(this).attr("href");
    if ( /(#.*)/.test(href) ){
      var hash = href.match(/(#.*)/)[0];
      var path = href.match(/([^#]*)/)[0];

      if (window.location.pathname == path || path.length == 0){
        event.preventDefault();
        $('html,body').animate({scrollTop:$(this.hash).offset().top}, 1000);
        window.location.hash = hash;
      }
    }
});
-7

jQuery - лучший!

$('a').click(function(){
    //code here
});

Ещё вопросы

Сообщество Overcoder
Наверх
Меню