CodyHouse » Navigations https://codyhouse.co A free library of HTML/CSS/Javascript resources to boost your web projects and learn new tricks. Tue, 04 Apr 2017 16:36:48 +0000 en-US hourly 1 http://wordpress.org/?v=4.2.12 Stripe.com Navigation https://codyhouse.co/gem/stripe-navigation/ https://codyhouse.co/gem/stripe-navigation/#comments Wed, 12 Oct 2016 11:51:01 +0000 https://codyhouse.co/?post_type=gem&p=17280 Stripe.com navigation A morphing dropdown that animates according to the size of its content. A few weeks ago stripe.com launched a new website design. It looks awesome. One thing we dig in particular is the morphing navigation dropdown: instead of hiding and showing a new dropdown “container” when the user switches from one navigation item to the other, they animate the dropdown background to make space for different content sizes. We thought it would be interesting to explain how this effect is achieved, therefore we created our own version of Stripe navigation. Original version: Stripe.com Icons: Nucleoapp.com

Creating the structure

The HTML structure is composed of two main elements: the nav.main-nav for the top navigation items and the div.morph-dropdown-wrapper wrapping the dropdown elements. For each list item in the nav.main-nav element, a li.dropdown is created inside the .morph-dropdown-wrapper.
<header class="cd-morph-dropdown">
	<a href="#0" class="nav-trigger">Open Nav<span aria-hidden="true"></span></a>
	
	<nav class="main-nav">
		<ul>
			<li class="has-dropdown gallery" data-content="about">
				<a href="#0">About</a>
			</li>

			<li class="has-dropdown links" data-content="pricing">
				<a href="#0">Pricing</a>
			</li>

			<li class="has-dropdown button" data-content="contact">
				<a href="#0">Contact</a>
			</li>
		</ul>
	</nav>
	
	<div class="morph-dropdown-wrapper">
		<div class="dropdown-list">
			<ul>
				<li id="about" class="dropdown gallery">
					<!-- dropdown content here -->
				</li>

				<li id="pricing" class="dropdown links">
					<!-- dropdown content here -->
				</li>

				<li id="contact" class="dropdown button">
					<!-- dropdown content here -->
				</li>
			</ul>

			<div class="bg-layer" aria-hidden="true"></div>
		</div> <!-- dropdown-list -->
	</div> <!-- morph-dropdown-wrapper -->
</header>
An additional div.bg-layer has been created inside the div.morph-dropdown-wrapper and is used to create the dropdown morphing background.

Adding style

On small devices, the div.morph-dropdown-wrapper is hidden by default; when a user clicks the menu icon, the .nav-open class is added to the .cd-morph-dropdown to reveal the navigation.
.cd-morph-dropdown {
  position: relative;
}
.cd-morph-dropdown .morph-dropdown-wrapper {
  display: none;
  position: absolute;
  top: 60px;
  left: 0;
  width: 100%;
}
.cd-morph-dropdown.nav-open .morph-dropdown-wrapper {
  display: block;
}
On bigger devices (viewport width more than 1000px), the .dropdown-list and the li.dropdown elements are hidden by default.
@media only screen and (min-width: 1000px) {
	.cd-morph-dropdown .dropdown-list {
	    position: absolute;
	    top: 0;
	    left: 0;
	    visibility: hidden;
  	}
  	.cd-morph-dropdown .dropdown {
	    position: absolute;
	    left: 0;
	    top: 0;
	    opacity: 0;
	    visibility: hidden;
	    width: 100%;
	    transition: opacity .3s, visibility .3s;
  	}
}
When a user hovers over one of the elements inside the nav.main-nav, the .is-dropdown-visible class is added to the .cd-morph-dropdown and the .dropdown-list visibility is changed to visible. At this point, the dropdown wrapper is visible, but its content is still hidden. To reveal the content selected by the user, the .active class is added to the selected li.dropdown element (the one with an id equal to the data-content of the navigation item the user is hovering over).
@media only screen and (min-width: 1000px) {
	.cd-morph-dropdown .dropdown.active {
	    opacity: 1;
	    visibility: visible;
  	}
}
Since the li.dropdown elements have an absolute position, they do not actually take space inside their parent (div.dropdown-list), that means the div.dropdown-list width and height do not change according to the visible content. Since its overflow property is set to hidden (so that no content is visible outside the dropdown wrapper), we use JavaScript to change its height and width to make sure the selected dropdown content is always visible. To create the dropdown background, we use the div.bg-layer. It has an absolute position, width and height equal to 1px and opacity of zero. When the .is-dropdown-visible class is added to the .cd-morph-dropdown, its opacity is changed to one and it is scaled up (using JavaScrip) to fit the visible content area.
@media only screen and (min-width: 1000px) {
	.cd-morph-dropdown .bg-layer {
    	/* morph dropdown background */
	    position: absolute;
	    top: 0;
	    left: 0;
	    height: 1px;
	    width: 1px;
	    background: #FFFFFF;
	    opacity: 0;
	    transition: opacity .3s;
	    transform-origin: top left;
  	}
  	.cd-morph-dropdown.is-dropdown-visible .bg-layer {
	    opacity: 1;
	    transition: transform .3s, opacity .3s;
  	}
}
When the user moves from a navigation item to a different one, the scaleX and scaleY values of the div.bg-layer are changed (using JavaScript) to create the morph effect.

Events handling

To implement this navigation, we created a morphDropdown object and used the bindEvents method to attach event handlers to the proper elements.
function morphDropdown( element ) {
	this.element = element;
	this.mainNavigation = this.element.find('.main-nav');
	this.mainNavigationItems = this.mainNavigation.find('.has-dropdown');
	this.dropdownList = this.element.find('.dropdown-list');
	//...
	
	this.bindEvents();
}
The bindEvents method is used to detect the mouseenter/mouseleave events on the .has-dropdown and .dropdown elements.
morphDropdown.prototype.bindEvents = function() {
	var self = this;
	
	this.mainNavigationItems.mouseenter(function(event){
		//hover over one of the nav items -> show dropdown
		self.showDropdown($(this));
	}).mouseleave(function(){
		//if not hovering over a nav item or a dropdown -> hide dropdown
		if( self.mainNavigation.find('.has-dropdown:hover').length == 0 && self.element.find('.dropdown-list:hover').length == 0 ) self.hideDropdown();
	});
	
	//...
};
The showDropdown method takes care of changing the height, width and translateX values of the .dropdown-list and to scale up/down the .bg-layer element.
morphDropdown.prototype.showDropdown = function(item) {
	var selectedDropdown = this.dropdownList.find('#'+item.data('content')),
		selectedDropdownHeight = selectedDropdown.innerHeight(),
		selectedDropdownWidth = selectedDropdown.children('.content').innerWidth(),
		selectedDropdownLeft = item.offset().left + item.innerWidth()/2 - selectedDropdownWidth/2;

	//update dropdown and dropdown background position and size
	this.updateDropdown(selectedDropdown, parseInt(selectedDropdownHeight), selectedDropdownWidth, parseInt(selectedDropdownLeft));
	
	//add the .active class to the selected .dropdown and .is-dropdown-visible to the .cd-morph-dropdown 
	//...
};

morphDropdown.prototype.updateDropdown = function(dropdownItem, height, width, left) {
	this.dropdownList.css({
	    '-moz-transform': 'translateX(' + left + 'px)',
	    '-webkit-transform': 'translateX(' + left + 'px)',
		'-ms-transform': 'translateX(' + left + 'px)',
		'-o-transform': 'translateX(' + left + 'px)',
		'transform': 'translateX(' + left + 'px)',
		'width': width+'px',
		'height': height+'px'
	});

	this.dropdownBg.css({
		'-moz-transform': 'scaleX(' + width + ') scaleY(' + height + ')',
	    '-webkit-transform': 'scaleX(' + width + ') scaleY(' + height + ')',
		'-ms-transform': 'scaleX(' + width + ') scaleY(' + height + ')',
		'-o-transform': 'scaleX(' + width + ') scaleY(' + height + ')',
		'transform': 'scaleX(' + width + ') scaleY(' + height + ')'
	});
};
 ]]>
https://codyhouse.co/gem/stripe-navigation/feed/ 23
Auto-Hiding Navigation https://codyhouse.co/gem/auto-hiding-navigation/ https://codyhouse.co/gem/auto-hiding-navigation/#comments Wed, 13 Jul 2016 10:22:03 +0000 https://codyhouse.co/?post_type=gem&p=14754 Auto-hiding Navigation A simple navigation that auto-hides when the user scrolls down, and becomes visible when the user scrolls up. Auto-hiding navigations have been around for quite some time now, in particular on mobile devices. The idea behind this UX pattern is simple yet efficient: we want the navigation to be easy to reach all the time, so we stick it on top. However, we auto-hide it when the user scrolls down, to create more room for the content. If the user scrolls up, we interpret his behaviour as will to access the navigation, so we bring it back. Since we’ve been using this approach in several clients’ projects, we thought it would be handy to have a ready-to-use snippet here on CodyHouse. Images: Unsplash

Creating the structure

The HTML structure is composed of a header.cd-auto-hide-header element used to wrap the primary navigation (nav.cd-primary-nav) and a main.cd-main-content for the page main content.
<header class="cd-auto-hide-header">
	<div class="logo"><a href="#0"><img src="img/cd-logo.svg" alt="Logo"></a></div>

	<nav class="cd-primary-nav">
		<a href="#cd-navigation" class="nav-trigger">
			<span>
				<em aria-hidden="true"></em>
				Menu
			</span>
		</a> <!-- .nav-trigger -->

		<ul id="cd-navigation">
			<li><a href="#0">The team</a></li>
			<li><a href="#0">Our Services</a></li>
			<li><a href="#0">Our Projects</a></li>
			<li><a href="#0">Contact Us</a></li>
		</ul>
	</nav> <!-- .cd-primary-nav -->
</header> <!-- .cd-auto-hide-header -->

<main class="cd-main-content">
	<!-- content here -->
</main> <!-- .cd-main-content -->
If the page has a sub-navigation, an additional nav.cd-secondary-nav is inserted inside the header element:
<header class="cd-auto-hide-header">
	<div class="logo"><a href="#0"><img src="img/cd-logo.svg" alt="Logo"></a></div>

	<nav class="cd-primary-nav">
		<a href="#cd-navigation" class="nav-trigger">
			<span>
				<em aria-hidden="true"></em>
				Menu
			</span>
		</a> <!-- .nav-trigger -->

		<ul id="cd-navigation">
			<!-- links here -->
		</ul>
	</nav> <!-- .cd-primary-nav -->

	<nav class="cd-secondary-nav">
		<ul>
			<li><a href="#0">Intro</a></li>
			<!-- additional links here -->
		</ul>
	</nav> <!-- .cd-secondary-nav -->
</header> <!-- .cd-auto-hide-header -->

<main class="cd-main-content sub-nav">
	<!-- content here -->
</main> <!-- .cd-main-content -->
Finally, if the secondary navigation is below a hero block, a .cd-hero element is inserted right below the <header>, followed by the .cd-secondary-nav element:
<header class="cd-auto-hide-header">
	<div class="logo"><a href="#0"><img src="img/cd-logo.svg" alt="Logo"></a></div>

	<nav class="cd-primary-nav">
		<a href="#cd-navigation" class="nav-trigger">
			<span>
				<em aria-hidden="true"></em>
				Menu
			</span>
		</a> <!-- .nav-trigger -->

		<ul id="cd-navigation">
			<!-- links here -->
		</ul>
	</nav> <!-- .cd-primary-nav -->
</header> <!-- .cd-auto-hide-header -->

<section class="cd-hero">
	<!-- content here -->
</section> <!-- .cd-hero -->

<nav class="cd-secondary-nav">
	<ul>
		<!-- links here -->
	</ul>
</nav> <!-- .cd-secondary-nav -->

<main class="cd-main-content sub-nav-hero">
	<!-- content here -->
</main> <!-- .cd-main-content -->

Adding style

We used the .cd-auto-hide-header class to define the main style of the auto-hiding header. By default, the header has a fixed position and a top of zero; when the user starts scrolling down, the .is-hidden class is used to hide the header right above the viewport.
.cd-auto-hide-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 60px;
  transition: transform .5s;
}
.cd-auto-hide-header.is-hidden {
  transform: translateY(-100%);
}
In the style.css file (or style.scss if you are using Sass) the code you find right below the comment '1. Auto-Hiding Navigation - Simple' is the one you need to include in your project if you are using the 'Simple' auto-hiding navigation (primary navigation only). If your header has a sub-navigation (right below the primary navigation), then you need to include also the style you find under the '2. Auto-Hiding Navigation - with Sub Nav' comment. This second block of code is used to define the main style for the secondary navigation (using the .cd-secondary-nav class). Finally, if your secondary navigation is below a hero section, in addition to the previous two blocks you need to include also the code under the '3. Auto-Hiding Navigation - with Sub Nav + Hero Image' section. This is used to define two classes, .fixed and .slide-up, which are added to the secondary navigation while scrolling (the first one to make it 'sticky' and the second to slide it up when the primary navigation is hidden).
.cd-secondary-nav.fixed {
  position: fixed;
  top: 60px;
}
.cd-secondary-nav.slide-up {
  transform: translateY(-60px);
}
Finally, the 'Main content'  and 'Intro Section' blocks are used to define the basic style for the .cd-main-content and .cd-hero elements (mostly padding/margin to account for the fixed header).

Events handling

We use jQuery to listen for the scroll event on the window object.
var scrolling = false;
$(window).on('scroll', function(){
	if( !scrolling ) {
		scrolling = true;
		(!window.requestAnimationFrame)
			? setTimeout(autoHideHeader, 250)
			: requestAnimationFrame(autoHideHeader);
	}
});
The autoHideHeader() function takes care of hiding/revealing the navigation according to whether the user is scrolling up or down.]]>
https://codyhouse.co/gem/auto-hiding-navigation/feed/ 47
Vertical Fixed Navigation #2 https://codyhouse.co/gem/vertical-fixed-navigation-2/ https://codyhouse.co/gem/vertical-fixed-navigation-2/#comments Thu, 07 Jan 2016 12:25:27 +0000 https://codyhouse.co/?post_type=gem&p=6989 vertical-fixed-navigation-2 A smart vertical navigation, with round indicators that turn into labelled icons when the user interacts with them. Our first concept of vertical fixed navigation is one of our most popular resources. This time we tried to push this concept a little further. The basic idea behind putting round indicators on the side of a web page, is to give a hint to the user about the number of sections she/he can go through. We think of each dot as a content chapter, with its own title. Usually users have to hover over a dot to access the title. In an attempt to simplify this pattern, we decided to transform the dots when the user interacts with them, by scaling them up and showing an icon + label. Users don’t need to select a specific dot/item, but just move to the side, thus showing their willingness to access the navigation. Here is a quick preview of the final result (created using After Effects): v-nav-animation

Creating the structure

Our navigation is an unordered list wrapped in a nav.cd-vertical-nav. A button.cd-nav-trigger is used to open the navigation on small devices. Besides, a section.cd-section has been created for each navigation item.
<nav class="cd-vertical-nav">
	<ul>
		<li><a href="#section1" class="active"><span class="label">Intro</span></a></li>
		<li><a href="#section2"><span class="label">Events</span></a></li>
		<!-- additional navigation items here -->
	</ul>
</nav><!-- .cd-vertical-nav -->

<button class="cd-nav-trigger cd-image-replace">Open navigation<span aria-hidden="true"></span></button>

<section id="section1" class="cd-section">
	<div class="content-wrapper">
		<h1>Vertical Fixed Navigation #2</h1>
		<a href="#section2" class="cd-scroll-down cd-image-replace">scroll down</a>
	</div>
</section><!-- cd-section -->

<section id="section2" class="cd-section">
	<div class="content-wrapper">
		<!-- section content here -->
	</div>
</section><!-- cd-section -->

<!-- additional sections here -->

Adding style

On small devices (viewport width smaller than 800px), we set a position: fixed for the .cd-nav-trigger and <nav> elements and  placed them at the bottom-right corner of the page; we then scale down the navigation, using the bottom-right corner as transform origin. When user clicks on the .cd-nav-trigger element, we give the .open class to the navigation to change its scale value from 0 to 1 , with a CSS3 transition to achieve a smooth animation.
.cd-nav-trigger {
  display: block;
  position: fixed;
  z-index: 2;
  bottom: 30px;
  right: 5%;
}

.cd-vertical-nav {
  position: fixed;
  z-index: 1;
  right: 5%;
  bottom: 30px;
  transform: scale(0);
  transform-origin: right bottom;
  transition: transform 0.2s;
}
.cd-vertical-nav.open {
  transform: scale(1);
}
On bigger devices, we use Modernizr to detect touch and no-touch devices (using.touch and .no-touch classes). On touch devices, the lateral navigation items (labels and icons) are visible by default, while on no-touch devices they are shown when the user hovers over the lateral navigation. We set a fixed height and width for the <nav> element, and place it on the right side of the viewport. We use its ::before pseudo-element to create the navigation background; on no-touch devices only, the ::before element is, by default, translated to the right (outside the viewport) and is moved back to its original position when the user hovers over the navigation. The same happens for the span.label elements.
@media only screen and (min-width: 800px) {
  .cd-vertical-nav {
    right: 0;
    top: 0;
    height: 100vh;
    width: 90px;
  }
  .cd-vertical-nav::before {
    /* this is the navigation background */
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.8);
    transform: translateX(100%);
    transition: transform 0.4s;
  }
  .no-touch .cd-vertical-nav:hover::before, 
  .touch .cd-vertical-nav::before {
    transform: translateX(0);
  }
  .cd-vertical-nav .label {
    display: block;
    transform: translateX(100%);
    transition: transform 0.4s;
  }
  .no-touch .cd-vertical-nav:hover .label, 
  .touch .cd-vertical-nav .label {
    transform: translateX(0);
  }
}
To create the navigation item icons and dots, we use, respectively, the ::after and ::before pseudo-elements of the navigation anchor elements (<a>). On no-touch devices only, the ::after and ::before are scaled down by default, and then scaled back up when the user hovers over the navigation.
@media only screen and (min-width: 800px) {
  .cd-vertical-nav a {
    position: relative;
    padding: 3em 0 0;
    margin: 1.4em auto;
  }
  .cd-vertical-nav a::before, 
  .cd-vertical-nav a::after {
    /* used to create the filled circle and the background icon */
    content: '';
    position: absolute;
    left: 50%;
    transition: transform 0.4s 0s;
  }
  .cd-vertical-nav a::before {
    /* filled circle */
    top: 0;
    height: 32px;
    width: 32px;
    border-radius: 50%;
    background: #eaf2e3;
    transform: translateX(-50%) scale(0.25);
  }
  .cd-vertical-nav a::after {
    /* icon */
    top: 8px;
    height: 16px;
    width: 16px;
    background: url(../img/cd-nav-icons.svg) no-repeat;
    transform: translateX(-50%) scale(0);
  }
  .no-touch .cd-vertical-nav:hover a::before, 
  .no-touch .cd-vertical-nav:hover a::after, 
  .touch .cd-vertical-nav li:nth-of-type(n) a::before, 
  .touch .cd-vertical-nav li:nth-of-type(n) a::after {
    transform: translateX(-50%) scale(1);
  }
}
Now the tricky part: when the navigation dots are scaled down, they are too distant one from the other. We can reduce this distance translating them along the Y axis. Let's start from the central dots (in our case, the second and the third); we want to translate down the second one (so we have to use a positive translate value), while we want to translate up the third one (so we have to use a negative translate value). In our case we have:
.cd-vertical-nav li:nth-of-type(2) a::after {
    transform: translateX(-50%) translateY(1.5em) scale(0);
  }
  .cd-vertical-nav li:nth-of-type(2) a::before {
    transform: translateX(-50%) translateY(1.5em) scale(0.25);
  }
  .cd-vertical-nav li:nth-of-type(3) a::after {
    transform: translateX(-50%) translateY(-1.5em) scale(0);
  }
  .cd-vertical-nav li:nth-of-type(3) a::before {
    transform: translateX(-50%) translateY(-1.5em) scale(0.25);
  }
Then, the translate value for the first dot is gonna be three times the one of the second dot, and the same for the fourth one (three times the translate value of the third dot).
.cd-vertical-nav li:first-of-type a::after {
    transform: translateX(-50%) translateY(4.5em) scale(0);
  }
  .cd-vertical-nav li:first-of-type a::before {
    transform: translateX(-50%) translateY(4.5em) scale(0.25);
  }
  .cd-vertical-nav li:nth-of-type(4) a::after {
    transform: translateX(-50%) translateY(-4.5em) scale(0);
  }
  .cd-vertical-nav li:nth-of-type(4) a::before {
    transform: translateX(-50%) translateY(-4.5em) scale(0.25);
  }
If you have a different number of navigation items, you have to change these translate values accordingly. For example, if you have six items, starting again from the central dots (in this case, the third and the fourth), you can assign them a translateY value of 1.5 em/-1.5em; then to the second and the fifth a translateY value of 4.5em/-4.5em (3*1.5), and finally to the first and sixth a translateY value of 7.5em/-7.5em (5*1.5). If you have an odd number of items, let's say 5, you do not translate the central one (in this case the third one). You then assign a translateY value of 3em/-3em(2*1.5) to the second and the fourth dots, and finally a translateY value of 6em/-6em(4*1.5) to the first and fifth dots.

Events handling

When user scrolls through the sections, the updateSections() function evaluates which section is currently being viewed and assigns the .active class to the corresponding navigation item. Besides, we listen to the click event on the button.cd-nav-trigger to open/close the navigation on small devices.]]>
https://codyhouse.co/gem/vertical-fixed-navigation-2/feed/ 36
Stretchy Navigation https://codyhouse.co/gem/stretchy-navigation/ https://codyhouse.co/gem/stretchy-navigation/#comments Wed, 18 Nov 2015 11:39:08 +0000 http://codyhouse.co/?post_type=gem&p=4546 stretchy-navigation A rounded navigation trigger that stretches on click/tap to reveal the navigation items. While surfing some Dribbble shots, we came across this nice shopping list concept by Hila Peleg, which inspired today’s resource. We decided to apply a similar idea to a stretching navigation, and create 3 different user cases where this snippet would be useful: 1) fixed navigation, 2) add content button and 3) edit content button. Icons: Nucleoapp.com

Creating the structure

The HTML structure is pretty basic: a nav.cd-stretchy-nav is used to wrap an unordered list (containing the navigation items) and an a.cd-nav-trigger (for the menu icon). An additional span.stretchy-nav-bg element is used to create the stretchy background.
<nav class="cd-stretchy-nav">
	<a class="cd-nav-trigger" href="#0">
		Menu
		<span aria-hidden="true"></span>
	</a>

	<ul>
		<li><a href="#0" class="active"><span>Home</span></a></li>
		<li><a href="#0"><span>Portfolio</span></a></li>
		<!-- other list items here -->
	</ul>

	<span aria-hidden="true" class="stretchy-nav-bg"></span>
</nav>

Adding style

We created the .cd-stretchy-nav class to define the main style for the stretchy navigation. We then used two additional classes, .add-content and .edit-content, to customise the toolbars for adding and editing content respectively. The basic idea of the animation is: we assign to the span.stretchy-nav-bg a fixed height and width (the same of the a.cd-nav-trigger); when the navigation is open, we use the .nav-is-visible class to animate its height (or width, for the .add-content toolbar) to create the stretching effect while revealing the navigation list items.
.cd-stretchy-nav {
  position: fixed;
  z-index: 2;
  top: 40px;
  right: 5%;
}
.cd-stretchy-nav .stretchy-nav-bg {
  /* this is the stretching navigation background */
  position: absolute;
  z-index: 1;
  top: 0;
  right: 0;
  width: 60px;
  height: 60px;
  border-radius: 30px;
  background: #9acd91;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
  transition: height 0.2s, box-shadow 0.2s;
}
.cd-stretchy-nav.nav-is-visible .stretchy-nav-bg {
  height: 100%;
  box-shadow: 0 6px 30px rgba(0, 0, 0, 0.2);
}
For the navigation items, we defined 2 different CSS Animations: the scaleIn for the item icons and the slideIn for the item labels; the animation-delay property is then used to animate different children at different moments.
.cd-stretchy-nav ul {
  position: relative;
  z-index: 2;
  visibility: hidden;
  transition: visibility 0.3s;
}
.cd-stretchy-nav ul a {
  position: relative;
}
.cd-stretchy-nav ul a::after {
  /* navigation item icons */
  content: '';
  position: absolute;
  height: 16px;
  width: 16px;
  transform: translateY(-50%) scale(0);
  opacity: .6;
  background: url(../img/cd-sprite-1.svg) no-repeat 0 0;
}
.cd-stretchy-nav ul span {
  /* navigation item labels */
  display: block;
  opacity: 0;
  transform: translateX(-25px);
}

.cd-stretchy-nav.nav-is-visible ul {
  visibility: visible;
}
.cd-stretchy-nav.nav-is-visible ul a::after {
  /* navigation item icons */
  transform: translateY(-50%) scale(1);
  animation: scaleIn 0.15s backwards;
}
.cd-stretchy-nav.nav-is-visible ul span {
  opacity: 1;
  transform: translateX(0);
  animation: slideIn 0.15s backwards;
}

.cd-stretchy-nav.nav-is-visible ul li:first-of-type a::after,
.cd-stretchy-nav.nav-is-visible ul li:first-of-type span {
  animation-delay: 0.05s;
}
/* animation delay for other children here ...*/

@keyframes scaleIn {
  from {
    transform: translateY(-50%) scale(0);
  }
  to {
    transform: translateY(-50%) scale(1);
  }
}

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateX(-25px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}
For the toolbars: when the navigation is open we only display the item icons (using the scaleIn animation), while the item labels are shown when hovering over the navigation (using CSS Transitions). For the editing toolbar, for example, we have:
.cd-stretchy-nav.edit-content ul span {
  position: absolute;
  top: 0;
  right: 35px;
  height: 30px;
  line-height: 30px;
  opacity: 0;
  visibility: hidden;
  background-color: rgba(0, 0, 0, 0.55);
  transition: opacity 0.2s, visibility 0.2s;
}
.cd-stretchy-nav.edit-content ul span::after {
  /* triangle below the tooltip */
  content: '';
  position: absolute;
  left: 100%;
  top: 50%;
  bottom: auto;
  transform: translateY(-50%);
  height: 0;
  width: 0;
  border: 4px solid transparent;
  border-left-color: rgba(0, 0, 0, 0.55);
}

.no-touch .cd-stretchy-nav.edit-content.nav-is-visible ul a:hover span {
  opacity: 1;
  visibility: visible;
}

Events handling

We used jQuery to listen to the click event on the a.cd-nav-trigger, and add/remove the .nav-is-visible class from the nav.cd-stretchy-nav.]]>
https://codyhouse.co/gem/stretchy-navigation/feed/ 29
Responsive Sidebar Navigation https://codyhouse.co/gem/responsive-sidebar-navigation/ https://codyhouse.co/gem/responsive-sidebar-navigation/#comments Mon, 14 Sep 2015 10:58:23 +0000 http://codyhouse.co/?post_type=gem&p=881 responsive-sidebar-navigation An easy-to-integrate side, vertical navigation, ideal for dashboards and admin areas. Building responsive navigations for mega sites is never an easy task. If you’re working on an admin panel, chances are you’ll need to design and develop a vertical menu, with plenty of sub-categories. That’s why we decided to share today's snippet! Our Sidebar navigation can make your life easier by providing a starting, simple template for your next project ;) Icons: Nucleo library.

Creating the structure

The HTML structure is composed by 2 main elements: a <header> element, containing the website logo, the search form, the navigation trigger (.cd-nav-trigger - mobile version only) and the top navigation, and a <main> element containing the page main content (div.content-wrapper) and the sidebar navigation (nav.cd-side-nav).
<header class="cd-main-header">
	<a href="#0" class="cd-logo"><img src="img/cd-logo.svg" alt="Logo"></a>
	
	<div class="cd-search">
		<form action="#0">
			<input type="search" placeholder="Search...">
		</form>
	</div> <!-- cd-search -->

	<a href="#0" class="cd-nav-trigger">Menu<span></span></a>

	<nav class="cd-nav">
		<ul class="cd-top-nav">
			<li><a href="#0">Tour</a></li>
			<li><a href="#0">Support</a></li>
			<li class="has-children account">
				<a href="#0">
					<img src="img/cd-avatar.png" alt="avatar">
					Account
				</a>

				<ul>
					<li><a href="#0">My Account</a></li>
					<!-- other list items here -->
				</ul>
			</li>
		</ul>
	</nav>
</header> <!-- .cd-main-header -->

<main class="cd-main-content">
	<nav class="cd-side-nav">
		<ul>
			<li class="cd-label">Main</li>
			<li class="has-children overview">
				<a href="#0">Overview</a>
				
				<ul>
					<li><a href="#0">All Data</a></li>
					<!-- other list items here -->
				</ul>
			</li>
			<li class="has-children notifications active">
				<a href="#0">Notifications<span class="count">3</span></a>
				
				<ul>
					<li><a href="#0">All Notifications</a></li>
					<!-- other list items here -->
				</ul>
			</li>

			<!-- other list items here -->
		</ul>

		<!-- other unordered lists here -->
	</nav>

	<div class="content-wrapper">
		<!-- main content here -->
	</div> <!-- .content-wrapper -->
</main> <!-- .cd-main-content -->
In the starting HTML structure, the .cd-search and .cd-top-nav elements are inside the <header>, while on mobile devices they are moved inside the .cd-side-nav element (more in the Events Handling section).

Adding style

We created 3 different sidebar configurations, according to the screen size. On small devices, the sidebar has a 100% width, is in absolute position and hidden by default (visibility: hidden). When the user clicks/taps the .cd-nav-trigger, the sidebar visibility is changed to visible (using the .nav-is-visible class).
.cd-side-nav {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.2s 0s, visibility 0s 0.2s;
}
.cd-side-nav.nav-is-visible {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.2s 0s, visibility 0s 0s;
}
On medium size devices (viewport width more than 768px), a minified version of the sidebar is visible by default: it is in relative position, has a fixed width (110px)  and a float: left so that it is on the left side of the <main> element.
@media only screen and (min-width: 768px) {
  .cd-side-nav {
    position: relative;
    float: left;
    width: 110px;
    /* reset style */
    visibility: visible;
    opacity: 1;
  }
}

@media only screen and (min-width: 768px) { 
 .cd-main-content .content-wrapper { 
 margin-left: 110px; 
 } 
} 
On bigger devices (viewport width more than 1170px), the expanded version of the sidebar is shown.

Events handling

In the starting HTML structure, the .cd-search and .cd-top-nav elements are inside the <header>. On small devices (viewport width less than 1170px), we move these elements inside the .cd-side-nav navigation.
var resizing = false;
moveNavigation();
$(window).on('resize', function(){
 if( !resizing ) window.requestAnimationFrame(moveNavigation);
});

function moveNavigation(){
 var mq = checkMQ(); //this function returns mobile,tablet or desktop 
 
 if ( mq == 'mobile' && topNavigation.parents('.cd-side-nav').length == 0 ) { //topNavigation = $('.cd-top-nav')
 detachElements();
 topNavigation.appendTo(sidebar); //sidebar = $('.cd-side-nav')
 searchForm.prependTo(sidebar);
 } else if ( ( mq == 'tablet' || mq == 'desktop') && topNavigation.parents('.cd-side-nav').length > 0 ) {
 detachElements();
 searchForm.insertAfter(header.find('.cd-logo')); //header = $('.cd-main-header')
 topNavigation.appendTo(header.find('.cd-nav'));
 }
 resizing = false;
}

function detachElements() {
 topNavigation.detach();//topNavigation = $('.cd-top-nav')
 searchForm.detach();//searchForm = $('.cd-search')
}
Besides, we integrated the jQuery-menu-aim plugin to differentiate between users trying hover over a sidebar item and  user trying to navigate into a submenu’s contents (desktop version only).]]>
https://codyhouse.co/gem/responsive-sidebar-navigation/feed/ 69
Mega Dropdown https://codyhouse.co/gem/mega-dropdown/ https://codyhouse.co/gem/mega-dropdown/#comments Wed, 13 May 2015 13:42:11 +0000 http://codyhouse.co/?post_type=gem&p=748 mega dropdown A responsive and easy to customise mega-dropdown component. One of the most challenging part when you’re working on a web projects with lots of content is to make it easy for a user to navigate through this content. One example we can all think of is Amazon: infinite categories, each one with its own sub-categories…that’s why they currently provide an easy-to-access navigation, in the form of a mega-dropdown element on the top-right corner of the page. We’ve been working on a similar concept, a responsive mega dropdown component with sub-categories. Here is a quick animation we put together to show you our mobile vs desktop approach: dropdown animation As you can notice from the demo, our dropdown is activated with a tap/click. We could have achieved the same thing using a :hover state instead, no need for js (we do provide a :hover fallback in case javascript is disabled). However these decisions should be based on what we thing is the best user experience. Users generally expect to click to access new content, while :hover effects mostly detect a “potential action”. This is why we preferred click over :hover state. In case you disagree, switching from one approach to the other is a piece of cake ;) Icons: Nucleo Library

Creating the structure

The HTML is structured in 2 main elements: the <header>, containing the dropdown (.cd-dropdown-wrapper), and the <main> for all the main content. The .cd-dropdown-wrapper containes a .cd-dropdown-trigger, to trigger the dropdown, and a .cd-dropdown, which is composed by nested unordered lists.
<header>
	<div class="cd-dropdown-wrapper">
		<a class="cd-dropdown-trigger" href="#0">Dropdown</a>
		<nav class="cd-dropdown">
			<h2>Title</h2>
			<a href="#0" class="cd-close">Close</a>
			<ul class="cd-dropdown-content">
				<li>
					<form class="cd-search">
						<input type="search" placeholder="Search...">
					</form>
				</li>
				<li class="has-children">
					<a href="#0">Clothing</a>

					<ul class="cd-secondary-dropdown is-hidden">
						<li class="go-back"><a href="#0">Menu</a></li>
						<li class="see-all"><a href="#0">All Clothing</a></li>
						<li class="has-children">
							<a href="#0">Accessories</a>

							<ul class="is-hidden">
								<li class="go-back"><a href="#0">Clothing</a></li>
								<li class="see-all"><a href="#0">All Accessories</a></li>
								<li class="has-children">
									<a href="#0">Beanies</a>

									<ul class="is-hidden">
										<li class="go-back"><a href="#0">Accessories</a></li>
										<li class="see-all"><a href="#0">All Benies</a></li>
										<li><a href="#0">Caps &amp; Hats</a></li>
										<!-- other list items here -->
									</ul>
								</li>
								<li class="has-children">
									<a href="#0">Caps &amp; Hats</a>

									<ul class="is-hidden">
										<li class="go-back"><a href="#0">Accessories</a></li>
										<li class="see-all"><a href="#0">All Caps &amp; Hats</a></li>
										<li><a href="#0">Beanies</a></li>
										<!-- other list items here -->
									</ul>
								</li>
								<li><a href="#0">Glasses</a></li>
								<!-- other list items here -->
							</ul>
						</li>

						<li class="has-children">
							<!-- other list items here -->
						</li>

						<li class="has-children">
							<!-- other list items here -->
						</li>

						<li class="has-children">
							<!-- other list items here -->
						</li>
					</ul> <!-- .cd-secondary-dropdown -->
				</li> <!-- .has-children -->

				<li class="has-children">
					<!-- other list items here -->
				</li> <!-- .has-children -->

				<li class="has-children">
					<!-- other list items here -->
				</li> <!-- .has-children -->

				<li class="cd-divider">Divider</li>

				<li><a href="#0">Page 1</a></li>
				<!-- other list items here -->

			</ul> <!-- .cd-dropdown-content -->
		</nav> <!-- .cd-dropdown -->
	</div> <!-- .cd-dropdown-wrapper -->
</header>

<main class="cd-main-content">
	<!-- your content here -->
</main>

Adding style

For mobile devices, the basic idea was to let the user focus totally on the dropdown content, once it has been activated. This is why we assigned a fixed position to the dropdown, and set its width and height to 100%. By default, it is hidden right above the viewport (translateY(-100%)). When the user clicks the trigger element, the .dropdown-is-active class is added to the dropdown which is translated back into the viewport.
.cd-dropdown {
  position: fixed;
  z-index: 1;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transform: translateY(-100%);
  transition: transform 0.5s;
}
.cd-dropdown.dropdown-is-active {
  transform: translateY(0);
}
When user selects a new sublevel in the dropdown, the visible items are translated to the left outside the viewport (using the .move-out class),  while the new items slide back into the viewport (removing the class .is-hidden class from their <ul> parent element).
.cd-dropdown-content.is-hidden, .cd-dropdown-content ul.is-hidden {
  /* push the secondary dropdown items to the right */
  transform: translateX(100%);
}

.cd-dropdown-content.move-out > li > a, .cd-dropdown-content ul.move-out > li > a {
  /* push the dropdown items to the left when secondary dropdown slides in */
  transform: translateX(-100%);
}
On bigger devices (viewport width bigger than 1024px), instead, there's enough space to place content side by side, with no need to replace the visible content.
@media only screen and (min-width: 1024px) {
  .cd-dropdown {
    position: absolute;
    top: 100%;
    /* reset style*/
    height: auto;
    width: auto;
    opacity: 0;
    visibility: hidden;
    transform: translateY(30px);
    transition: opacity 0.3s 0s, visibility 0s 0.3s, transform 0.3s 0s;
  }
  .cd-dropdown.dropdown-is-active {
    visibility: visible;
    opacity: 1;
    transform: translateY(0);
    transition: opacity 0.3s 0s, visibility 0.3s 0s, transform 0.3s 0s;
  }

  .cd-dropdown-content {
    /* reset mobile style */
    position: static;
    height: auto;
    width: 280px;
  }
  .cd-dropdown-content .cd-secondary-dropdown, .cd-dropdown-content .cd-dropdown-gallery, .cd-dropdown-content .cd-dropdown-icons {
    transform: translateX(0);
    left: 100%;
    height: auto;
  }
  .cd-dropdown-content .cd-secondary-dropdown.is-hidden, .cd-dropdown-content .cd-dropdown-gallery.is-hidden, .cd-dropdown-content .cd-dropdown-icons.is-hidden {
    /* reset mobile style */
    transform: translateX(0);
  }
  .cd-dropdown-content > .has-children > ul {
    visibility: hidden;
  }
  .cd-dropdown-content > .has-children:hover > ul {
    /* when hover over .cd-dropdown-content items - show subnavigation */
    visibility: visible;
  }
  .cd-dropdown-content > .has-children:hover > .cd-secondary-dropdown > li > ul {
    /* if .cd-secondary-dropdown is visible - show also subnavigation */
    visibility: visible;
  }
}

Events handling

We didn’t do a lot in jQuery, apart from listening to the click event on specific elements (e.g. .cd-dropdown-trigger, .go-back) and adding/removing classes accordingly.]]>
https://codyhouse.co/gem/mega-dropdown/feed/ 125
3D Bold Navigation https://codyhouse.co/gem/3d-bold-navigation/ https://codyhouse.co/gem/3d-bold-navigation/#comments Fri, 10 Apr 2015 12:27:57 +0000 http://codyhouse.co/?post_type=gem&p=667 3d-bold-navigation A bold navigation that slides in when active, replacing the current content in a 3D space. Today’s resource is a strong approach to showing a website navigation. Bear in mind, though, it doesn’t have to be the “main” navigation. You could have, for example, a product gallery and you’d like to create a smooth transition while switching from one product category to the other. To increase the focus on the menu, we pushed the main content along the z-axis (by using CSS transformations we actually scale down the content size, we don’t use 3D translations, but the result is the same). The interesting bit: when you select a new category, we switch the content in the background, then move it back to the original position, hiding the navigation. Now let’s dive into the code! The icons used in the demo are from our Nucleo icons application.

Creating the structure

The HTML is structured in 3 main elements: a .cd-nav-trigger used to create the menu icon, a .cd-section element containing the page main content and a .cd-nav-container for the main navigation.
<a href="#cd-nav" class="cd-nav-trigger">
	Menu<span><!-- used to create the menu icon --></span>
</a> <!-- .cd-nav-trigger -->

<main>
	<section class="cd-section index cd-selected">
		<header>
			<div class="cd-title">
				<h2><!--  title here  --></h2>
				<p><!--  brief description here  --></p>
			</div> <!-- .cd-title -->
		</header>

		<div class="cd-content">
			<!-- your content here -->
		</div>
	</section> <!-- .cd-section -->
</main>

<nav class="cd-nav-container" id="cd-nav">
	<header>
		<h3>Navigation</h3>
		<a href="#0" class="cd-close-nav">Close</a>
	</header>

	<ul class="cd-nav">
		<li class="cd-selected" data-menu="index">
			<a href="index.html">
				<span>
					<!-- svg icon here -->
				</span>

				<em><!--  title here  --></em>
			</a>
		</li>

		<li data-menu="projects">
			<!-- .... -->
		</li>

		<!-- other list items here -->
	</ul> <!-- .cd-3d-nav -->
</nav>
An additional div.cd-overlay has been used to create a shadow layer, visible only when navigation is active.

Adding style

To realise our animation, we used CSS3 Transformations applied to the <main> and <nav> elements. By default, the navigation has a position fixed and is translated to the right, outside the viewport (translateX(100%)). When user clicks the menu icon, the class .is-visible is added to the <nav> element which is moved back into the viewport (translateX(0)), while the .scale-down class is added to the <main> element to scale it down (scale(.9)). And of course we have used CSS3 Transitions to achieve a smooth animation!
.cd-nav-container {
  position: fixed;
  top: 0;
  right: 0;
  width: 80%;
  height: 100%;
  transform: translateX(100%);
  transition: transform 0.4s;
}
.cd-nav-container.is-visible {
  transform: translateX(0);
}

main {
  transition: transform 0.4s;
}
main.scale-down {
  transform: scale(0.9);
}
When user selects an item from the navigation, a new .cd-section element is created and inserted in the DOM (more details in the 'Events handling' section). The .cd-selected class is then assigned to this new inserted .cd-section element, while it is removed from the old .cd-section (the content originally visible in the page). This way the new section element (which is initially translated to the right, outside the viewport) is moved back (translateX(0)), covering the old content (z-index: 2). One note: during this animation you don't see the old section moving to the right (translateX(100%)) because we set a delay for the .cd-section transition on transformations (it will move after .4s).
.cd-section {
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  overflow-y: auto;
  transform: translateX(100%);
  transition: transform 0s 0.4s;
}
.cd-section.cd-selected {
  position: relative;
  z-index: 2;
  transform: translateX(0);
  transition: transform 0.4s 0s;
}

Events handling

The index.html file contains only the 'Intro' content. A different html file has been created for each section (projects.html, careers.html, ..) with exactly the same structure, but with different .cd-section content. When user selects a new item from the navigation, a new <section> element is created and inserted in the DOM (loadNewContent function). The load() function is then used to load the specific section content (we used a data-menu attribute assigned to the navigation list item to determine the file content to be loaded). Once the new html content has been inserted, we assign the .cd-selected class to the new section and close the navigation.
$('.cd-nav li').on('click', function(event){
	event.preventDefault();
	var target = $(this),
		//detect which section user has chosen
		sectionTarget = target.data('menu');
	if( !target.hasClass('cd-selected') ) {
		//if user has selected a section different from the one alredy visible
		//update the navigation -> assign the .cd-selected class to the selected item
		target.addClass('cd-selected').siblings('.cd-selected').removeClass('cd-selected');
		//load the new section
		loadNewContent(sectionTarget);
	} else {
		// otherwise close navigation
		toggleNav(false);
	}
});
function loadNewContent(newSection) {
	//create a new section element and insert it into the DOM
	var section = $('<section class="cd-section '+newSection+'"></section>').appendTo($('main'));
	//load the new content from the proper html file
	section.load(newSection+'.html .cd-section > *', function(event){
		//add the .cd-selected to the new section element -> it will cover the old one
		section.addClass('cd-selected').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
			//close navigation
			toggleNav(false);
		});
		section.prev('.cd-selected').removeClass('cd-selected');
	});

	$('main').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
		//once the navigation is closed, remove the old section from the DOM
		section.prev('.cd-section').remove();
	});

	if( $('.no-csstransitions').length > 0 ) {
		//detect if browser supports transitions
		toggleNav(false);
		section.prev('.cd-section').remove();
	}
}
One note: we implemented a simple load() function to upload the new html content, but you may wanna replace it with a proper $.ajax call in order to proper handle errors, beforeSend request etc. according to your project.]]>
https://codyhouse.co/gem/3d-bold-navigation/feed/ 45
Secondary sliding navigation https://codyhouse.co/gem/secondary-sliding-navigation/ https://codyhouse.co/gem/secondary-sliding-navigation/#comments Thu, 26 Feb 2015 12:20:58 +0000 http://codyhouse.co/?post_type=gem&p=597 secondary-sliding-navigation A bold, secondary menu that slides over the main navigation. Today’s resource is a simple, handy snippet: a secondary navigation that slides down, replacing the main navigation links. This approach can be an alternative to a standard dropdown menu, in particular if you want to emphasise more the sub navigation. Besides you can easily customize the snippet and use the slide in panel for a search box instead, or a login form - just to give you a couple of ideas.

Creating the structure

The HTML is structured in 2 main elements: an <header> wrapping the main navigation, and a <main> containing the page content. The main navigation is composed of 2 nested unordered lists, semantically wrapped in a <nav> element.
<header>
	<div class="cd-logo"><a href="#0"><img src="img/cd-logo.svg" alt="Logo"></a></div>

	<nav class="cd-main-nav-wrapper">
		<ul class="cd-main-nav">
			<li><a href="#0">About</a></li>
			<!-- other list items here -->
			<li>
				<a href="#0" class="cd-subnav-trigger"><span>Categories</span></a>

				<ul>
					<li class="go-back"><a href="#0">Menu</a></li>
					<li><a href="#0">Category 1</a></li>
					<!-- other list items here -->
				</ul>
			</li>
		</ul>
	</nav> 
	
	<a href="#0" class="cd-nav-trigger">Menu<span></span></a>
</header>

<main class="cd-main-content">
	<!-- main content here -->
</main>

Adding style

On small devices, the main navigation is on the right side, hidden by default; when user clicks the menu icon, the <main> and <header> elements translate to the left (nav-is-visible class is applied) to reveal the navigation. When user clicks the .cd-subnav-trigger, the main navigation is pushed to the left and replaced by the secondary navigation.
header.nav-is-visible {
  transform: translateX(-260px);
}
.cd-main-content.nav-is-visible {
  transform: translateX(-260px);
}
.cd-main-nav {
  position: fixed;
  top: 0;
  right: 0;
  width: 260px;
  visibility: hidden;
}
.cd-main-nav.nav-is-visible {
  visibility: visible;
}
.cd-main-nav li ul {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  transform: translateX(260px);
}
.cd-main-nav.moves-out > li > a {
  /* push the navigation items to the left - and lower down opacity - when secondary nav slides in */
  transform: translateX(-100%);
  opacity: 0;
}
.cd-main-nav.moves-out > li > ul {
  /* reveal secondary nav */
  transform: translateX(0);
}
On desktop devices (viewport width more than 1024px), the secondary navigation is placed on top of the header (outside the viewport) and slides in covering the main navigation. We assigned a higher z-index to the .cd-logo and .cd-subnav-trigger so that they remain visible after the sub navigation has slided in. Besides, we assigned the sub navigation the same padding as the .cd-main-nav  and inserted a .placeholder element as last list item occupying the same space of the .cd-subnav-trigger: this way we make sure the sub navigation list items don't cover both the logo and the .cd-subnav-trigger.
@media only screen and (min-width: 1024px) {
  .cd-main-nav {
    height: 80px;
    /* padding left = logo size + logo left position*/
    padding: 0 5% 0 calc(5% + 124px);
    text-align: right;
  }
  .cd-main-nav li ul {
    height: 80px;
    background-color: #7e4d7e;
    /* padding left = logo size + logo left position*/
    padding: 0 5% 0 calc(5% + 124px);
    transform: translateY(-80px);
    transition: transform 0.3s 0.2s;
  }
  .cd-main-nav li ul li {
    opacity: 0;
    transform: translateY(-20px);
    transition: transform 0.3s 0s, opacity 0.3s 0s;
  }
  .cd-main-nav .placeholder {
    /* never visible or clickable- it is used to take up the same space as the .cd-subnav-trigger */
    display: block;
    visibility: hidden;
    opacity: 0;
    pointer-event: none;
  }
  .cd-main-nav.moves-out > li > ul {
    transition: transform 0.3s;
    transform: translateY(0);
  }
  .cd-main-nav.moves-out > li ul li {
    opacity: 1;
    transform: translateY(0);
    transition: transform 0.3s 0.2s, opacity 0.3s 0.2s;
  }
}

Events handling

We used jQuery to add/remove classes according to specific events. The only important thing to note is that in the starting HTML structure the navigation is inside the <header>. On mobile, we wanted the navigation to be on the side, hidden by default, and it was easier for us to have it outside the header. So we use jQuery to move the navigation outside the header on small devices.]]>
https://codyhouse.co/gem/secondary-sliding-navigation/feed/ 63