Advertisement

How to Build a Shrinking Fixed Top Bar With Foundation

by
Student iconAre you a student? Get a yearly Tuts+ subscription for $45 →

A very common trend these days is the use of a fixed navigation, which shrinks to become less intrusive as the user scrolls down the page. In this tutorial, I'm going to show you how you can achieve this by using ZURBs Foundation Top Bar, some custom sass and jQuery. To top it off we'll add a couple of media queries to make our menu responsive. Let's get started!

Requirements

You'll need a couple of things to get a good grip on this tutorial:

  • Basic understanding of the Foundation Topbar
  • Basic understanding of Foundation and The Grid System
  • Knowledge of working with Sass and Compass
  • A little experience in the use of jQuery for some events handling

Getting Started

First, we're going to set up our working environment. If you don't know how to do this using Compass and Sass, then check out the "Getting Started" section of Build a Top Bar Off-Canvas Navigation With Foundation 5.

Create your new Foundation project and use compass watch to compile your project. We'll create our own style.scss in the scss folder for our customizations and some general styling. With this set up, we'll dive into the general HTML structure, let's go!

Setting up the HTML Structure

Step 1: General Markup

Having started a new Foundation project, go to the index.html file and start by removing all the content in between the body tags, except for the scripts right before the closing body tag. Then add the following line to your <head>, to import our style.css.

<link rel="stylesheet" href="stylesheets/style.css" />

Next, we're going to add some markup, like the header, a main section and the footer, and we'll also add some dummy content to give our page some filling.

<!-- HEADER SECTION -->
<div class="contain-to-grid header-section">

	<!-- TOPBAR SECTION -->
	<nav class="top-bar important-class" data-topbar>

	</nav> <!-- END TOPBAR SECTION -->
</div> <!-- END HEADER SECTION

<!-- CONTENT FILL WHEN SCROLL = 0 -->
<div class="header-fill"></div>

<!-- CONTENT SECTION -->
<div class="row content-section">
	<div class="main-content">
		<div class="small-12 medium-12 large-12 columns">
			<h1>Fancy Foundation Top Bar</h1>
			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Et, fugiat, explicabo architecto at praesentium modi soluta alias veniam voluptate magnam obcaecati facilis cumque voluptatum impedit eius reiciendis ad minus odio similique sequi molestiae voluptatem commodi aliquam assumenda numquam doloribus libero tempora vitae sed animi. Ratione, quasi iste fugiat debitis molestiae doloremque consequuntur hic delectus molestias repudiandae reprehenderit rerum reiciendis enim aperiam cum ut adipisci veritatis soluta illo praesentium consequatur voluptate possimus dolorem et officiis perspiciatis commodi quae eligendi alias culpa atque ducimus eum odit accusamus ad labore quod necessitatibus. Officiis, ducimus, voluptate doloremque nihil rerum consequuntur obcaecati fugiat cum veritatis quidem qui nulla distinctio laborum perspiciatis quia tempora eveniet tempore aliquam pariatur aliquid quibusdam aspernatur quis maiores minus quas culpa reprehenderit id iure optio asperiores? Excepturi, deleniti, at, expedita quod animi harum est sit iste distinctio consequuntur mollitia corporis soluta. Quos, asperiores voluptas totam nesciunt atque iusto commodi. Autem, animi eius odio commodi vitae nihil possimus neque minima obcaecati aspernatur voluptate dolorem consequuntur illo vel iste deserunt tempore eaque maxime cum ratione rem odit officia tempora ut recusandae saepe maiores quae repellat debitis atque est praesentium numquam mollitia dolor ipsum modi fuga veniam error perspiciatis quas provident optio similique iure.</p>
			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Et, fugiat, explicabo architecto at praesentium modi soluta alias veniam voluptate magnam obcaecati facilis cumque voluptatum impedit eius reiciendis ad minus odio similique sequi molestiae voluptatem commodi aliquam assumenda numquam doloribus libero tempora vitae sed animi. Ratione, quasi iste fugiat debitis molestiae doloremque consequuntur hic delectus molestias repudiandae reprehenderit rerum reiciendis enim aperiam cum ut adipisci veritatis soluta illo praesentium consequatur voluptate possimus dolorem et officiis perspiciatis commodi quae eligendi alias culpa atque ducimus eum odit accusamus ad labore quod necessitatibus. Officiis, ducimus, voluptate doloremque nihil rerum consequuntur obcaecati fugiat cum veritatis quidem qui nulla distinctio laborum perspiciatis quia tempora eveniet tempore aliquam pariatur aliquid quibusdam aspernatur quis maiores minus quas culpa reprehenderit id iure optio asperiores? Excepturi, deleniti, at, expedita quod animi harum est sit iste distinctio consequuntur mollitia corporis soluta. Quos, asperiores voluptas totam nesciunt atque iusto commodi. Autem, animi eius odio commodi vitae nihil possimus neque minima obcaecati aspernatur voluptate dolorem consequuntur illo vel iste deserunt tempore eaque maxime cum ratione rem odit officia tempora ut recusandae saepe maiores quae repellat debitis atque est praesentium numquam mollitia dolor ipsum modi fuga veniam error perspiciatis quas provident optio similique iure.</p>
			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Et, fugiat, explicabo architecto at praesentium modi soluta alias veniam voluptate magnam obcaecati facilis cumque voluptatum impedit eius reiciendis ad minus odio similique sequi molestiae voluptatem commodi aliquam assumenda numquam doloribus libero tempora vitae sed animi. Ratione, quasi iste fugiat debitis molestiae doloremque consequuntur hic delectus molestias repudiandae reprehenderit rerum reiciendis enim aperiam cum ut adipisci veritatis soluta illo praesentium consequatur voluptate possimus dolorem et officiis perspiciatis commodi quae eligendi alias culpa atque ducimus eum odit accusamus ad labore quod necessitatibus. Officiis, ducimus, voluptate doloremque nihil rerum consequuntur obcaecati fugiat cum veritatis quidem qui nulla distinctio laborum perspiciatis quia tempora eveniet tempore aliquam pariatur aliquid quibusdam aspernatur quis maiores minus quas culpa reprehenderit id iure optio asperiores? Excepturi, deleniti, at, expedita quod animi harum est sit iste distinctio consequuntur mollitia corporis soluta. Quos, asperiores voluptas totam nesciunt atque iusto commodi. Autem, animi eius odio commodi vitae nihil possimus neque minima obcaecati aspernatur voluptate dolorem consequuntur illo vel iste deserunt tempore eaque maxime cum ratione rem odit officia tempora ut recusandae saepe maiores quae repellat debitis atque est praesentium numquam mollitia dolor ipsum modi fuga veniam error perspiciatis quas provident optio similique iure.</p>
			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Et, fugiat, explicabo architecto at praesentium modi soluta alias veniam voluptate magnam obcaecati facilis cumque voluptatum impedit eius reiciendis ad minus odio similique sequi molestiae voluptatem commodi aliquam assumenda numquam doloribus libero tempora vitae sed animi. Ratione, quasi iste fugiat debitis molestiae doloremque consequuntur hic delectus molestias repudiandae reprehenderit rerum reiciendis enim aperiam cum ut adipisci veritatis soluta illo praesentium consequatur voluptate possimus dolorem et officiis perspiciatis commodi quae eligendi alias culpa atque ducimus eum odit accusamus ad labore quod necessitatibus. Officiis, ducimus, voluptate doloremque nihil rerum consequuntur obcaecati fugiat cum veritatis quidem qui nulla distinctio laborum perspiciatis quia tempora eveniet tempore aliquam pariatur aliquid quibusdam aspernatur quis maiores minus quas culpa reprehenderit id iure optio asperiores? Excepturi, deleniti, at, expedita quod animi harum est sit iste distinctio consequuntur mollitia corporis soluta. Quos, asperiores voluptas totam nesciunt atque iusto commodi. Autem, animi eius odio commodi vitae nihil possimus neque minima obcaecati aspernatur voluptate dolorem consequuntur illo vel iste deserunt tempore eaque maxime cum ratione rem odit officia tempora ut recusandae saepe maiores quae repellat debitis atque est praesentium numquam mollitia dolor ipsum modi fuga veniam error perspiciatis quas provident optio similique iure.</p>
		</div>
	</div>
</div> <!-- END CONTENT SECTION -->

<!-- FOOTER SECTION -->
<div class="footer-section">
	<div class="row">
		<div class="small-12 medium-12 large-12 columns">
			<p>&copy; Copyright 2014</p>
		</div>
	</div>
</div> <!-- END FOOTER SECTION -->

Here we created a header section, including the <nav>, a content section and a footer section. There are a couple of things to note:

  • Our <nav> has a class .important-class, which we'll be using to tell jQuery which element to target when we're going to scroll down.
  • We've included a div with a class .header-fill. We'll use this to put some space in between the top of the browser and the content section, as our header will be fixed and has a higher z-index then the rest of the elements on the page.

Step 2: Top Bar Markup

Next up, we're going to write the HTML for our Top Bar. We need a title area for our logo and a section with an <ul> to store our menu items. Take a look at the following HTML:


<!-- TOPBAR SECTION -->
<nav class="top-bar important-class" data-topbar>
		
    <!-- TITLE AREA & LOGO -->
	<ul class="title-area">
		<li class="name">
			<img src="img/Acme_Colour.png" alt="" id="logo-image">
		</li>
		<li class="toggle-topbar menu-icon"><a href="#"><span>menu</span></a></li>
	</ul> <!-- END TITLE AREA & LOGO -->

    <!-- MENU ITEMS -->
	<section class="top-bar-section">
		<ul class="right">
			<li class="active"><a href="index.php">Home</a></li>
			<li><a href="blog.php">Blog</a></li>
			<li><a href="#">About us</a></li>
			<li><a href="#">Portfolio</a></li>
			<li class="has-dropdown">
				<a href="#">Services</a>
				<ul class="dropdown">
					<li><a href="#">Service #1</a></li>
					<li><a href="#">Service #2</a></li>
					<li><a href="#">Service #3</a></li>
				</ul>
			</li>
			<li><a href="#">Contact</a></li>
		</ul>
	</section> <!-- END MENU ITEMS -->
</nav> <!-- END TOPBAR SECTION -->

We've added an <ul> with the class title-area where we keep our logo. Next, we have our <section> with a class of top-bar-section and an <ul> with a class .right, containing all our list items. Our image has an id of logo-image which we will also need in our jQuery later on in this tutorial.

Step 3: Results So Far

If we open up our browser and go to our index file, we'll find that our basic Foundation styling does a lot of work for us, to make things look nice. Our logo still doesn't fit though. In the next step we're going to fix this and give our header navigation some proper styling.

Setting up Sass

To get the results we desire, we'll need some basic styling for our sections, especially the header and the Top Bar section. We are going to make use of Sass to make it happen.

Step 1: General Styling

To start, we're going to give all our sections some basic styling. Take a look at the Sass below:

$primary-color: #ef4523;

/*
   HEADER SECTION
   ========================================================================== */
.header-section {
    -webkit-box-shadow: 0 0 5px 0 rgba(0,0,0,0.4);
	box-shadow: 0 0 5px 0 rgba(0,0,0,0.4);
	position: fixed;
	z-index: 999;
	min-width: 100%;
}

.contain-to-grid {
	background-color: rgba(255, 255, 255, 0.97);
}

// FILL USED FOR HEADER
.header-fill {
	background: #fff;
	height: 135px;
	.tablet-mobile-logo img {
		padding-top: 30px;
	}
}

// USED FOR JQUERY ACTION
.padding-on-my-header {
	padding: 17px 0.9375rem 62px 0.9375rem;
	ul.title-area img {
		margin: -5px 0 0 0;
	}
}

.full-width {
	min-width: 100%;
}

p {
	line-height: 3rem;
	padding-bottom: 30px;
}


/*
   CONTENT SECTION
   ========================================================================== */


.content-section {
	.main-content {
		margin-top: 35px;
	}
}


/*
   FOOTER SECTION
   ========================================================================== */

.footer-section {
	background: #333;
	min-height: 100px;
	p {
		color: #fff;
		margin-top: 50px;
	}
}

We're using a primary-color variable here, which we're going to use for some of the Top Bar styling. Our header-section has a nice, subtle box-shadow, so it actually looks like it's floating above the rest of the content. By setting its position to fixed and making the z-index: 999, we make sure the navigation sticks to the top of the browser when we scroll down and that it stays above all the other elements on the page. 

Our .contain-to-grid class has a subtle transparent white color, so that when we scroll, it appears as if the header floats on top of all the other elements. We still need to fix up that menu though, so let's take care of that next.

Step 2: Topbar Styling

Now, we're going to add the styling to give our Top Bar a nice, sleek look. You could also adjust some of the settings of the top bar in _settings.scss, but I'm going to show you how to do this using our own custom overrides. The Sass below explains what's happening where:

/*
   TOPBAR NAVGATION
   ========================================================================== */
.top-bar
{
    background: none;
	padding: 45px 0.9375rem 90px 0.9375rem;
	transition: all 0.5s ease 0.1s;
	// LOGO ADJUSTMENT
	ul.title-area img {
		margin: -10px 0 0 0;
	}
	.top-bar-section ul {
		background: none;
		// MENU ITEM STYLES
		li a:not(.button), li.active a:not(.button) {
			background: none;
			line-height: 30px;
			font-size: 12px;
			padding: 0;
			margin: 5px 0 0 0;
			text-transform: uppercase;
		}
		// MENU ITEM HOVERS
		li a:not(.button):hover {
			background: none;
			border-bottom: 2px solid $primary-color;
			color: #222;
		}
		// MENU ITEM ACTIVE
		li.active a:not(.button) {
			border-bottom: 2px solid $primary-color;
			color: #222;
			&:hover {
				background: none;
			}
		}
		li {
			margin-left: 30px;
			a {
				color: #888;
			}
		}
	}
	// DROPDOWN MENU
	.top-bar-section ul li:hover:not(.has-form) > a {
		color: #333;
	}
	.top-bar-section li ul.dropdown {
		background: #fff;
		border: 1px solid #ddd;
		color: #888;
		li {
			border-bottom: 1px solid #ddd;
			margin: 0;
			padding: 5px 15px 5px 15px;
		}
	}
	.top-bar-section li ul.dropdown li a:not(.button):hover, .top-bar-section li ul.dropdown li a:not(.button) {
		background: none;
		color: #222;
		border-bottom: none;
		padding: 20px -4px 40px 45px;
	}
	.top-bar-section ul.dropdown li:hover:not(.has-form) > a:not(.button) {
		background: none;
		color: #222;
	}
	// DROPDOWN ARROW
	.has-dropdown > a:after {
	    border-color: rgba(0, 0, 0, 0.5) transparent transparent;
	    margin-top: -5px;
	}
}

Note: We're going to move the .padding-on-my-header class below the Top Bar rules. This is necessary for the padding to override that of the Top Bar.

We've added some padding to our Top Bar and we have set a transition of 0.5s, ease 0.1s. This will provide a smooth transition effect when our jQuery kicks in. The background is set to none, so that our header has the slightly transparent color which we gave our .contain-to-grid class. The rest is some basic styling for the Top Bar's menu items, dropdowns, hovers and active states. Nothing too overstated, but it's given us a clean result by adding some padding and white space.

Step 3: Results So Far

Let's take a look at what we have so far. It's certainly starting to look like something! However, our menu is still a little big for when we scroll down the page. That's where our .padding-on-my-header class steps in.

jQuery for Effect

Let's use a little bit of jQuery magic to add the .padding-on-my-header class on scroll and change the logo to a smaller sized one.

Step 1: Creating Our init.js

We are going to create an init.js file to house our jQuery code. Put it in your /js folder and include the following line at the bottom of your index file, right before the closing body tag, to include the script:

        <!-- JAVASCRIPTS -->
    	<script src="bower_components/jquery/dist/jquery.min.js"></script>
		<script src="bower_components/foundation/js/foundation.min.js"></script>
		<script src="js/app.js"></script>
        <!-- OUR JQUERY MAGIC -->
		<script src="js/init.js"></script>
	</body>
</html>

Our init.js will contain the following:

jQuery(window).scroll(function() {
    if (scroll >= 50) {
        $('#logo-image').attr('src', 'img/Acme_Monogram_Colour.png')
        $(".important-class").addClass("padding-on-my-header");
    }
    if (scroll < 50) {
    	$(".important-class").removeClass("padding-on-my-header");
    	$('#logo-image').attr('src', 'img/Acme_Colour.png')
    }
});

Let's look at what is actually happening here. When the user scrolls down, we perform the following function: if the user scrolls more than 50 pixels, then we make the top bar smaller and insert a smaller sized logo:

  • We find our id logo-image and replace the image source with that of our smaller logo.
  • Next, we look for our .important-class and add another class to it: .padding-on-my-header

When we go back up, and scroll below 50 pixels, we do the reverse and remove the padding class, putting back the big ol' logo.

Step 2: Check the Results

Go ahead and move on back to the browser. Refresh the page and try scrolling down. If everything went as planned you should now see the Top Bar shrinking with a smooth transition and the big logo being replaced by the smaller one. So far so good. But when we resize our browser, you'll see that it isn't quite responsive yet. Let's take care of that!

Media Queries for Mobile Optimization

We'll be creating a media query for 1024px devices and smaller. For that to take its proper effect, we need to change the small breakpoint of Foundation. How you say? Well that's easy! We're just going to dive into our _settings.scss and look for the following setting:

// Media Query Ranges
$small-range: (0em, 64em);
$medium-range: (64em, 64em);
$large-range: (64.063em, 90em);
$xlarge-range: (90.063em, 120em);
$xxlarge-range: (120.063em, 99999999em);

As you can see, we've moved the small-range from 0em - 40em to 0em - 64em, which calculates to 1024px; Our medium range now starts at 64em. Save your settings for the changes to take effect and let's get to our media query!

Step 1: Adding the Media Queries

Our Top Bar on a smaller device won't need to be that big. We're going to shrink it a little and reposition our menu. We'll also be using a much smaller header-fill. Take a look at the styles below:

@media only screen and (max-width: 1024px) {

    .top-bar {
		margin-top: 0;
		padding: 0;
		float: none;
		// MENU BUTTON AND HAMBURGER ICON
		.toggle-topbar.menu-icon a {
			color: #222;
			&:after {
    			box-shadow: 0 10px 0 1px #222, 0 16px 0 1px #222, 0 22px 0 1px #222;
    		}
		}
		// LOGO
		ul.title-area img {
			margin: -2px 0 0;
			width: 145px;
		}
		.top-bar-section {
			ul {
				background: #333;
				li {
					margin-left: 0;
				}
				li > a {
					background: $primary-color;
					border-radius: 0;
					font-size: 0.9rem;
				}
				// NORMAL BUTTONS
				li:not(.has-form) a:not(.button) {
					background: none;
					color: #fff;
					padding: 10px 15px;
					margin-top: 0;
					&:hover {
						background: $primary-color;
						color: #fff;
						margin-top: 0;
					}
				}
				// ACTIVE BUTTON
				li.active:not(.has-form) a:not(.button) {
					background: $primary-color;
					color: #fff;
					padding: 10px 15px;
					margin-top: 0;
					&:hover {
						background: lighten($primary-color, 5%);
						margin-top: 0;
					}
				}
			}
		}
	}
	// SMALLER IMAGE
	.top-bar.padding-on-my-header ul.title-area img {
		margin: 5px 13px 0;
		width: 35px;
	}
	// EXPANDED TOPBAR MENU
	.top-bar.expanded {
		margin-top: 0;
		padding: 0;
		float: none;
		.toggle-topbar.menu-icon a {
			color: #fff;
			&:after {
    			box-shadow: 0 10px 0 1px #fff, 0 16px 0 1px #fff, 0 22px 0 1px #fff;
    		}
		}
	}

	// SMALLER HEADER
	.header-fill {
		height: 40px;
	}

}

Let's take a look at what we've done here:

  • We removed all padding and margins on the Top Bar.
  • We gave the Menu text and the hamburger icon a grey color, instead of the default white color, so it is visible on our white Top Bar.
  • We fixed up our larger logo to fit within the Top Bar.
  • In the top-bar-section we are styling our responsive menu items, hovers and active states.
  • We also resize and reposition the smaller logo.
  • We removed some of the padding and margins on our expanded responsive menu.
  • Lastly, we made our .header-fill smaller, so that it is equal to the height of our Top Bar.

Step 2: Enjoy Your Final Results!

When we go back to our browser and resize it, we can now see that our responsive navigation is in full effect. Scroll down and see how the logo image still changes. Click on the Menu icon to see the expanded version of our responsive navigation.

Conclusion

With some Sass and jQuery magic, we managed to transform the powerful, basic Top Bar from ZURB's Foundation to an awesome, trendy sticky header with some smooth effects. Ready for you to use on your own or your clients' projects. Have fun!

Resources


Advertisement