Dot Navigation Styles

Today we’d like to share some subtle effects and styles for simple dot navigation with you. These styles could, for example, be used for a page scroll navigation or a thumbnail preview, in a vertical or horizontal fashion.

Small UI elements usually don’t get too much attention when it comes to creative effects. They are often neglected because of their size. But they can offer a great opportunity to add some subtle, yet interesting effects. Recently, you might have seen some kind of dot navigation with a vertical or horizontal layout for scrolling a website to a section. Today we want to share a set of inspirational dot navigation styles with very subtle effects when we hover or when we click on them. For the effects we employ several techniques, including transitions on pseudo-elements, perspective and SVG.

Note that some effects might not work as intended in some browsers (SVG transition, 3D transform-style). For older browsers you might have to add a simple fallback for the selected dot in some examples.

For the structure we’ll have an unordered list with links:

<div class="dotstyle dotstyle-fillup">
	<ul>
		<li class="current"><a href="#">Home</a></li>
		<li><a href="#">About</a></li>
		<li><a href="#">Products</a></li>
		<li><a href="#">Portfolio</a></li>
		<li><a href="#">Blog</a></li>
		<li><a href="#">Contact</a></li>
	</ul>
</div>

For some examples, we also use an additional empty list element, i.e. in order to “move” the current item in the “dot move” style.

We define some common styles:

.dotstyle ul {
	position: relative;
	display: inline-block;
	margin: 0;
	padding: 0;
	list-style: none;
	cursor: default;
}

.dotstyle li {
	position: relative;
	display: block;
	float: left;
	margin: 0 16px;
	width: 16px;
	height: 16px;
	cursor: pointer;
}

.dotstyle li a {
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	outline: none;
	border-radius: 50%;
	background-color: #fff;
	background-color: rgba(255,255,255,0.3);
	text-indent: -999em;
	cursor: pointer; /* make the text accessible to screen readers */
	position: absolute;
}

Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.

An example for a style and subtle effect is the following one, where we “fill” the inner circle. We do that by setting the link to overflow hidden and using a pseudo-element as the filling part:

/* Fill up */
.dotstyle-fillup li a {
	overflow: hidden;
	background-color: rgba(0,0,0,0);
	box-shadow: inset 0 0 0 2px rgba(255,255,255,1);
	transition: background 0.3s;
}

.dotstyle-fillup li a::after {
	content: '';
	position: absolute;
	bottom: 0;
	height: 0;
	left: 0;
	width: 100%;
	background-color: #fff;
	box-shadow: 0 0 1px #fff;
	transition: height 0.3s;
}

.dotstyle-fillup li a:hover,
.dotstyle-fillup li a:focus {
	background-color: rgba(0,0,0,0.2);
}

.dotstyle-fillup li.current a::after {
	height: 100%;
}

Another interesting example is the stroke that we draw using SVG and transitioning the stroke-dashoffset of the circle shape:

/* SVG draw circle stroke */	
.dotstyle-drawcircle li {
	width: 18px;
	height: 18px;
}

.dotstyle-drawcircle li a {
	top: 3px;
	left: 3px;
	width: 12px;
	height: 12px;
	background-color: #c44d48;
	-webkit-transition: opacity 0.3s;
	transition: opacity 0.3s;
}

.dotstyle-drawcircle li svg {
	z-index: 10;
}

.dotstyle-drawcircle li svg circle {
	opacity: 0;
	fill: none;
	stroke: #fff;
	stroke-width: 3;
	stroke-linecap: round;
	stroke-linejoin: round;
	stroke-dasharray: 39 39; 
	stroke-dashoffset: 39; /* ~ length of circle path (pi*2r) */
	transition: stroke-dashoffset 0.3s, opacity 0.3s;
}

.dotstyle-drawcircle li.current a,
.dotstyle-drawcircle li a:hover,
.dotstyle-drawcircle li a:focus {
	opacity: 0.5;
}

.dotstyle-drawcircle li.current svg circle {
    opacity: 1;
    stroke-dashoffset: 0;
	transition: stroke-dashoffset 0.3s, opacity 0.15s;
}

For the “hop” effect we also use an extra bit of JavaScript in order to add another class to the current item which indicates if the previous current item was on the right. This will allow us to change the transform origin and let the “hop” happen from the right.

Hope you enjoy these styles and find them inspiring!

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay in the loop: Get your dose of frontend twice a week

Fresh news, inspo, code demos, and UI animations—zero fluff, all quality. Make your Mondays and Thursdays creative!

Feedback 40

Comments are closed.
  1. This is one of the best effect i have ever seen 🙂 just loved it, gonna use it on a project. Thanks Mary love you

  2. You are a genius and I wish in this world could exist more women (but also person) like you!

  3. Nice effect, i’ve tried to put link on the href but i don’t know why it doesn’t works

    • Same problem, I’ve tried everything i know but nothing. How can this be fixed?

    • Sorry. Ignore. Got it fixed. 😀
      I used PageScroll2id.js
      Just be sure to amend this code:
      <script> (function($){ $(window).load(function(){ /* Page Scroll to id fn call */ $("#nav a,a[href='#top'],a[rel='m_PageScroll2id']").mPageScroll2id({ highlightSelector:"#nav a" }); /* demo functions */ $("a[rel='next']").click(function(e){ e.preventDefault(); var to=$(this).parent().parent("section").next().attr("id"); $.mPageScroll2id("scrollTo",to); }); }); })(jQuery); </script>
      follows your nav class structure 🙂

  4. Love the looks, but hate dot navigation style, the touch / click target is way too small to be user friendly.

    • cheapest way to do that is by removing float:left inside “.dogstyle li{}”

  5. As always, the effects are splendid.

    I’ve noticed though there’s been a trend of articles without the iconic walkthrough of how most of the effects came in fruition; That’s what the github issues section and the ‘contact us’ section are for, I guess.

    At the same time, I’m surprised there isn’t a gittip button or plans of a CoDrops book (going through the nuts and bolts of the most advanced examples of SVG, CSS & JavaScript awesomeness on this site). yet.

  6. This is awesome!
    However when I tried it the animation works fine but the buttons are not. I figured out that the code below is the reason. I m just new in web development and I can’t fully understand each character (in the code below) means.

    [].slice.call( document.querySelectorAll( ‘.dotstyle > ul’ ) ).forEach( function( nav ) {
    new DotNav( nav, {
    callback : function( idx ) {
    //console.log( idx )
    }
    } );
    } );

    Help please. Thanks!

    • Yea I am having the same issue.. It just won’t work for me either :(.. Did you ever get it to work?

  7. Another idea to fill the circles can be effects similar to filling it with pencil. It looks great when implemented just in black and white.

  8. Great work!!

    I’ve used the tooltip version, you could add -ms-transform to the CSS to cater for IE9

    @Mariam, to make vertical add clear:both to the li tag in CSS, then adjust the margin

    • I had the same problem with the tooltip style. I just swapped “li” and “a” in css and html and now it works.

      HTML

      Tooltip 1

      <a href=”index.html” rel=”nofollow”>Home</a>
      <a href=”index2.html” rel=”nofollow”>About</a>
      <a href=”index3.html” rel=”nofollow”> Products Products Products</a>

      CSS

      /* Common styles and resets */

      .dotstyle ul {
      position: relative;
      display: inline-block;
      margin: 0;
      padding: 0;
      list-style: none;
      cursor: default;
      -webkit-touch-callout: none;
      -webkit-user-select: none;
      -khtml-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
      }

      .dotstyle a {
      position: relative;
      display: block;
      float: left;
      margin: 0 16px;
      width: 16px;
      height: 16px;
      cursor: pointer;
      }

      .dotstyle a li {
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      outline: none;
      border-radius: 50%;
      background-color: #fff;
      background-color: rgba(255, 255, 255, 0.3);
      text-indent: -999em; /* make the text accessible to screen readers */
      cursor: pointer;
      position: absolute;
      }

      .dotstyle a li:focus {
      outline: none;
      }

      /* Individual styles and effects */

      /* Tooltip */

      .dotstyle-tooltip a {
      border: 2px solid #fff;
      border-radius: 50%;
      z-index: 1;
      -webkit-transition: border-color 0.3s ease;
      transition: border-color 0.3s ease;
      }

      .dotstyle-tooltip a li {
      white-space: nowrap;
      top: auto;
      bottom: 250%;
      left: 50%;
      visibility: hidden;
      padding: 0 10px;
      width: auto;
      height: auto;
      border-radius: 0;
      background-color: #c44d48;
      color: #fff;
      text-indent: 0;
      line-height: 2;
      opacity: 0;
      -webkit-transform: translateX(-50%) translateY(-50%);
      transform: translateX(-50%) translateY(-50%);
      -webkit-transition: -webkit-transform 0.3s ease, opacity 0.3s ease, visibility 0s 0.3s ease;
      transition: transform 0.3s ease, opacity 0.3s ease, visibility 0s 0.3s ease;
      }

      .dotstyle-tooltip a li::after { /* http: //cssarrowplease.com/ */
      position: absolute;
      left: 50%;
      margin-left: -10px;
      width: 0;
      height: 0;
      border: solid transparent;
      border-width: 10px;
      border-color: transparent;
      border-top-color: #c44d48;
      content: ”;
      pointer-events: none;
      top: 99%;
      -webkit-backface-visibility: hidden;
      backface-visibility: hidden;
      -webkit-transition: opacity 0.3s ease;
      transition: opacity 0.3s ease;
      }

      .no-touch .dotstyle-tooltip a:hover li,
      .dotstyle-tooltip a.current li {
      z-index: 100;
      visibility: visible;
      opacity: 1;
      -webkit-transform: translateX(-50%) translateY(0%);
      transform: translateX(-50%) translateY(0%);
      -webkit-transition: -webkit-transform 0.3s ease, opacity 0.3s ease;
      transition: transform 0.3s ease, opacity 0.3s ease;
      }

      .dotstyle-tooltip a.current {
      border-color: #c44d48;
      }

      .dotstyle-tooltip a:hover {
      z-index: 100;
      }

      .no-touch .dotstyle-tooltip ul:hover a.current li {
      opacity: 0.2;
      }

      .dotstyle-tooltip ul a.current:hover li {
      opacity: 1;
      }

  9. Hello, I am trying to use this for my website. It works for Chrome and Mozilla. But doesn’t show up at all in IE and Safari. I have added webkit equivalents of box-shadow and border-radius, but that hasnt helped. Is there anything more that I am missing? Any help will be appreciated. Thanks.

  10. Hi, these are great! We’ve implemented them on our website. We had an independent usability expert (?) review the site and they suggested arrows either side of the selected dot

  11. Wow that is awesome, and it looks like you had fun doing it, too! Wanna pick up some freelance?