CSS3 Slider Timeline Menu

Alt Text


I was inspired by the website theCampusBubble and its fixed navigation. It has a slider / timeline menu with a dial that slides over as each new section is scrolled to. You can click on each link as well and it will smooth scroll along with adjusting the dial to the selected section. I liked this idea and took it a step further with giving each section a color. The slider background color will fade to the selected section’s color.

HTML structure

Here is the html for the general structure of the timeline menu. The slider div consists of the menu links and the slider bar. Inside the bar there is the before color and the after color and the actual knob of the slider.

<div class="menu">
  <div class="slider">
      <li class="category active"><a href="#home">HOME</a></li>
      <li class="category"><a href="#search">SEARCH</a></li>
      <li class="category"><a href="#about">ABOUT US</a></li>
      <li class="category"><a href="#contact">CONTACT US</a></li>
    <div class="bar">
      <div class="before"></div>
      <a class="knob"></a>
      <div class="after"></div>

Here is the general structure of each content section. The id’s must match the links in the menu for the smooth scroll to work.

<div id="search" class="container blue">
<div id="about" class="container green">
  <h1>About Us</h1>


The css for the menu is very simple. There are transitions on the slider bars and knob to make the animations work.

.menu {
  width: 100%;
  position: fixed;
  height: 100px;
  background-color: #fff;
  top: 0;
  left: 0;
  z-index: 2;
  .menu .slider {
    position: relative;
    left: 10%;
    width: 80%;
    text-align: center;
    .menu .slider .bar, .menu .slider .bar .before {
      height: 20px;
      transition: .5s; 
      -webkit-transition: .5s; 
      border-radius: 20px;
      -moz-border-radius: 20px;
      -webkit-border-radius: 20px;
    .menu .slider .bar {
      position: relative;
      left: 3px;
      width: 100%;
      background-color: #777;
      .menu .slider .bar .before {
        width: 100px;
        float: left;
        position: relative;
        left: -3px;
      .menu .slider .bar a.knob { 
        position: absolute;
        top: -5px;
        left: 0;
        margin: 0;
        display: block;
        width: 30px;
        height: 30px;
        background-color: #ccc;

        border-radius: 15px;
        -moz-border-radius: 15px;
        -webkit-border-radius: 15px;
        transition: .5s; 
        -webkit-transition: .5s; 
    .menu ul { 
      height: 100%; 
      display: inline-block;
      margin: 20px 0 15px 0;
    .menu ul li {
      margin: 0 40px;
      font-size: 12px;
      font-weight: bold;
      float: left;
    .menu ul li a { color: #444; margin: 0; }


The jQuery scripts handles the smooth scrolling and also does some calculations for accurately positioning the slider knob.

	  // Slider functionality
	    // slide knob to position function
	    (function( $ ){
         $.fn.slideToPos = function() {
           var left = $(this).position().left + ($(this).width() / 2) - ($(".menu a.knob").width() / 2) - 2;
           $(".menu a.knob").css("left", left);
           var before = $(this).parent().parent().parent().children(".bar").first().children(".before").first();
           before.css("width", left + 20).css("backgroundColor", $($(this).attr("href")).css("backgroundColor"));
           return this;
      })( jQuery );
	 	$(".menu ul li.active a").slideToPos();     
    $(".menu ul li a").click(function(e) {
      $('html, body').animate({ scrollTop: $(this.hash).offset().top }, 400);
    // Scroll Spy
    $(window).scroll(function() {
      var top = $(window).scrollTop() + 100; // Take into account height of fixed menu
      $(".container").each(function() {
        var c_top = $(this).offset().top;
        var c_bot = c_top + $(this).height();
        var hash = $(this).attr("id");
        var li_tag = $('a[href$="' + hash + '"]').parent();
        if ((top > c_top) && (top < c_bot)) {
          if (li_tag.hasClass("active")) {
            return false;
          else {
            $(".menu ul li.active a").slideToPos();