Випадающее навигационное меню на CSS/HTML

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

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

То есть наводим на первый уровень → видим вложенные пункты → нажимаем и переходим на страницу второго уровня (подпункт). Фактически одно нажатие.

Если мы не даем возможность сразу перейти на подпункт, то пользователю нужно будет сначала посетить родительский раздел, а затем только вложенный в него пункт меню. Это не удобно с точки зрения юзабилиты — у нас есть лишнее нажатие и переход, то есть два нажатия.

Когда это необходимо

  1. При наличии каталога. В большинстве случаев каталог имеет категории и подкатегории.
    К примеру вложенность:
    — Магазин (уровень 1)
    — Категория 1 (уровень 2)
    — Категория 2 (уровень 2)
    — Категория 3 (уровень 2)

  2. В других случаях, когда есть раздел «О нас», например
    — О нас (уровень 1)
    — Наша история (уровень 2)
    — Наша команда (уровень 2)
    — Отзывы (уровень 2)

Навигационное меню

Условия

  1. Навигационное меню должно быть сделано неупорядоченным списком, то есть на тегах <ul><li>, все свойства на элементы задаем от основного класса на родительском элементе.
  2. Активный класс называется ‘active’
  3. В неупорядоченном списке нет тегов кроме <ul>, <li>, <a>. Если нужно добавить обертку <div>, <span> и другие — сделайте это на js

По коду дополнительно можно посмотреть здесь — «Стандартные HTML элементы и структура сайта«, там же можно загрузить HTML шаблон.

Почему именно так

  1. Навигационное меню будет интегрироваться в CMS, а 100% CMS таких как Worpdress, Joomla, Opencart и многие другие, имеют именно такую ​​разметку – неупорядоченный список без классов на ссылках или других дополнительных конструкциях типа как обертка вокруг вложенного <ul>
  2. Классы могут отличаться в различных CMS. Например, в WordPress активный класс это current-menu-item, у Joomla — active, это лишь пример, а не проблема. Переименовать или добавить через класс это не проблема. Проблема это когда будут добавлены классы на все уровни, еще и разные, и это нужно как-то будет интегрировать. Да, можно подключить свою разметку меню через Walker_Nav_Menu в Wordrpess или добавить через модуль в Joomla попытаться сделать разметку, вот только зачем – это все гораздо сложнее, чем сделать это на css.
  3. В целом это стандарт использовать список без лишних элементов для навигационного меню.

Как делать меню

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

HTML код для навигационного меню первого уровня


<ul class="menu">
	<li><a href="#">Home</a></li>
	<li><a href="#">Shop</a></li>
	<li><a href="#">Blog</a></li>
	<li><a href="#">About Us</a></li>
	<li><a href="#">Contact Us</a></li>
</ul>

Тег <a> не оставляем пустым. Если нам неизвестна ссылка, то ставим ‘#‘. Это обязательно.

Тег <li> это блочный элемент, чтобы сделать его линейным (пункты рядом друг с другом), нам необходимо использовать css свойство display чтобы изменить поведение элемента.

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

Допустимо использовать одно из трех значений:

  1. display: flex (нет сейчас больших проблем при применении)
  2. float: left (нужно будет добавлять дополнительные свойства на родительский контейнер, поэтому еще после применения на дочерние <li> элементы свойства float, высота родительского <ul> будет равна нулю
  3. inline-block (требуется учитывать дополнительный отступ в 4px, которое будет добавлено на каждый элемент, также будут проблемы с вертикальным позиционированием текста или других элементов внутри элемента)

CSS код для навигационного меню первого уровня


.menu {
	display: flex; /* задаем flex на родительский контейнер чтобы сделать вложенные элементы в одну строчку */
	background: #4d6719; /* добавляю фон на родительский контейнер */
}
.menu li {
	font-size: 16px; /* размер шрифта */
	font-family: Arial, Helvetica; /* добавляем через запятую шрифты */
	border-left: 1px solid #7ba428; /* визуальный элемент – полоска между пунктами */
	position: relative; /* это необходимо, чтобы позиционировать второй уровень относительно первого */
}
.menu>li:last-child {
	border-right: 1px solid #7ba428; /* мы добавили полоску слева, но у последнего пункта полоски не будет справа, поэтому добавляем ее отдельно только на последний пункт */
}
.menu li a {
	display: block; /* делаем тэг блоковым, чтобы можно было применить отступы */
	padding: 0 25px; /* добавляю отступы слева и справа – чтобы было пространство между полосками */
	line-height: 40px; /* такой высоты у нас будет контейнер, мы его центрируем по вертикали. */
	color: #9acd32;
	text-decoration: none;
}
.menu li a:hover, 
.menu li.active>a {
	color: #fff;
	background: #9acd32; 
        /* изменяем при наведении цвет фона пункта меню, цвет текста, через который прописываем значение для активного пункта  */
}

По «.menu li a»:

  • отступы нужно ставить именно на ссылку, чтобы пользователю проще было нажать (юзабилити) на ссылку – она будет размером на весь элемент.
  • центрировать текст с помощью отступов сложно; центрировать с помощью align-items — можно, но все равно нужно задавать вертикальный размер на <a>, так как у блочного элемента высота равна нулю и будет в нашем случае равна 16px — размеру шрифта пунктов навигационного меню, который равен 16px. Поэтому line-height это самый простой и быстрый способ
  • .menu li.active>a — пропишем через комбинатор (>), чтобы эти свойства не наследовали второму уровню меню

Визуально меню будет выглядеть так:

Добавим второй уровень меню для «Shop». Код HTML будет таким


<ul class="menu">
	<li><a href="#">Home</a></li>
	<li class="active">
		<a href="#">Shop</a>
		<ul>
			<li><a href="#">Category 1</a></li>
			<li class="active"><a href="#">Category 2</a></li>
			<li><a href="#">Category 3</a></li>
		</ul>
	</li>
	<li><a href="#">Blog</a></li>
	<li><a href="#">About Us</a></li>
	<li><a href="#">Contact Us</a></li>
</ul>

Код CSS для второго уровня выпадающего меню


/* sublevel */
.menu li ul {
	position: absolute; /* позиционируем абсолютно, чтобы этот элемент был в пределах первого уровня "shop" - я добавлял на него relative */
	top: 40px; /* указываем отступ сверху, который равен нашему line-height первого уровня */
	left: 0; /* позиционирование слева */
	width: 200px; /* задаем размер контейнера, иначе ширина будет равна ширине пункта меню второго уровня */
	border: 1px solid #5c7b1e; /* зададим обводку */
	border-top: none; /* уберем обводку сверху – она у нас будет добавлена ​​на li сверху */
	display: none; /* после того, как все стили оформлены, скрываем второй уровень меню */
}
.menu li ul li {
	border: none; /* обнуляем стили первого уровня */
	border-top: 1px solid #5c7b1e;
}
.menu li ul li a {
	line-height: 23px; /* обнуляем межстрочный интервал с первого уровня */
	background: #c2e184;
	color: #3d5214;
	padding: 10px 15px; /* задаем отступы */
}
.menu li ul li a:hover, 
.menu li ul li.active a {
	background: #6b9023; 
	color: #fff;
}
/* mouse over */
.menu li:hover ul {
	display: block; /* показываем меню при наведении на первый уровень меню */
}

Визуально навигационное меню будет выглядеть так

Код HTML выпадающего меню полностью


<ul class="menu">
	<li><a href="#">Home</a></li>
	<li class="active">
		<a href="#">Shop</a>
		<ul>
			<li><a href="#">Category 1</a></li>
			<li class="active"><a href="#">Category 2</a></li>
			<li><a href="#">Category 3</a></li>
		</ul>
	</li>
	<li><a href="#">Blog</a></li>
	<li><a href="#">About Us</a></li>
	<li><a href="#">Contact Us</a></li>
</ul>

Код CSS выпадающего меню полностью


.menu {
	display: flex; /* задаем flex на родительский контейнер чтобы сделать вложенные элементы в одну строчку */
	background: #4d6719; /* добавляю фон на родительский контейнер */
}
.menu li {
	font-size: 16px; /* размер шрифта */
	font-family: Arial, Helvetica; /* добавляем через запятую шрифты */
	border-left: 1px solid #7ba428; /* визуальный элемент – полоска между пунктами */
	position: relative; /* это необходимо, чтобы позиционировать второй уровень относительно первого */
}
.menu>li:last-child {
	border-right: 1px solid #7ba428; /* мы добавили полоску слева, но у последнего пункта полоски не будет справа, поэтому добавляем ее отдельно только на последний пункт */
}
.menu li a {
	display: block; /* делаем тэг блоковым, чтобы можно было применить отступы */
	padding: 0 25px; /* добавляю отступы слева и справа – чтобы было пространство между полосками */
	line-height: 40px; /* такой высоты у нас будет контейнер, мы его центрируем по вертикали. */
	color: #9acd32;
	text-decoration: none;
}
.menu li a:hover, 
.menu li.active>a {
	color: #fff;
	background: #9acd32; 
        /* изменяем при наведении цвет фона пункта меню, цвет текста, через который прописываем значение для активного пункта  */
}
/* sublevel */
.menu li ul {
	position: absolute; /* позиционируем абсолютно, чтобы этот элемент был в пределах первого уровня "shop" - я добавлял на него relative */
	top: 40px; /* указываем отступ сверху, который равен нашему line-height первого уровня */
	left: 0; /* позиционирование слева */
	width: 200px; /* задаем размер контейнера, иначе ширина будет равна ширине пункта меню второго уровня */
	border: 1px solid #5c7b1e; /* зададим обводку */
	border-top: none; /* уберем обводку сверху – она у нас будет добавлена ​​на li сверху */
	display: none; /* после того, как все стили оформлены, скрываем второй уровень меню */
}
.menu li ul li {
	border: none; /* обнуляем стили первого уровня */
	border-top: 1px solid #5c7b1e;
}
.menu li ul li a {
	line-height: 23px; /* обнуляем межстрочный интервал с первого уровня */
	background: #c2e184;
	color: #3d5214;
	padding: 10px 15px; /* задаем отступы */
}
.menu li ul li a:hover, 
.menu li ul li.active a {
	background: #6b9023; 
	color: #fff;
}
/* mouse over */
.menu li:hover ul {
	display: block; /* показываем меню при наведении на первый уровень меню */
}

Рабочий пример выпадающего навигационного меню

Вас также может заинтересовать