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

Нужен САЙТ? Заказуй у меня - Жми сюда! Нужен хостинг или домен? Жми сюда! Хочешь создать интернет-магазин? Жми сюда! (Shopify)

Как вам известно, по нажатию на якорную ссылку нас перекидывает на ту часть страницы с которой эта ссылка связана. Сам переход происходит мгновенно и этот нюанс мы с вами поправим.

Для того чтобы реализовать плавный переход после нажатия по ссылке, нам необходимо будет написать небольшой скрипт, который отследит момент нажатия, выяснит на какой блок ссылается якорь и плавно прокрутит страницу до нужного места. Но давайте обо всем по порядку :)
 

1. Структура меню с якорными ссылками

Чтобы при нажатии по ссылке мы переходили к определенному блоку, абзацу, необходимо в атрибут href прописать имя идентификатора того блока на который мы хотим сослаться, например:
у нас есть блока <div id="main">...</div>, внутренняя ссылка на этот блок будет иметь следующий вид: <a href="#main"></a>
Таким образом все ссылки ссылаются на ID блоков.
Вот и сам код меню из демо-примера:

<nav id="menu">
	<ul>
		<li><a href="#ex1">Link #1</a></li>
		<li><a href="#ex2">Link #2</a></li>
		<li><a href="#ex3">Link #3</a></li>
		<li><a href="#ex4">Link #4</a></li>
	</ul>
</nav>

Каждая ссылка ссылается на соответствующий блок:

<div id="content">
	<section id="ex1">
		...
	</section>
	<div class="separator"></div>
	<section id="ex2">
		...
	</section>
	<div class="separator"></div>
	<section id="ex3">
		...
	</section>
	<div class="separator"></div>
	<section id="ex4">
		...
	</section>
</div>

2. Скрипт плавного перехода к нужному блоку

Итак нам нужно обработать нажатия по ссылкам в нашем меню, отменить стандартное поведение, выяснить на какой блок ссылается якорь и анимировать переход.

 
$(document).ready(function(){
	$("#menu").on("click","a", function (event) {
		//отменяем стандартную обработку нажатия по ссылке
		event.preventDefault();

		//забираем идентификатор бока с атрибута href
		var id  = $(this).attr('href'),

		//узнаем высоту от начала страницы до блока на который ссылается якорь
			top = $(id).offset().top;
		
		//анимируем переход на расстояние - top за 1500 мс
		$('body,html').animate({scrollTop: top}, 1500);
	});
});

 

Каждую строку скрипта я прокомментировал, если остались вопросы пиши в комментариях к посту - помогу ;)

Нужен САЙТ? Заказуй у меня - Жми сюда! Нужен хостинг или домен? Жми сюда! Хочешь создать интернет-магазин? Жми сюда! (Shopify)

Делясь ссылкой на пост в социальных сетях - Вы помогаете развитию блога! Спасибо ;)

(20 голосов. Рейтинг: 4,80 из 5)
Loading...Loading...

Рубрика: jQuery, Как сделать?

Комментарии (94)

| RSS комментария

  1. Guest:

    Спасибо, Дмитрий за статью!
    Есть вопрос, от новичка: куда вставить код скрипта?

    спасибо

    • Дмитрий Британ:

      Доброе утро!
      1. Вам нужно подключить библиотеку jQuery, как это сделать я описал в этом посте: Подключаем библиотеку jQuery к своему проекту
      2.1. Код скрипта можно сохранить в отдельный файл, например script.js. Если этот файл сохранен в одной папке с файлом index.html, то в теге head вам нужно прописать такую строку:
      <script type="text/javascript" src="script.js"></script>
      2.2 Если вы не хотите сохранять код скрипта в отдельный файл, вы можете добавить его в конце страницы перед закрывающимся тегом

      <script type="text/javascript">
      $(document).ready(function(){
      $("#menu").on("click","a", function (event) {
      //отменяем стандартную обработку нажатия по ссылке
      event.preventDefault();

      //забираем идентификатор бока с атрибута href
      var id = $(this).attr('href'),

      //узнаем высоту от начала страницы до блока на который ссылается якорь
      top = $(id).offset().top;

      //анимируем переход на расстояние - top за 1500 мс
      $('body,html').animate({scrollTop: top}, 1500);
      });
      });
      </script>
      </body>

      Если что-то осталось не ясным или не получилось, пишите!
      Постараюсь ответить подробнее :)

  2. Наташа:

    Спасибо:) отличное решение, сегодня пригодилось!

  3. reg:

    Спасибо большое. Все сделал, все работает. Выручили:)

  4. Добрый вечер! Сделал меню, прилипающее к верху страницы при прокрутке (не из Ваших уроков, а нашел другой скрипт раньше), затем по Вашему уроку сделал плавный переход к якорям. И тут возникла проблема — при переходе к якорной ссылки определенного абзаца — мое меню (т.к. он фиксировано) перекрывает часть контента своей высотой. Как вариант, мне пришла в голову идея сделать при прокрутке к якорю отступ от верхней части окна браузера до якоря на высоту меню (т.е. 60 пикс.) Но в скриптах пока не силен, поэтому прошу совета, как это можно реализовать. Сайт написал. Подключены две кнопки меню (О расчетном центре, Услуги). Очень прошу помощи. Заранее благодарю.

  5. Привет!
    Можно ли использовать этот скрипт для сайта на Joomla?

  6. Анатолий:

    Сделал все как в демо. Но плавный переход не работает почему-то.
    Сайт сделал на Bootstrap. Подскажите пожалуйста почему не срабатывает?

  7. Здравствуйте, есть сайт на котором много товаров и если опуститься к нижнему товару и нажать на ссылку пользователь остается внизу страницы (тоесть нужного товара не видно). Можно ли сделать так что бы его бросало в нужную часть сайта (к якорю). Заранее спасибо.

    • Дмитрий Британ:

      Не понял вашу ситуацию. Может дадите ссылку, где можно посмотреть )

  8. Александр:

    Здравствуйте. Подскажите, а как сделать плавный переход к якорю, который расположен на другой странице сайта, а не на этой же?
    Спасибо.

  9. Здравствуйте. Добавил данный скролл для другого меню, но он не работает, а именно идет конфликт на «a href». Кода в скрипте убираю «a» то она просто переходит, без плавного скролла. Когда оставляю все как в примере то он вообще не переходит по ссылкам.

    • Дмитрий Британ:

      Здравствуйте. Возможно у вас нет идентификаторов с тем названием которое прописано в атрибуте href для ссылки?
      Идеальный вариант чтобы вы дали мне ссылку на ваш пример или часть html кода :)

  10. Данил:

    Здравствуйте, ваш скрипт отлично работает, но у меня возник вопрос, а почему когда подключаешь jQuery из файлика все работает, а если с гугла, то скрипт не работает?
    Заранее спасибо ;)

    • Данил:

      А еще хотел бы дополнить тем, что с версией jquery-1.11.3.min тоже не работает? =( Что я делаю не так?

      • Дмитрий Британ:

        Сложно сказать …
        Нужно смотреть ваш пример и что выдает консоль …
        Посмотрите мой код на jsfiddle ( http://jsfiddle.net/webcomplex/43ry9bft/ ) и выложите свой вариант, посмотрим :)

        • Данил:

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

    • Дмитрий Британ:

      Здравствуйте, Данил!
      Укажите, пожалуйста, путь к гугл библиотеке jQuery, чтобы я мог проверить :)

  11. Игорь:

    Подскажите пожалуйста, как сделать, что б после перехода на якорь в адресной строке указывался к нему путь site.com/#ex1?

  12. Степан:

    У меня все работает в меню, но у меня на сайте есть еще и стрелки, которые дают переход к следующему якору. Как можно сделать это в скрипте? Заранее спасибо

    • Дмитрий Британ:

      Здравствуйте, дайте ссылку на ваш сайт или выложите код на https://jsfiddle.net
      Сложно что-то сказать не видя код перед глазами :)

      • Степан:

        https://jsfiddle.net/7qr0qL87/

        html — вот так выглядит стрелка вниз
        css — это ее оформление

        цель сделать js чтобы при нажатии на эту кнопку, body двигалась вниз на якорь

        • Дмитрий Британ:

          Просто продублируйте основную функцию из примера для вашей кнопки

  13. Пыщ-пыщ:

    Спасибо за скрипт! Очень помогло) Нужен он был не для красоты, а для того чтобы избавиться от неверного скролла до якоря (потому что меню наверху зафиксировано). Выставил в скрипте top-70 как писал парень выше и вуаля!
    Но есть одно «но». Скрипт не работает с id с пробелами. Есть список со ссылками на якоря, некоторые работают по скрипту, некоторые ведут себя стандартно. Как быть?) Id генерятся с подзаголовков статьи и делать с ними что-то на начальном уровне сложновато.
    Есть варианты?)

    • Пыщ-пыщ:

      Сам себе и отвечу) Поиск сделал не по id а по name. Получилось так:

      $(«#menu»).on(«click», «a», function (event) {
      var id = $(this).attr(‘href’);
      id = id.substr(1, id.length); //Первый символ — решетка не нужен.
      var name = («#article a[name='» + id + «‘]»); //нашел ту самую ссылку, с атрибутом name равным искомому. Дальше все стандартно
      var top = $(name).offset().top;
      $(‘body,html’).animate({scrollTop: top — 70}, 1000);
      });

    • Дмитрий Британ:

      Такая генерация id не верна, т.е. по сути раз у вас пробелы в гназвании, то это воспринимается как несколько идентификаторов для одного элемента, а это не верный подход, желательно исправить, например заменив пробелы на тире.

      • Пыщ-пыщ:

        Я обошелся без id, в конце концов, код я написал. То, что айди не корректен, я согласен, его генерит редактор CKEditor и не хотелось что-то делать с этим.

  14. Эй дарагой, спасиба бальщой, не только себе узнал как скрипт сайт ставить, но ещё и jQuэrry скачаль, раньше не зналь, что он за зверь такой!

    Да продлит Аллах твои дни, вах спасиба!

    Подскажи же, дарагой, а как сделать, щьтоб нижний ссылька «иди наверх» тоже плавно крутиль? Я и так пробоваль — и сяк пробоваль — вниз крутит вяло, а навэрх сразу шустро в один клац, шайтан!

    Эй памаги да!

  15. Михаил:

    Доброго дня!
    Спасибо за скрипт, рулит!!!
    Есть вопрос следующего характера, как его можно модифицировать (и можно ли?) если у меня на странице реализован переход по якорям в зависимости от значения выбранного в теге select?

    То есть «стандартный» вариант перехода реализован следующим образом:
    select onChange=»document.location.href=’#’+this.value»
    Есть ли возможность в этом случае переход сделать плавным?
    Заранее признателен.

    • Дмитрий Британ:

      Я так понял скрипт прописан непосредственно в разметке, вам его нужно вынести в отдельный файлик и прописать обработку для блока select, из него вытягиваете айдишник, а дальше как в статье обрабатываете переход

      • Михаил:

        Скрипт в отдельном файле, но не в этом дело: я с jQuery «на «вы» и с глубоким поклоном» — понял как обработать переход, но уме не приложу как обработать select и вытянуть из него id… (((

      • Михаил:

        id-шник вытянул, но не могу получить его отступ от начала страницы…

        $(document).ready(function() {
        $(«select»).change(function(){
        var id = $(this).val();
        alert(id); // выдает правильный id
        alert($(id)); // выдает object Object (я так понимаю ссылка на объект)
        alert($(id).offset().top); // не выдает ничего… (((
        });
        });

        Хелп, плз, в чем может быть ошибка?

      • Михаил:

        Продолжая традицию ответов «самому себе» конструкция заработала в следующем виде:
        $(document).ready(function() {
        $(«select»).change(function(){
        var id = $(this).val(),
        top = $(«#»+id).offset().top;
        $(‘body,html’).animate({scrollTop: top}, 1000);
        });
        });

        Есть подозрение что это «сильно криво», но работает… =)

        • Дмитрий Британ:

          У меня совсем мало времени сейчас на блог остается, по-этому редко отвечаю, но в этом есть и свои плюсы у вас было время самостоятельно разобраться, что намного полезнее чем подсказка. Рад за вас! :)

          • Михаил:

            Спасибо за блог, за то, что Вы хоть и редко, но отвечаете!
            Искренне надеюсь что «совсем мало времени» компенсируется «очень много денег», ну или других «приятностей»… ;)

  16. Дмитрий:

    Данный скрипт не работает в мозиле. Как его можно адаптировать?

  17. Амстердам:

    Да, «отлично», отменили стандартную обработку ссылки — получили ошибку при клике по стандартной ссылке, если такая есть в меню, а она есть. Как исправить этот неприятный момент?

  18. Yuki:

    Здравствуйте, такой вопрос (ранее поднимался в теме, но не было ответа):
    сайт на Bootstap, ранее были различные реализации плавного скролла, но в Opera, Chrom, Яндекс-браузере не работает переход по якорям вообще. Может идёт конфликт в bootstrap.js — файле?

  19. Сергей:

    Здравствуйте!
    Если бы у меня ссылки были вида ссылка, то плавный переход работал бы.
    А у меня на сайте ссылки в меню генерируются только таким образом:
    ссылка
    ссылка
    и никак иначе. Потому что в коде есть тег , он нужен для корректной работы CMS. Но в таком виде плавный переход по этим ссылкам не работает.
    Подскажите, пожалуйста, как доработать скрипт для моей ситуации.
    Спасибо.

  20. Людмила:

    Синяя кнопка не работает!!(

  21. Vektor:

    Здравствуйте.Как и всем помог ваш скрипт,юзал уже раза три все было ок.
    Но сейчас возникла проблема.При прокрутке страницы тупит на пол пути.и потом резко к якорю.

  22. Спасибо!
    Просто и эффективно.

  23. Анна:

    Здравствуйте!У меня фиксированное верхнее меню, мне нужно, что бы при нажатии и при скролле страницы ссылка меняла свой фоновый цвет находясь возле соответствующего блока. Подскажите пожалуйста как это реализовать? :) Вот пример http://dorokhova.com/index_en.html#layout

  24. Vlad:

    Классный скрипт. Спасибо!

  25. Вася:

    Сделайте демо-примеры на отдельной странице как было раньше, а не как щас — в модальном окне. Сейчас исходный код демо в перемешку с общими стилями.

    • Дмитрий Британ:

      Жмем, правой кнопкой мышки над кнопкой «Демо», в контекстном меню выбираем — «Открыть ссылку в новой вкладке» — профит ;)

  26. Проблема такая: есть цикл с выводом ссылок, в зависимости от опции срабатывает несколько раз:
    <a href="» class=»link»>

    добавляю к нему ссылку на меню :

    <a href="» class=»link»>

    В таком случае анимация срабатывает только для первой ссылки.
    Вопрос как ето исправить?)

    • Дмитрий Британ:

      Здравствуйте, мне на код в целом посмотреть, может ссылка на сайт или на jsfiddle.net залейте

  27. Соня:

    Дмитрий подскажите пожалуйста, как можно реализовать плавный скролл не через id, а через class?

    Благодарю за скорый ответ :)

    • Дмитрий Британ:

      Скорого ответа не получилось, но реализовать ваш вариант очень просто.
      Достаточно прописать класс блоков в атрибут data-target для ссылок и просто вытягивать значение не с href а из data-target.

  28. Евгений:

    Здравствуйте!

    Как сделать обратную откатку по кнопке «Вернуться к оглавлению»?

  29. maxim:

    Доброго времени суток. отличная статья. Помогло! У меня вопрос. как сделать кнопку «далее». например в лэндинг странице(обычно посередине, снизу экрана, стрелочка «вниз»). Скрипт сработал для прокрутки к каждому id в меню. но не работает для отдельной ссылки. То есть ссылка рабочая но скрипт не выходит вкрутить. Может ли кто то разобрать на пальцах? Спасибо.

    • Дмитрий Британ:

      Тут нужна ссылка на вашу страницу тогда смогу подсказать )

      • Александр:

        Я бы тоже не отказался от решения. Было бы неплохо написать в статье, как обращаться к конкретному элементу, а не всем ссылкам меню. Работает сейчас, если вместо #меню написать название блока, внутри которого ссылка, а вот как на ссылку отдельно направить скрпт, что-то не пойму.

        • Александр:

          Разобрался, убрать а в первой строчке $(«.block1_link»).on(«click», function (event) {
          Спасибо за статью.

  30. Андрей:

    Скрипт говно, переходы делает но заблокировал переходы по остальным ссылкам в блоке #menu

    • Дмитрий Британ:

      Значит нужно немного подредактировать скрипт для вашего случая

  31. Mixa:

    Доброго времени суток, а как сделать что бы не по клику а допустим переход был сформирован автоматическим перенаправлением?

  32. Спасибо, для частного случая сгодился без правок и допиливаний.

  33. Спасибо автору ! Очень сильно люблю библиотеку Jquery за ее простоту и понятность !

  34. Евгений:

    Не работает скролл, можете взглянуть на код?
    https://jsfiddle.net/v8dmmmpv/

  35. Евгений:

    Еще вопрос, не по теме, как сделать так, чтобы при открытии Modal(окна), оно закрывало(затемняло) навигационную панель

  36. Виктор:

    Спасибо бро, очень помог.

  37. отличная статья, очень помогла. Спасибо вам большое.

  38. Павел:

    Скажите пожалуйста а как на Joomla реализовать ?

Оставьте свой комментарий