Плавная навигация на странице

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

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

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

В левой колонке будет расположен контент, содержащий заголовки с идентификатором и текст (возьмем 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. Abdukadir:

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

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

  3. Алиса:

    Спасибо!

  4. 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') класс вашего меню и класс фиксированного меню

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

  6. Роман:

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

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

  8. JAH:

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

  9. Юлия:

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

  10. JAH:

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

  11. Julia:

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

  12. пшк:

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

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

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

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

  14. Hovo:

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

  15. JAH:

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

  16. Рафаэль:

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

  17. JAH:

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

  18. JAH:

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

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

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

  20. Рафаэль:

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

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

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

  21. Алексей:

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

  22. JAH:

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

  23. IntuitQ:

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

  24. IntuitQ:

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

  25. Илья:

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

    Благодарю!

  26. JAH:

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

  27. Евгений:

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

  28. JAH:

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

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

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

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

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

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

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

  30. Евгений:

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

  31. JAH:

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

    $('a[href^="#"]:not(#slider a)').bind('click.smoothscroll'.........
    
  32. 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

  33. Евгений:

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

  34. JAH:

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

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

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