Выпадающее меню для WordPress на CSS

В этой статье я расскажу, как создать выпадающее меню для WordPress на CSS. Сначала опишу все этапы создания меню с настройкой через CSS, а затем выведу его через файл темы.

Примечание: я буду использовать WordPress 3.9 и тему Twenty Thirteen, но все действия аналогичны для любого сайта на WordPress 3.

Демо-версия

Ниже приведена ссылка на скачивание ZIP-архива, который содержит все необходимые для этой статьи коды.

Демо-версия: Выпадающее меню для WordPress - Версия 1.0 (3 кБ ZIP)

Создаем меню в WordPress

WordPress 3 имеет простой в использовании drag-and-drop интерфейс для создания структуры меню. Если вы еще не работали с меню, чтобы создать и сохранить пользовательское меню, перейдите Внешний вид > Меню. Задайте для меню название и сохраните его:

Создаем меню в WordPress

Добавление пользовательского Walker-класса в functions.php

Прежде, чем мы сможем вывести меню в файле темы WordPress, нам нужно добавить Walker-класс WordPress в файл functions.php.

Этот код «очистит» выводимую HTML-разметку нашего меню, чтобы мы могли легко создавать CSS. Скопируйте и вставьте код класса Walker в файл functions.php, который располагается в папке темы. Если файл functions.php не существует, создайте его, а затем вставьте в него код класса:

class CSS_Menu_Walker extends Walker {
	var $db_fields = array('parent' => 'menu_item_parent', 'id' => 'db_id');
	
	function start_lvl(&$output, $depth = 0, $args = array()) {
		$indent = str_repeat("t", $depth);
		$output .= "n$indent<ul>n";
	}
	
	function end_lvl(&$output, $depth = 0, $args = array()) {
		$indent = str_repeat("t", $depth);
		$output .= "$indent</ul>n";
	}
	
	function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0) {
	
		global $wp_query;
		$indent = ($depth) ? str_repeat("t", $depth) : '';
		$class_names = $value = '';
		$classes = empty($item->classes) ? array() : (array) $item->classes;
		
		/* Добавление активного класса */
		if (in_array('current-menu-item', $classes)) {
			$classes[] = 'active';
			unset($classes['current-menu-item']);
		}
		
		/* Проверка наличия дочерних элементов */
		$children = get_posts(array('post_type' => 'nav_menu_item', 'nopaging' => true, 'numberposts' => 1, 'meta_key' => '_menu_item_menu_item_parent', 'meta_value' => $item->ID));
		if (!empty($children)) {
			$classes[] = 'has-sub';
		}
		
		$class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item, $args));
		$class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';
		
		$id = apply_filters('nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args);
		$id = $id ? ' id="' . esc_attr($id) . '"' : '';
		
		$output .= $indent . '<li' . $id . $value . $class_names .'>';
		
		$attributes  = ! empty($item->attr_title) ? ' title="'  . esc_attr($item->attr_title) .'"' : '';
		$attributes .= ! empty($item->target)     ? ' target="' . esc_attr($item->target    ) .'"' : '';
		$attributes .= ! empty($item->xfn)        ? ' rel="'    . esc_attr($item->xfn       ) .'"' : '';
		$attributes .= ! empty($item->url)        ? ' href="'   . esc_attr($item->url       ) .'"' : '';
		
		$item_output = $args->before;
		$item_output .= '<a'. $attributes .'><span>';
		$item_output .= $args->link_before . apply_filters('the_title', $item->title, $item->ID) . $args->link_after;
		$item_output .= '</span></a>';
		$item_output .= $args->after;
		
		$output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
	}
	
	function end_el(&$output, $item, $depth = 0, $args = array()) {
		$output .= "</li>n";
	}
}

Вывод меню через файл темы

Теперь у нас есть созданное меню и размещенный класс Walker. Пришло время вывести наше меню через файл темы. Для этого мы используем функцию wp_nav_menu(). С помощью PHP мы вызовем эту функцию и передадим ей параметры нашего меню для вывода структуры HTML.

Параметр menu - это название меню, созданного нами в шаге 1. container_id добавляет в HTML-код меню идентификатор CSS, который мы будем использовать позже в стилях CSS. Параметр Walker указывает функции wp_nav_menu() использовать для вывода HTML-разметки наш пользовательский Walker-класс WordPress:

<?php wp_nav_menu(array(
	'menu' => 'Main Menu', 
	'container_id' => 'cssmenu', 
	'walker' => new CSS_Menu_Walker()
)); ?>

Добавьте этот PHP-код в один из файлов темы. Где бы вы его не поместили, меню будет выводиться в этом месте. Я использую тему WordPress по умолчанию Twenty Thirteen. Она содержит файл header.php, в него я и вставлю этот код.

Если вы сделали все правильно, то сейчас должны увидеть, что в вашей теме отображается HTML-список без заданных стилей:

Вывод меню через файл темы

Добавление CSS

Откройте файл CSS вашей темы styles.css (в папке CSS или в корневом каталоге темы). Вы можете сразу скопировать и вставить весь приведенный ниже код в файл CSS вашей темы. Я буду разбивать CSS-код на части, чтобы пояснять каждый его фрагмент.

Обратите внимание, что мы используем тот же идентификатор, который мы указали в функции wp_nav_menu() - #cssmenu.

Первый фрагмент CSS-кода - это всего лишь несколько строк, чтобы быть уверенными, что все браузеры начинают обработку с той же точки:

#cssmenu,
#cssmenu ul,
#cssmenu li,
#cssmenu a {
	border: none;
	margin: 0;
	padding: 0;
	line-height: 1;
	-webkit-box-sizing: content-box;
	-moz-box-sizing: content-box;
	box-sizing: content-box;
}

Следующий фрагмент CSS-кода - это стили первого уровня выпадающего меню. Если браузер пользователя не поддерживает градиенты, то заполните фон цветом #3c3c3c.

Псевдокласс :after позволяет добавить тонкую цветную рамку вокруг каждого пункта меню:

#cssmenu {
	height: 37px;
	display: block;
	padding: 0;
	margin: 0;
	border: 1px solid;
	border-radius: 5px;
	width: auto;
	border-color: #080808;
}
#cssmenu,
#cssmenu > ul > li > ul > li a:hover {
	background: #3c3c3c;
	background: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%);
	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #3c3c3c), color-stop(100%, #222222));
	background: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%);
	background: -o-linear-gradient(top, #3c3c3c 0%, #222222 100%);
	background: -ms-linear-gradient(top, #3c3c3c 0%, #222222 100%);
	background: linear-gradient(top, #3c3c3c 0%, #222222 100%);
}
#cssmenu > ul {
	list-style: inside none;
	padding: 0;
	margin: 0;
}
#cssmenu > ul > li {
	list-style: inside none;
	padding: 0;
	margin: 0;
	float: left;
	display: block;
	position: relative;
}
#cssmenu > ul > li > a {
	outline: none;
	display: block;
	position: relative;
	padding: 12px 20px;
	text-align: center;
	text-decoration: none;
	text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.4);
	font-weight: bold;
	font-size: 13px;
	font-family: Arial, Helvetica, sans-serif;
	border-right: 1px solid #080808;
	color: #ffffff;  
}
#cssmenu > ul > li > a:hover {
	background: #080808;
	color: #ffffff;
}
#cssmenu > ul > li:first-child > a {
	border-radius: 5px 0 0 5px;
}
#cssmenu > ul > li > a:after {
	content: '';
	position: absolute;
	border-right: 1px solid;
	top: -1px;
	bottom: -1px;
	right: -2px;
	z-index: 99;
	border-color: #3c3c3c;  
}

На данный момент ваше меню должно выглядеть так, как показано на рисунке ниже:

Добавление CSS

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

Сначала нам нужно установить для всех пунктов подменю display: none. После этого мы используем псевдокласс :hover, чтобы установить для подменю состояние:hover. Это создаст эффект скрытия и вывода подменю при наведении указателя мыши на родительский элемент:

#cssmenu ul li.has-sub:hover > a:after {
	top: 0;
	bottom: 0;
}
#cssmenu > ul > li.has-sub > a:before {
	content: '';
	position: absolute;
	top: 18px;
	right: 6px;
	border: 5px solid transparent;
	border-top: 5px solid #ffffff;
}
#cssmenu > ul > li.has-sub:hover > a:before {
	top: 19px;
}
#cssmenu ul li.has-sub:hover > a {
	background: #3f3f3f;
	border-color: #3f3f3f;
	padding-bottom: 13px;
	padding-top: 13px;
	top: -1px;
	z-index: 999;
}
#cssmenu ul li.has-sub:hover > ul,
#cssmenu ul li.has-sub:hover > div {
	display: block;
}
#cssmenu ul li.has-sub > a:hover {
	background: #3f3f3f;
	border-color: #3f3f3f;
}
#cssmenu ul li > ul,
#cssmenu ul li > div {
	display: none;
	width: auto;
	position: absolute;
	top: 38px;
	padding: 10px 0;
	background: #3f3f3f;
	border-radius: 0 0 5px 5px;
	z-index: 999;
}
#cssmenu ul li > ul {
	width: 200px;
}
#cssmenu ul li > ul li {
	display: block;
	list-style: inside none;
	padding: 0;
	margin: 0;
	position: relative;
}
#cssmenu ul li > ul li a {
	outline: none;
	display: block;
	position: relative;
	margin: 0;
	padding: 8px 20px;
	font: 10pt Arial, Helvetica, sans-serif;
	color: #ffffff;
	text-decoration: none;
	text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.5);
}
#cssmenu ul ul a:hover {
	color: #ffffff;
}
#cssmenu > ul > li.has-sub > a:hover:before {
	border-top: 5px solid #ffffff;
}

Если вы все сделали правильно, то должны получить новое выпадающее меню WordPress. Если, вам кажется, что в этом меню что-то не так, прочитайте раздел, посвященный устранению неполадок.

Исходные файлы

По этой ссылке вы можете скачать исходные файлы. ZIP-архив содержит functions.php и styles.css:

Демо-версия: Выпадающее меню для WordPress - Версия 1.0 (3 кБ ZIP)

Устранение неполадок

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

Единственный способ решить эту проблему - определить эти стили CSS и удалить их. Лучше всего использовать для этого расширение Firebug для Firefox и проинспектировать стили CSS вручную. Как только вы найдете конфликтующие стили, удалите их.