Методы создания адаптивной навигации в WordPress

Навигация – одно из самых проблематичных мест при реализации качественного адаптивного дизайна. В качестве предисловия к этой статье я настоятельно рекомендую изучить следующие материалы от Брэда Фроста: набор адаптивных навигационных паттернов и комплексные навигационные паттерны. В этой статье я раскрою два метода переключения (toggle), предназначенных для создания адаптивной навигации в WordPress.

Общие адаптивные навигационные паттерны в WordPress

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

Метод переключения обычно представлен кнопкой с текстом или иконкой «гамбургера», заменяющей встроенный метод навигации, когда размер экрана ужимается до определенного размера. Триггер для метода переключения – то, на чем я хочу сфокусировать свое внимание.

Первый метод переключения – изменение размеров c помощью jQuery на базе ширины окна
Я использовал метод, очень похожий на описанный далее, еще с тех пор, как я увидел его в _s теме более года назад. По существу, триггер обрабатывается путем определения ширины окна с помощью $( window ).width(). Я разберу несколько обновленную версию этого кода ниже, а пока вы можете увидеть этот метод в действии на Github Gist.

Когда ширина окна превышает 600px, используется класс main-navigation, а когда ширина окна становится меньше 600px, для меню используется класс main-small-navigation. Кроме того, h1, используемый для вспомогательного текста (что сделано с целью удобства просмотра), меняется при переключении меню и является текстом, связанным с функцией jQuery .click.

Именно поэтому меню может быть превращено в активируемый по клику переключаемый метод навигации для небольших экранов.

Это достаточно удобное решение, однако используется оно не так часто. У него есть определенная сложность – необходимо тщательно подгонять пиксельное значение той границы, за которой меню будет изменяться. Этот метод будет идеальным, если вы формируете родительскую тему из стартеров, таких как _s, однако в идеале лучше воспользоваться родительскими темами, поддерживающими дочерние темы и детальную настройку. Мы можем сделать фиксированные значения фильтруемыми с помощью PHP, используя wp_localize_script.

Интеграция wp_localize_script для достижения гибкости

Ниже приведен пример альтернативного JS-файла и соответствующего подключения, использующего wp_localize_script для последующей PHP-фильтрации фиксированных значений.

/**
 * Обрабатывает переключение основного навигационного меню для небольших экранов.
 * small_menu_vars.size используется вместо "600" или других фиксированных пиксельных значений – оно определяется при помощи wp_localize_script в функциях 
 */
jQuery( document ).ready( function( $ ) {
	var $masthead = $( '#masthead' ),
	    timeout = false;

	$.fn.smallMenu = function() {
		$masthead.find( '.site-navigation' ).removeClass( 'main-navigation' ).addClass( 'main-small-navigation' );
		$masthead.find( '.site-navigation h1' ).removeClass( 'assistive-text' ).addClass( 'menu-toggle' );

		$( '.menu-toggle' ).click( function() {
			$masthead.find( '.menu' ).toggle();
			$( this ).toggleClass( 'toggled-on' );
		} );
	};

	// Определяем ширину области просмотра при первой загрузке
	if ( $( window ).width() < small_menu_vars.size )
		$.fn.smallMenu();

	// Определяем ширину области просмотра, когда пользователь изменил размеры окна 
              // браузера
	$( window ).resize( function() {
		var browserWidth = $( window ).width();

		if ( false !== timeout )
			clearTimeout( timeout );

		timeout = setTimeout( function() {
			if ( browserWidth < small_menu_vars.size ) {
				$.fn.smallMenu();
			} else {
				$masthead.find( '.site-navigation' ).removeClass( 'main-small-navigation' ).addClass( 'main-navigation' );
				$masthead.find( '.site-navigation h1' ).removeClass( 'menu-toggle' ).addClass( 'assistive-text' );
				$masthead.find( '.menu' ).removeAttr( 'style' );
			}
		}, 200 );
	} );
} );

Вы можете использовать переменную small_menu_vars.size вместо зафиксированного ранее пиксельного значения. Эта переменная способна использовать динамические данные благодаря великолепной функции wp_localize_script, которая так прекрасно была рассмотрена Pippin Williamson в прошлом году. Я считаю, что такой вариант использования может оказаться достаточно полезным, особенно если его применять в родительских темах.

Если перенестись к нашему примеру, то, чтобы использовать эту переменную, мы должны соответствующим образом настроить нашу переменную с помощью wp_localize_script. Вот код, который покажется вам знакомым, если вы прочли руководство Williamson:

<?php
/**
 * Регистрируем скрипты для темы и подключаем их на сайте.
 *
 * @since 0.1.0.
 */
add_action( 'wp_enqueue_scripts', 'krogs_theme_scripts' );

function krogs_theme_scripts() {

	wp_register_script( 'small-menu', get_template_directory_uri() . '/js/small-menu.js', array( 'jquery' ), '20120206', true );

	wp_localize_script('small-menu', 'small_menu_vars', array(
			'size' => apply_filters( 'krogs_theme_small_menu_size', 600 )
		)
	);

	wp_enqueue_script( 'small-menu' );

}     

Заметили фильтр? Именно здесь и начинается самое интересное. Теперь мы можем сделать число, которое раньше нам нужно было фиксировать вручную, фильтруемым из дочерних тем. Вот пример фильтра:

<?php
/**
 * функция krogs_child_theme_new_menu_size.
 * 
 */
add_filter( 'krogs_theme_small_menu_size', 'krogs_child_theme_new_menu_size' );

function krogs_child_theme_new_menu_size( $size ) {

	$size = 450;

	return 450;

}

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

Второй метод переключения – JavaScript и медиа-запросы CSS

Предыдущий скрипт действительно завязан на jQuery, и если ваш проект не требует подключения этой библиотеки (что маловероятно в наши дни), то в таком случае вы можете взглянуть на альтернативное решение. Или, возможно, у вас возникла идея обработки точки перехода более качественным способом с помощью CSS медиа-запросов.

Последняя навигационная итерация в теме _s использует JavaScript реализацию, позволяющую идентифицировать текущее состояние разметки страницы и сделать CSS-основанное переключаемое меню очень простым.

Для начала давайте посмотрим на разметку навигации.

<header id="masthead" class="site-header" role="banner">
	<div class="site-branding">
		<h1 class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1>
		<h2 class="site-description"><?php bloginfo( 'description' ); ?></h2>
	</div>

	<nav id="site-navigation" class="main-navigation" role="navigation">
		<h1 class="menu-toggle"><?php _e( 'Menu', '_s' ); ?></h1>
		<div class="screen-reader-text skip-link"><a href="#content" title="<?php esc_attr_e( 'Skip to content', '_s' ); ?>"><?php _e( 'Skip to content', '_s' ); ?></a></div>

		<?php wp_nav_menu( array( 'theme_location' => 'primary' ) ); ?>
	</nav><!-- #site-navigation -->
</header><!-- #masthead --> 

Первое, что вы должны заметить: класс menu-toggle стоит в h1 с самого начала. Все, что сделает наш Javascript – это активирует функцию click для h1, используя переключаемый класс. Само переключаемое меню (h1) скрыто по умолчанию с помощью display: none; и меняется с помощью медиа-запроса для ширины max-width: 600px на display: block;. В то же самое время наше стандартное меню скрыто по умолчанию и отображается только тогда, когда активирован переключаемый класс.

/* Небольшое меню */
.menu-toggle {
	display: none;
	cursor: pointer;
}

@media screen and (max-width: 600px) {
	.menu-toggle,
	.main-navigation.toggled .nav-menu {
		display: block;
	}

	.main-navigation ul {
		display: none;
	}
}

Код Javascript, который делает это, содержится в самом низу файла. В первых 15 строках (или где-то так) стоит проверка, что различные части меню существуют, и если их нет, то выполнение Javascript останавливается.

Переменная button определяется путем получения h1 в #site-navigation.

/**
 * navigation.js
 *
 * Обрабатывает переключение меню для небольших экранов.
 */
( function() {
	var container, button, menu;

	container = document.getElementById( 'site-navigation' );
	if ( ! container )
		return;

	button = container.getElementsByTagName( 'h1' )[0];
	if ( 'undefined' === typeof button )
		return;

	menu = container.getElementsByTagName( 'ul' )[0];

	// Скрывает кнопку переключения меню, если меню пустое, и возвращает раннее значение
	if ( 'undefined' === typeof menu ) {
		button.style.display = 'none';
		return;
	}

	if ( -1 === menu.className.indexOf( 'nav-menu' ) )
		menu.className += ' nav-menu';

	button.onclick = function() {
		if ( -1 !== container.className.indexOf( 'toggled' ) )
			container.className = container.className.replace( ' toggled', '' );
		else
			container.className += ' toggled';
	};
} )();

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

Гибкость для тем

Этот метод является более гибким, поскольку значения для точек перехода заданы в CSS. Однако было бы несколько странным переписывать медиа-запросы в дочерней теме, чтобы скорректировать границу перехода.

Какой метод лучше?

Я считаю, что практически во всех ситуациях второй метод без jQuery, включающий в себя обработку через CSS, выигрывает, поскольку он гибкий, быстрый и отличается отличной поддержкой.

Однако некоторые темы могут быть структурированы так, что переписывание CSS медиа-запросов будет представлять собой значительную сложность, потому в таком случае предпочтительным вариантом будет использование jQuery решения и wp_localize_script.

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

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

Блог про WordPress
Добавить комментарий

Получать новые комментарии по электронной почте.