Фиксированное горизонтальное меню с активными пунктами

Пример горизонтального меню для лэндингов, в котором реализовано:

  • При прокрутке меню фиксируется.
  • Выделение активного пункта меню по текущему блоку.
  • По клику на меню происходит плавная прокрутка до якоря.
  • Адаптация позиции меню при изменении ширины окна браузера.
<div class="wrp">
	<div class="header">Шапка сайта</div>
</div>

<div class="header-menu-wrp">
	<div class="wrp">
		<div class="header-menu">
			<ul>
				<li><a href="#block-1">Блок 1</a></li>
				<li><a href="#block-2">Блок 2</a></li>
				<li><a href="#block-3">Блок 3</a></li>
				<li><a href="#block-4">Блок 4</a></li>
			</ul>
		</div>
	</div>
</div>

<div class="wrp">
	<div id="block-1" class="block">Блок id="block-1"</div>
	<div id="block-2" class="block">Блок id="block-2"</div>
	<div id="block-3" class="block">Блок id="block-3"</div>
	<div id="block-4" class="block">Блок id="block-4"</div>
</div>
HTML

Для работы потребуется jQuery:

<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
HTML

Код разнесен на две независимые секции – «Фиксация меню» и «Выделение активных пунктов».

$(document).ready(function(){
	/* Фиксация меню при прокрутке */
	$('.header-menu-wrp')
		.addClass('original')
		.clone()
		.insertAfter('.header-menu-wrp')
		.addClass('cloned')
		.removeClass('original');

	function resizeMenu(){
		var $original = $('.header-menu-wrp.original');
		var $cloned = $('.header-menu-wrp.cloned');
		
		if ($(window).scrollTop() >= ($original.offset().top)){    
			$cloned.css({
				'top': 0, 
				'width': $original.css('width'), 
				'display': 'block',
				'left': $original.offset().left+'px'
			});
			$original.css('visibility', 'hidden');
		} else {
			$cloned.css('display', 'none');
			$original.css('visibility', 'visible');
		}
	}

	$(window).scroll(function(){
		resizeMenu();
	});

	$(window).resize(function(){
		resizeMenu();	
	});

	/* Выделение активных пунктов меню */
	var last_id;
	var $top_menu = $('.header-menu-wrp.cloned');
	var menu_height = $top_menu.outerHeight(true);
	var $menu_items = $top_menu.find('a');
	var $scroll_items = $menu_items.map(function(){
		var item = $($(this).attr('href'));
		if (item.length){
			return item;
		}
	});

	$menu_items.click(function(e){
		var href = $(this).attr('href'),
		offset_top = href === '#' ? 0 : $(href).offset().top - menu_height;
		$('html, body').stop().animate({
			scrollTop: offset_top
		}, 300);
		e.preventDefault();
	});

	$(window).scroll(function(){
		var from_top = $(this).scrollTop() + menu_height;
		var mar = parseInt($top_menu.css('margin-bottom'));
		var cur = $scroll_items.map(function(){
			if ($(this).offset().top < from_top + mar){
				return this;
			}
		});
		cur = cur[cur.length - 1];
		var id = cur && cur.length ? cur[0].id : '';
		if (last_id !== id){
			last_id = id;
			$menu_items.parent()
				.removeClass('active')
				.end()
				.filter("[href='#" + id + "']")
				.parent()
				.addClass('active');
		}
	});
});
JS
/* Стили блоков */
.wrp {
	width: 600px;
	margin: 0 auto;
}
.header {
	text-align: center;
	border: 1px dashed #ddd;
	padding: 50px 0;
	margin: 20px 0;
	font-size: 18px;
}
.block {
	text-align: center;
	border: 1px dashed #ddd;
	padding: 100px 0;
	margin-bottom: 20px;
	font-size: 18px;
	background: #eeeeee; 
}

/* Фиксированное меню */
.header-menu-wrp {
	height:40px; 
	line-height:40px; 
	width:100%;
	background: #f48221;
	color: white;
	margin-bottom: 20px;
}
.header-menu-wrp.cloned {
	position: fixed;
	top: 0;
	margin-top: 0;
	z-index: 9999;
	display: none;
}

/* Растягивание меню на всю ширину */
.header-menu {
	width: 100%;
	display: table;
	border-left: 1px solid #ffa44c;
}
.header-menu ul {
	display: table-row;
}
.header-menu li {
	display: table-cell;
	float: none;
	border-right: 1px solid #ffa44c;
}
.header-menu li.active {
	background: orange;
}
.header-menu li a {
	display: block;
	color: #fff;
	text-align: center;
}
CSS
19.12.2018, обновлено 17.02.2020
8552

Комментарии

, чтобы добавить комментарий.

Другие публикации

Выделение активных пунктов меню с помощью JQuery
Небольшой пример, как выделить активный пункт в меню с помощью JQuery. Возьмем меню для левой колонки...
2997
+4
Выравнивание блоков на всю ширину (justify)
Как в горизонтальным меню, метод с justify и after 100% можно использовать для выравнивания других элементов в одну...
5316
0
Горизонтальное меню justify
В отличии предыдущего меню, где есть отступы у каждого элемента, часто возникает задача сделать резиновое меню без них. Пункты меню должно идти с одинаковыми интервалами и без отступов по бокам.
5533
0
Главное меню для мобильной версии сайта
Не очень сложное раскрывающееся меню для мобильной версии сайта на JQuery.
27785
+10
Меню-подсказка на затемненном фоне
Пример реализации всплывающей подсказки или меню с затемнением фона на jQuery и CSS, в верстке использованы блок со...
3234
+1
Как сделать интерактивную схему на SVG + jQuery
В данном примере описано как сделать интерактивную схему магазинов на основе векторной графики SVG и jQuery.
29858
+11