WordPress Component Library
10up Engineering

Responsive Navigation

The responsive navigation component is a normal horizontal navigation on large screen, and collapses down to an off-canvas model on small viewports. The default HTML should work within the confines of WordPress, but some modifications may have to be implemented for your specific use case. No jQuery is required.

HTML

<header class="site-header" role="banner" itemscope="itemscope" itemtype="http://schema.org/WPHeader">
	<?php if( is_front_page() ) : ?>
		<h1 class="site-title" itemscope itemtype="http://schema.org/Organization">
			<img class="site-logo"
				src="<?php echo esc_url( get_template_directory_uri() . '/image/folder/path' ); ?>"
				height="40" width="140"
				itemprop="logo"
				alt="">
			<!--
				Visually hide this text.
				WCAG 2.0: “image alt text cannot be the primary text of a link"
			-->
			<span class="screen-reader-text"><?php echo esc_attr( bloginfo( 'name' ) ); ?></span>
		</h1>
	<?php else : ?>
		<div class="site-title" itemscope itemtype="http://schema.org/Organization">
			<a href="<?php echo esc_url( home_url() ); ?>" rel="home" class="site-link" itemprop="url">
				<img class="site-logo"
					src="<?php echo esc_url( get_template_directory_uri() . '/image/folder/path' ); ?>"
					height="42" width="140"
					itemprop="logo"
					alt="">
				<!--
					Visually hide this text.
					WCAG 2.0: “image alt text cannot be the primary text of a link"
				-->
				<span class="screen-reader-text"><?php echo esc_attr( bloginfo( 'name' ) ); ?></span>
			</a>
		</div>
	<?php endif; ?>

	<nav class="site-navigation" role="navigation" itemscope="itemscope" itemtype="http://schema.org/SiteNavigationElement">

		<a href="#primary-menu" id="js-menu-toggle" class="site-menu-toggle">
			<span class="screen-reader-text">
				<?php esc_html_e( 'Primary Menu', 'tenup' ); ?>
			</span>
			<span aria-hidden="true"></span>
		</a>

		<?php
			wp_nav_menu( array(
				'theme_location' => 'primary',
				'menu_class'     => 'primary-menu',
				'menu_id'        => 'menu-main-nav',
			) );
		?>
	</nav>
</header>
<header class="site-header" role="banner" itemscope="itemscope" itemtype="http://schema.org/WPHeader">
	<h1 class="site-title" itemscope itemtype="http://schema.org/Organization">
		<a  itemprop="url" class="site-link" href="#" rel="home">
			<img itemprop="logo" class="site-logo" src="https://placehold.it/140x40?text=LOGO" height="42" width="140" alt="">
			<!--
				Visually hide this text.
				WCAG 2.0: “image alt text cannot be the primary text of a link"
			-->
			<span class="screen-reader-text">Amazing Company</span>
		</a>
	</h1>

	<nav class="site-navigation" role="navigation" itemscope="itemscope" itemtype="http://schema.org/SiteNavigationElement">

		<a href="#menu-main-nav" id="js-menu-toggle" class="site-menu-toggle">
			<span class="screen-reader-text">Primary Menu</span>
			<span aria-hidden="true"></span>
		</a>

		<ul id="menu-main-nav" class="primary-menu">
			<li id="menu-item-1912" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-1912">
				<a href="#">About Us</a>
			</li>
			<li id="menu-item-1913" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-1913">
				<a href="#">Our Work</a>
				<ul class="sub-menu">
					<li id="menu-item-1914" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-1914">
						<a href="#">JavaScript</a>
					</li>
					<li id="menu-item-4494" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-4494">
						<a href="#">WordPress</a>
						<ul class="sub-menu">
							<li id="menu-item-4495" class="menu-item menu-item-type-post_type menu-item-object-post menu-item-4495">
								<a href="#">Plugins</a>
							</li>
							<li id="menu-item-4496" class="menu-item menu-item-type-post_type menu-item-object-post menu-item-4496">
								<a href="#">Themes</a>
							</li>
						</ul>
					</li>
				</ul>
			</li>
			<li id="menu-item-1915" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-1915">
				<a href="#">Giving Back</a>
			</li>
			<li id="menu-item-1916" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-1916">
				<a href="#">Blog</a>
			</li>
			<li id="menu-item-1916" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-1916">
				<a href="#">Contact</a>
			</li>
		</ul>

	</nav>
</header>

SCSS Download SCSS

// Breakpoints
$bp-small:          40.625em !default;      // 650px
$bp-medium:         53.125em !default;      // 850px
$bp-large:          62.5em !default;        // 1000px

// Variables
$color-gray: #999 !default;

// Use this flag to toggle the CSS & JS for traditional "large screen" horizontal navigation
$use-large-screen: true !default;

.screen-reader-text {
	clip: rect(1px, 1px, 1px, 1px);
	position: absolute !important;
	height: 1px;
	width: 1px;
	overflow: hidden;
}

/*
	REQUIRED: Adding the named breakpoint into the DOM for JS hooks
*/

body:before {
	content: "small";
	display: none;

	@if $use-large-screen == true {

		@media ( min-width: $bp-medium ) {
			content: "medium";
		}

		@media ( min-width: $bp-large ) {
			content: "large";
		}

	}

}

.container {
	max-width: 1000px;
	margin: auto;
}

// Component Sass
.site-header {
	background: $color-gray;
	padding: .5rem;
	position: relative;

	&:before,
	&:after {
		content: " ";
		display: table;
	}

	&:after {
		clear: both;
	}

}

.site-title {
	line-height: 0;
	margin: 0;
	padding: 0 1em 0 0;
	float: left;
}

.site-link {
	display: inline-block;
	line-height: 0;

	img {
		max-height: 48px;
	}
}

.site-navigation {

	@if $use-large-screen == true {
		@media ( min-width: $bp-medium ) {
			float: right;
		}
	}

	ul {
		list-style: none;
		padding: 0;
	}
}

.site-menu-toggle {
	float: right;
	line-height: 40px;
	font-size: 20px;
	text-decoration: none;
	margin-right: 10px;

	@if $use-large-screen == true {
		@media ( min-width: $bp-medium ) {
			display: none;
		}
	}
}

.primary-menu {
	background: $color-gray;
	margin: 0;
	overflow: hidden;
	clear: both;
	display: none;

	&[aria-hidden="true"] {
		width: 0;
	}

	&[aria-hidden="false"],
	&:target {
		display: block;
	}

	@if $use-large-screen == true {
		@media ( min-width: $bp-medium ) {
			background: transparent;
			display: block;
			float: right;
			height: auto;
			overflow: visible;
			position: relative;
			top: 0;
			transform: translateX(0);
			width: auto;
		}
	}

	.menu-item {
		@if $use-large-screen == true {
			@media ( min-width: $bp-medium ) {
				display: inline-block;
				position: relative;
				text-align: left;
			}
		}

		button {
			display: none;
		}

		&.menu-item-has-children {
			> a {
				padding-right: 25px;
				position: relative;

				&:after {
					background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512' viewBox='0 0 512 512'%3E%3Cpath fill='white' d='M256 352L96 198.406 141.72 160 256 275.188 370.28 160 416 198.406 256 352z'/%3E%3C/svg%3E ");
					background-size: cover;
					content: "";
					height: 20px;
					position: absolute;
					right: 0;
					top: calc(50% - 10px);
					width: 20px;
				}
			}
		}

		&:hover,
		&:focus {
			> .sub-menu {
				.no-js & {
					display: block;
				}

				@if $use-large-screen == true {
					@media ( min-width: $bp-medium ) {
						display: block;
					}
				}
			}
		}

		a {
			display: block;
			padding: 10px 15px;
		}

	} // .menu-item

	&.uses-click {
		.menu-item {
			&:hover {
				.sub-menu {
					display: none;

					&[aria-hidden="false"] {
						display: block;
					}

				}
			}
		}
	}

	.sub-menu {
		background-color: $color-gray;
		display: none;
		min-width: 125px;
		background: #777;

		.sub-menu {
			background: #555;
		}

		@if $use-large-screen == true {
			@media ( min-width: $bp-medium ) {
				position: absolute;

				.menu-item {
					display: block;
				}
			}
		}

	} // .sub-menu

	.child-has-focus > .sub-menu {
		display: block;
	}
}

JS Usage | Plugin

TenUp.navigation({
	'target'        : '#menu-main-nav',
	'toggle'        : '#js-menu-toggle',
	'sub_menu_open' : 'click'
}, function() {
	console.log('Amazing callback function!');
});

JavaScript API

TenUp.navigation( { options }, callback );

This is the main method to call the plugin. It currently takes two arguments, an options object and callback function.

options

Currently recognizes the following: target, toggle, sub_menu_open. To request more options, please file an issue.

target : '#primary-nav'

The target option should contain the ID (with #) on the navigation <ul>. Using an ID will be faster than a class, but they should both work. The default value is #primary-nav.

toggle : '#js-menu-toggle'

The toggle option is the ID value assigned to the anchor used to toggle the small screen menu. The default value is #js-menu-toggle.

sub_menu_open : 'click'

The sub_menu_open option lets you set the style on opening the menu for large screen. The default value is hover, but click is another option.

callback

Accepts a function that will be executed upon completion.

Sass API

To turn off the large screen view all together set the Sass variable $use-large-screen to false in the .scss file. All breakpoints (for CSS and JS are managed in the Sass file).

Browser Compatibility

Feature Chrome Firefox Internet Explorer Safari
Basic Support Latest Latest 10+ 5.1+

Resources