Меняем активный пункт меню при прокрутке страницы

Очень часто на одностраничниках можно встретить такую фишку, когда начинаешь прокручивать страницу, верхнее меню плавно едет за вами и в зависимости от того, какой вы сейчас раздел просматриваете, будет выделен соответствующий пункт меню (посмотрите демо).

Все это делается чтобы пользователю было легче ориентироваться на одностраничнике и чтобы он знал, где конкретно сейчас находится.

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

HTML

Для реализации идеи, мы должны создать HTML-структуру нашего плавающего меню

        <header class="sticky-header">
            <nav class="top-menu">
                <ul>
                    <li><a class="active" href="#home">Главная</a></li>
                    <li><a href="#about">О нас</a></li>
                    <li><a href="#service">Услуги</a></li>
                    <li><a href="#contact">Контакты</a></li>
                </ul>
            </nav>
        </header>

Затем создаем структуру контентной части нашего одностраничника. Она будет состоять из отдельных разделов (секций). Для каждой из этих секций мы обязательно задаем уникальный идентификатор.

Данный идентификатор должен соответствовать значению атрибута href ссылки меню, которая логически ссылается на этот раздел.

<section id="home">
Здесь любой контент...
</section>

<section id="about">
Здесь любой контент...
</section>

<section id="service">
Здесь любой контент...
</section>

<section id="contact">
Здесь любой контент...
</section>

CSS

Теперь добавить немного стилей для нашего меню.

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

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

.sticky-header {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	background: rgba(0, 0, 0, .8);
}
.top-menu ul {
	margin: 20px 0;
	text-align: center;
}
.top-menu ul li {
	list-style: none;
	display: inline-block;
	margin: 0 15px;
}
.top-menu a {
	color: #fff;
	-webkit-transition: .5s;
	-moz-transition: .5s;
	transition: .5s;
}
.top-menu a:hover,
.top-menu a.active {
	color: #e0a2a2;
}

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

jQuery

Ну и теперь немного jQuery. За основу я взял скрипт, который был представлен в этой статье. Правда определенные изменения он все же пережил.

var menu_selector = ".top-menu"; // Переменная должна содержать название класса или идентификатора, обертки нашего меню. 

function onScroll(){
	var scroll_top = $(document).scrollTop();
	$(menu_selector + " a").each(function(){
		var hash = $(this).attr("href");
		var target = $(hash);
		if (target.position().top <= scroll_top && target.position().top + target.outerHeight() > scroll_top) {
			$(menu_selector + " a.active").removeClass("active");
			$(this).addClass("active");
		} else {
			$(this).removeClass("active");
		}
	});
}

$(document).ready(function () {

	$(document).on("scroll", onScroll);

	$("a[href^=#]").click(function(e){
		e.preventDefault();

		$(document).off("scroll");
		$(menu_selector + " a.active").removeClass("active");
		$(this).addClass("active");
		var hash = $(this).attr("href");
		var target = $(hash);

		$("html, body").animate({
		    scrollTop: target.offset().top
		}, 500, function(){
			window.location.hash = hash;
			$(document).on("scroll", onScroll);
		});

	});

});

В этом коде, в принципе, ничего менять не нужно, разве только значение переменной menu_selector. Она должна содержать название класса или идентификатора, обертки нашего меню. Если ваше меню обернуто не в тег с классном .top_menu, то измените это значение.

Кстати, если вы больше любите jQuery плагины, то вместо приведенного вверху jQuery кода, вы можете подключить к странице плагин jquery.changeActiveNav.js (он есть в дополнительных материалах).

И затем просто его проинициализируйте.

$(document).ready(function(){
	$(".top-menu").changeActiveNav();
});

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

Теперь, если вы все сделал правильно, у вас должно заработать.

При прокрутке странице, как только в поле зрения посетителя появляется соответствующий раздел (секция), в нашем меню будет найдена ссылка, соответствующая этому разделу и затем к ней будет добавляться класс .active.

Так как, мы с вами для класса .active задали определенные стили в CSS, то теперь этот пункт меню будет выделяться соответствующим образом.

Если же мы просто кликнем по пункту меню, то будет сделана прокрутка к соответствующему разделу.

Понравилась статья?

Тогда оставь свой комментарий или расскажи о ней своим друзьям и коллегам.

Комментарии ВКонтакте

Добавить комментарийКомментариев (6)

Ilhom 8 марта 2016 г. в 14:32

Поздравляю вас, Александр, с днем рождения. Всего вам наилучшего!

Ответить

Дмитрий 13 января 2016 г. в 01:26

С праздником, Александр!

Ответить

Александр 11 января 2016 г. в 22:37

С Днем рождения, Александр! Всего самого доброго и светлого! И спасибо огромное за Ваши уроки! Очень нравится Ваша манера объяснения темы! Очень все подробно, неторопливо и предельно ясно! Еще раз Вас с 25-летием !

Ответить

Дима 11 января 2016 г. в 20:35

С Днём Рождения Александр! Море удачи и дачу у моря вам 🙂 По чаще радуйте нас своими супер - пупер уроками 🙂 Спасибо!

Ответить

Сергей 11 января 2016 г. в 19:49

Александр! С днем рождения! Счастья, здоровья, исполнения всех Ваших желаний. Вы один из лучших преподавателей. Ждем Ваших новых уроков.

Ответить

Алик 11 января 2016 г. в 18:01

Здравствуйте, Александр! С Днем Рождения, дорогой! Всех благ и больших успехов на ниве web-программирования!

Ответить
Наверх

Скачивание материалов доступно
только подписчикам!

Если вы подпишитесь, то сможете сразу же получить доступ ко всем материалам этого блога

Подписка бесплатная и займет у вас
не более 1 минуты

Получение доступа к материалам

Для получения доступа, заполните форму ниже. Введите свое настоящее имя и e-mail

« Вернуться назад

Проверьте свой почтовый ящик

и подтвердите подписку

После этого вы сразу же получите доступ ко всем материалам этого блога

Введите e-mail, который вы указывали при подписке

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

« Вернуться назад