Я уже писал о том как сделать плавную прокрутку к началу страницы при клике на ссылку «наверх». В этом мини уроке я расскажу как сделать плавную навигацию по странице. Решение я буду демонстрировать на примере содержания статьи, но Вы легко сможете его применить и для создания навигационного меню, и еще для того на что у Вас хватит фантазии (моя на содержании статьи и меню закончилась)

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

Создаем двух колоночный макет

В левой колонке будет расположен контент, содержащий заголовки с идентификатором и текст (возьмем Lorem Ipsum).  А в правой колонке будет содержание его сделаем с помощью ненумерованного списка со ссылками. В ссылках будет якорь к заголовками с левой колонки.

<!Doctype HTML>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
	<title>Плавная навигация на странице | Howtomake</title>
</head>

<body>

<div id="main">
	<h2 id="one">One</h2>
	<p>Тут текст Lorem Ipsum</p>
	<h2 id="two">Two</h2>
	<p>Тут текст Lorem Ipsum.</p>
	<h2 id="three">Three</h2>
	<p>Тут текст Lorem Ipsum</p>
	<h2 id="four">Four</h2>
	<p>Тут текст Lorem Ipsum</p>
	<h2 id="five">Five</h2>
	<p>Тут текст Lorem Ipsum</p>
	<h2 id="six">Six</h2>
	<p>Тут текст Lorem Ipsum</p>
</div>

<aside>
	<ul>
		<li><a href="#one">One</a></li>
		<li><a href="#two">Two</a></li>
		<li><a href="#three">Three</a></li>
		<li><a href="#four">Four</a></li>
		<li><a href="#five">Five</a></li>
		<li><a href="#six">Six</a></li>
	</ul>
</aside>

</body>
</html>

Итак макет страницы готов. В принципе для того чтобы осуществлялась навигация по странице этого достаточно, но не хочется, чтобы были резкие скачки к нужному месту на странице, больше хочется плавных переходов.

Исходя из наших желаний перед закрывающимся тегом </body> подключаем библиотеку jQuery с Google API:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

И займемся написанием скрипта, который будет анимировать переходы по странице.

Пишем скрипт

Если Вы не хотите использовать фиксированное содержание справа, то к каждому заголовку на странице, средствами jQuery можно добавить ссылку «наверх», которая будет возвращать к началу статьи и содержанию (я ее добавлю сразу):

<script type="text/javascript">
$(document).ready(function(){

	// = Добавляем ссылку наверх к заголовку
	$('h2').append('<a href="#header">top</a>');

	// = Вешаем событие прокрутки к нужному месту
	//	 на все ссылки якорь которых начинается на #
	$('a[href^="#"]').bind('click.smoothscroll',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;
		});
	});

});
</script>

Суть скрипта очень простая, на все ссылки у которых якорь (тег href) начинается с диеза (#) вешается событие, которое рассчитывает расстояние (высоту) до элемента с идентификатором якоря и далее при клике с помощью методов animate() и scroll() плавно перемещает выбранный контент вверх (вниз).

Примечание: * скрипт нужно поместить после вызова библиотеки jQuery.

Осталось только написать стили, я пишу свои (по минимуму), а Вы измените в соответствии с Вашим шаблоном: цвет, шрифт, местоположение и т.д.

Добавим стилей CSS

/* = Общие стили */
body {
	padding: 0 4em;
	margin: 0;
	font: 14px/1.8 Helvetica;
	color: #444;
}
a {
	text-decoration: none;
}

/* = Стили для контента */
#main {
	width: 75%;
}
h2 {
	font-size: 1.8em;
	border-bottom: 1px solid #444;
	position: relative;
}

/* = Стили для ссылки наверх */
h2 a {
	position: absolute;
	bottom: 0;
	right: 0;
	padding: 0 10px;
	font-size: 11px;
	color: #fff;
	background: #444;
	display: block;
}

/* = Стили для содержания */
aside {
	display: block;
	width: 20%;
	position: fixed;
	left: 78%;
	top: 170px;
}
li {
	list-style: square;
	color: #006600;
}
li a {
	font: bold italic 16px Helvetica;
	color: #006600;
}
li a:hover {
	color: #990000;
}

Заключение

Раньше, для достижения этого эффекта я пользовался плагином scrollTo.js, но веб-дизайн это живой организм, растущий и вечно развивающийся, поэтому целесообразно дописать 10 строк кода, вместо использования плагина. И между прочим если Вам нужен шорткод для вывода содержания статьи WordPress, то Кама постарался написать его, использовать шорткод удобно для больших статей.

Добавить комментарий:


Комментарии
  1. Евгений

    у меня сайт на wordpress, поставил код содержания от Кама. работает.
    поставил код плавной прокрутку — работает, но перестает работать слайдер. Не прокручивает картинки. Подскажите как исправить?

  2. JAH

    Евгений, скорей всего у Вашего слайдера булеты (или ссылки «вперед-назад») в теге href содержат знак # попробуйте заменить его на

    href="javascript: void(0)"
  3. Евгений

    в моем шаблоне нельзя вписывать скрипт прямо в тему. конфликтуют скрипты.
    нужно через wp_enqueue_script…
    подскажите как можно сделать?

  4. JAH

    Евгений, попробуйте подключить так
    только вынесите код прокрутки в отдельный файл scrolll.js

    function htm_add_jquery() {
        /** REGISTER jquery.js **/
        wp_deregister_script('jquery');
        wp_register_script('jquery', get_bloginfo('template_directory') . '/js/jquery-1.7.2.min.js', false, '1.7.2');
    	wp_enqueue_script('jquery');
    
        /** REGISTER scrolll.js **/
        wp_register_script( 'scrolll', get_bloginfo('template_directory') . '/js/scrolll.js', false, '1' );
        wp_enqueue_script( 'scrolll' );
    }
    add_action( 'init', 'htm_add_jquery' );
    

    Этот код нужно вставить в файл functions.php

  5. JAH

    Евгений, и напишите плз id контейнера в котором слайдер со стрелками(или булетами) находится, можно написать тогда скрипт в виде исключения:

    $('a[href^="#"]:not(#slider a)').bind('click.smoothscroll'.........
    
  6. Евгений

    большое спасибо!!
    так все работает ) и слайдер тоже

  7. Евгений

    еще со стилями нужен совет.

    /* = Стили для ссылки наверх */
    h2 a {
    	position: absolute;
    	bottom: 0;
    	right: 0;
    	padding: 0 10px;
    	font-size: 11px;
    	color: #fff;
    	background: #444;
    	display: block;
    

    эта часть у меня меняет весь заголовок, а не только ссылку top

  8. JAH

    ну тут все просто со стилями, я просто не добавлял в h2 ссылку на пост (или любую другую)
    чтобы их различать просто добавь класс ссылке наверх:

    // = Добавляем ссылку наверх к заголовку
    $('h2').append('<a href="#header" class="link-top" rel="nofollow">top</a>');

    и чуть стили по другому будут:

    /* = Стили для ссылки наверх */
    h2 .link-top {...
  9. Евгений

    вот теперь точно все. Красота. Огромное спасибо )
    угостил бы пивом… или колой… если б жили рядом ))

  10. JAH

    хорошо что все получилось)

  11. Илья

    Привет! Спасибо за статью! Но не мог бы ты помочь с небольшим улучшением… Нужно что бы страница прокручивалась вниз (как сейчас),но после попадания на нужное место немного поднималась наверх? Буквально на 40px, а то у меня фиксированное меню и оно сверху кладется на див 🙂

    Благодарю!

  12. IntuitQ

    Уважаемый JAH!
    Очень понравилась ваша плавная прокрутка, но не могу при этом использовать табы. Дело в том, что в теге href в табах содержиттся # и страница при загрузке сразу спускается к ним. Двойной клик по закладке таб заставляет его перемещаться вверх (по логике с своему содержимому). Всё остальное функционирует исправно.
    Всю ночь бьюсь…исключение не работает, замена $ тоже.
    Подскажите, как решить проблему? Очень надеюсь на ответ.

  13. IntuitQ

    …добавил к контейнеру исключения «а» и всё работает)
    спасибо!

  14. JAH

    IntuitQ, рад помочь!

  15. Алексей

    Спасибо, интересный скрипт.

  16. Рафаэль

    Jah добрый день. Установи ваш скрипт все замечательно но почему-то не по всем пунктам меню —

    Обо мне
    Портфолио
    Хостинг
    Контакты

    Работает все кроме «Портфолио»
    В консоле пишет Uncaught TypeError: Cannot read property ‘top’ of null
    В чем может быть проблема?

  17. Hovo

    Уважаемый JAH!
    У меня шаблон Attitude и нужно сделать такой эффект только для одной страницы. Как мне это сделать Очень прошу помочь! Заранее благодарен

  18. JAH

    Hovo, у вас для body есть классы (page или single и page-id или single-id) в своем script.js вы можете указать

    if($('body').hasCLass('page-id')){
     /* тут выполняем скрипт */
    }
  19. JAH

    Рафаэль, эта ошибка означает, что скрипт не может посчитать отступ сверху к блоку портфолио, скорей всего hash-тег не совпадает с id’шником блока портфолио

  20. Рафаэль

    Точно id-шник не совпадал. Спаибо за помощь. Надеюсь в скором времени ваш скрипт будет подсвечивать навигационные элементы в соответствии с местом нахождения пользователя.

  21. JAH

    Рафаэль, да с подсветкой у меня уже есть написанный скрипт, нету времени его никак выложить 🙁

  22. Hovo

    Спасибо JAH! Попробую

  23. Vitaliy

    Спасибо огромное, под каждый пункт было лень писать, а здесь все и сразу.

  24. пшк

    если перейти напрямую по ссылке http://www.howtomake.com.ua/demo/how-to-make-plavnaya-navigaciya-na-stranice#five

    то плавный скрол не сработает

    как сделать что бы срабатывал ?

  25. Julia

    У меня не работает пишет ошибку Uncaught TypeError: Cannot read property ‘top’ of null

  26. JAH

    Julia, эта ошибка означает что Вы рассчитываете высоту до элемента которого нет на странице, перепроверьте хэш-теги ссылок и айдишники блоков к которым должен срабатывать скролл

  27. Юлия

    Все равно не работает пишет TypeError: $target.offset(…) is null

  28. JAH

    Юлия, это ошибка указывает на то что айдишник блока к которому нужно прокрутить не совпадает с атрибутом href ссылки по которой кликнули

  29. Николай

    Спасибо, помогла, с меня клик, сами знаете где:)

  30. Роман

    Спасибо большое, выручили как раз то что искал!!!

  31. Отличная работа — большое спасибо.
    Подскажите, пожалуйста:
    1. по первом варианту — все работает, но как можно сделать, чтобы при нажатии по содержимому перекидывало не строго на h2 или h3, а несколько выше, ибо у меня выходит всплывающее верхнее меню и перекрывает часть подзаголовка и строку «вверх»?

  32. JAH

    Александр, нужно в этой строке

    'scrollTop': $target.offset().top
    

    отминусовать высоту вашего меню может даже чуть больше

    'scrollTop': $target.offset().top - 100
    

    лучше конечно через переменную типа

    var minus = $('.nav').hasClass('fixed') ? 100 : 0;
    'scrollTop': $target.offset().top - minus
    

    вместо $('.nav').hasClass('fixed') класс вашего меню и класс фиксированного меню

  33. Алиса

    Спасибо!

  34. Сергей

    Добрый день, все отлично работает, реализовал на одном из наших проектов massive.ua. Вопрос, необходимо, чтоб при клике на нужный уровень ( например 3 ) этот блок подсвечивался, менял стиль, а также подсвечивался, когда ползователь находится на одном из якорей.
    То есть клиент выдит на каком ровне он находится. Как это можно реализовать?

  35. Abdukadir

    Здравствуйте!
    У меня такой вопрос, когда нажали и перешли по одной из ссылок и если нажать назад в браузере то возвращаетесь обратно!
    а мне надо чтоб не возвращалось ! как это сделать?