Advanced techniques for navigation with CSS

Advanced techniques for navigation with CSS

Table of Contents

There are people who will tell you that you cannot create cool effects like sliding or fading without getting your hands on JavaScript. Don’t listen to those ignorants. They have no clue about what can you do with good old HTML and a few lines of CSS. In this post I will show couple effects you can use to enhance the navigation on your website. There will also be a bit of thoughts on designing a navigation. If you want you can skip it and move right to the tricks and sample code, but this stuff is worth reading!

The question of navigation

Have you ever saw a partially hidden road sign? That would be weird right? Imagine driving somewhere and having to interact in some way with car’s system so you can reveal the navigation or signs around the road. That would be just ridiculous. Funny, we are doing it already (yes me too)! Websites use this approach for mobile devices because there is not so much space available for navigation. A small, and growing, number of websites are adopting this “mobile version of navigation for desktops as well.

The question you should ask, at least for desktop users, is how important navigation is. When you hide it on purpose, users have to find it first and understand its label. Only then can they use it. This approach is understandable with elements that don’t convey any important information, but is this the case of navigation? Well, it can be. When visitor lands on your website, it is because he is looking for some content. The navigation is not his main interest (if he is not a web designer looking for inspiration 🙂 ).

In this situation, navigation can potentially be hidden without causing any damage or harm. What are the other situations? This is hard to answer because the majority will be full of visitors coming from search engines looking for specific content. If we take this is a premise, then, I think, it is safe to say that navigation is not a crucial piece of the puzzle. Therefore it can be hidden, even as a default state. Damn I would not consider this as an outcome. Maybe it is a bit twisted logic, but whatever you can sue me if you want.

The takeaway: You can hide navigation behind an or text label if you want. Visitors is interested in content and does not care about navigation anyway.

Icon or text

OK. Let’s say you decided to use hidden navigation as a default state. Next question is how should navigation be labeled. You can either use some icon, depending on your preferences, or use a text label. Since icons and symbols have been a huge trend last two years or so, many web designers will probably incline to the first option. However, more recently, some web designers started to switch from icons to text labels to indicate navigation. You probably saw some of those variations using “MENU” as label.

This subject of icon versus text might seem silly but the reality is more complex. When designing anything that will be available to other people, you have to think about accessibility. In case of navigation, accessibility is crucial. You have to plan what label or icon will you use. Will you go with the majority and chose the burger icon? Thanks to its popularity, burger icon is now easily distinguishable and most of your users will understand its meaning. You can almost say it transformed itself into new design pattern.

Anyway, problem can arise if you decide use different iconography in your design. Then, some users might get confused. Take me for example … When I was playing with android development and testing, some of the icons were unfamiliar to me as some one used to iOS. The trouble is that there is no uniform icon or symbol across the available platforms. You will turn on computer with Windows and there is one icon, on iOS another and Android also has its own. It’s a bit of mess.

For this reason, I am more and more inclined to dropping of the icons for navigation and menu and going with plain text instead. In my latest project, I used this approach as well. The navigation is hidden as default, no matter what resolution your device has. The label is pretty simple–MENU (well, with black borders around). In this way, because “MENU” is a term majority of users will understand, I don’t have to worry about breaking something.

What’s more, when you will encounter this label on screen reader, it will understand it as well. This is something you cannot say about icons, no matter if they are created by CSS or SVG. Try this by yourself and see how will these devices recognize and translate those symbols. Trust me, you will have a lots of fun. Some people may argue that you can add a hidden text. Yes you can. You definitely can add a text label just for these devices such as screen readers. It is a bit of work, but go ahead if you want.

For me, this is not a solid argument. It is like taking a pain killer to get rid of headache instead of looking for underlying cause(s). It is just a quick fix that will work in short term. Another thing is what will you do if your stylesheet or source files for icon font will break? Remember, the text label you used is still hidden. How are you going to solve this? Wait a moment, you can use JavaScript to check whether certain are available and manipulate with DOM in case they are missing. You can also grab some server-side solution.

Do you see it too? It is getting more and more complex. With one new solution, there are also two new issues that might appear. In the end, the person suffering the most from this situation will be the user. Website will end up overloaded with JavaScript or PHP. It will take centuries until it loads and if someone restricts JavaScript on his device … Rather not even think about this option. Why not to avoid all this bullshit and use plain English? It does not matter what language do you speak, you will still understand word such as “menu”.

The takeaway: Don’t try to reinvent the wheel making it only more complex. Go the other way, simplify.

Advanced CSS techniques for navigation

After a moment of theory and philosophy, let’s move the practical side. Below, I will show you four examples of how you can make your navigation more dynamic and interesting without writing a single line of JavaScript. So, even if you have no clue what JavaScript is, you don’t need to worry. It is not a prerequisite today.

The HTML comes first

To make things easier, in all four examples, I’m going to use the same HTML code so the only thing that will change will be the CSS. These examples will all use trick or hack with checkbox and label. The principle is simple. Checkbox is placed before the navigation and then is hidden via CSS. In case of label, you have two options. Place it either before checkbox or after it. I like to use the second option because I can then change the style dynamically of label as well.

In short, the checkbox trick is about using checked state and CSS selectors to show or hide navigation and also to dynamically change the styles of label. In order to make this trick work, it is important to always place checkbox before the navigation. Below is the basic HTML we are going to use. The menu will be dead simple. Six links in one row.

HTML:

<header role="banner">
  <nav role="navigation">
    <input id="checkbox--nav" class="checkbox--nav" type="checkbox" hidden>

    <label for="checkbox--nav" class="link--black label--menu">MENU</label>

    <ul class="nav__list">
      <li><a href="index.html" class="link--black">Home</a></li>

      <li><a href="lorem.html" class="link--black">Account <i class="fa fa-angle-right"></i></a></li>

      <li><a href="lorem.html" class="link--black">About</a></li>

      <li><a href="lorem.html" class="link--black">Works</a></li>

      <li><a href="lorem.html" class="link--black">Blog</a></li>

      <li><a href="lorem.html" class="link--black">Contact</a></li>
    </ul>
  </nav>
</header>

The basic styling

Let’s also include necessary CSS for hiding the checkbox and also some basic styling to me the navigation look great. The majority of styles will stay the same. The only differences will be in what effect we are going to use and sometimes in width or height of the navigation list. Below, you have the basic (a bit longer) CSS.

CSS:

/**
 * Customizing typography
 */
body {
  font-size: 100%;
  font-family: "Open Sans", "Trebuchet MS", sans-serif;
}

/**
 * Hidding the checkbox via attribute “hidden”
 */
*[hidden] {
  display: none;
  visibility: hidden;
}

/**
 * Animation for transitions between default and hover states for link and label
 */
a,
.label--menu {
  transition: color 0.25s cubic-bezier(0.4, 0, 1, 1);
}

/**
 * Styles for label
 */
.label--menu {
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 99;
  padding: 0.5rem 0.5rem;
  font-size: 1rem;
  font-weight: bold;
  color: #333;
  border: 2px solid;
  cursor: pointer;
}

/**
 * Styles for navigation list
 */
.nav__list {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  list-style-type: none;
  transition: all 0.25s cubic-bezier(0.4, 0, 1, 1);
}

/**
 * Styles for navigation links
 */
.nav__list a {
  display: block;
  margin: 0.5rem;
  font-weight: bold;
  text-transform: uppercase;
}

.link--black {
  text-decoration: none;
  color: #010101;
}

.link--black:focus,
.link--black:hover {
  color: #888;
}

Side note: As you can see, I included a transition for navigation list as well to make the effects smoother.

Fade it in

The first technique is about navigation fading in. To make this effect reality we will use simple opacity and visibility. As default, the list will be displayed, but opacity will be set to “0” and visibility to “hidden”.

CSS:

/**
 * Styles for navigation list
 */
.nav__list {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  list-style-type: none;
  transition: all .25s cubic-bezier(.4,0,1,1);
  opacity: 0;
  visibility: hidden;
}

Now comes the trick … When checkbox is checked, after clicking on MENU label, we will use checkbox and checked state followed by tylda selector and .nav__list class selector to change the opacity to “1” and visibility to “visible”. This, with applied transition, will create nice fading effect.

CSS:

/**
 * Checkbox trick–fading
 */
.checkbox--nav:checked ~ .nav__list {
  opacity: 1;
  visibility: visible;
}

Roll it down

Next trick is a bit … Trickier. In order to create a navigation that will roll or slide down, we are going to play with height, max-height and overflow properties. First, we have to specify the height of the list. This will be set to “auto”. Next step is to set the max-height to “0” and overflow to “hidden”. As a result, navigation links will be hidden because the list has no length (0 pixels).

The checkbox magic comes in one line … Set the max-height property to some high number. It does not matter how high will you go, just make sure it is bigger than the height of the list. Otherwise some links would not be visible. Now, when you click on menu label, navigation will smoothly roll or slide down.

CSS:

/**
 * Styles for navigation list
 */
.nav__list {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  list-style-type: none;
  transition: all 0.25s cubic-bezier(0.4, 0, 1, 1);
  height: auto;
  max-height: 0;
  overflow: hidden;
}

/**
 * Checkbox trick–rolling
 */
.checkbox--nav:checked ~ .nav__list {
  max-height: 666px;
}

Slide it

One thing I like about Material design is the navigation sliding from side. How about to re-create this effect? In order to do so, we will need to add some overlay. Let’s place it into the nav element, right after the navigation list.

HTML:

...
</ul>

<div class="nav__overlay"></div>

Next step is to add a few styles to our overlay. This means “absolute” positioning, setting z-index to “1”, width and height to “100%”, choosing some background-color, opacity to “0”, visibility to ”hidden” and also including transition.

CSS:

/**
 * Styles for overlay
 */
.nav__overlay {
  position: absolute;
  top: 0;
  left: 0;
  z-index:1;
  width: 100%;
  height: 100%;
  background-color: rgba(0,0,0,.55);
  opacity: 0;
  visibility: hidden;
  transition: all .25s cubic-bezier(.4,0,1,1);
}

We also need to add couple of CSS lines to navigation list. These changes include setting positioning to “relative”, z-index to “2” (placing navigation above overlay), setting fixed width and finally moving it out of screen with transform property set to translateX with minus value of the list’s width. This will make navigation list disappear.

CSS:

/**
 * Styles for navigation list
 */
.nav__list {
  position: relative;
  z-index: 2;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  width: 120px;
  background-color: #fff;
  list-style-type: none;
  transform: translateX(-120px);
  transition: all .25s cubic-bezier(.4,0,1,1);
}

To make this trick work, when checkbox is checked, we will move the list back using transform property set to translateX(0px) and also change the opacity and visibility of overlay to “1” and “visible”. As a result we will get navigation smoothly sliding from side with fading overlay under it.

CSS:

/**
* Checkbox trick–sliding
*/
.checkbox--nav:checked ~ .nav__list {
  transform: translateX(0px);
}
.checkbox--nav:checked ~ .nav__overlay {
  opacity: 1;
  visibility: visible;
}

Side note: If you want, you can add light box-shadow to navigation in order to add some depth.

CSS:

.nav__list {
 ...

  box-shadow: 3px 0px 3px rgba(0,0,0,0.16), 3px 0px 3px rgba(0,0,0,0.23);
}

Full screen navigation

The last trick will be implementing a full screen navigation. This can be handy because the links will be always on the top and nothing will distract users from them. All you have to do is set the height of header, nav and .nav__list elements to “100%”. You can also use justify-content property set to space-around or space-between to stretch the navigation across the screen while distributing it evenly. I will use the full-screen navigation with fading affect.

CSS:

/**
 * Full screen navigation
 */
header,
nav,
.nav__list {
  height: 100%;
}

/**
 * Styles for navigation list
 */
.nav__list {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  list-style-type: none;
  transition: all 0.25s cubic-bezier(0.4, 0, 1, 1);
  opacity: 0;
  visibility: hidden;
}

/**
 * Checkbox trick–fading
 */
.checkbox--nav:checked ~ .nav__list {
  opacity: 1;
  visibility: visible;
}

Side note: If you want to use rolling or sliding down effect with full-screen mode, set the height property to “100%” instead of auto. This way, navigation will roll down to full height of the screen.

Closing thoughts on advanced techniques for navigation with CSS

As you can see on the examples above, you can enhance the navigation in your design with great effects with just a few lines of CSS. Why don’t you take this post as an intro or small warm up and create even more advanced pure CSS effects? For example, we didn’t try to use CSS animations. The takeaway is straightforward … Your imagination and creativity is the limit and anything is possible. Thanks for your time and enjoy your tea (or coffee).

If you liked this article, please subscribe so you don't miss any future post.

If you'd like to support me and this blog, you can become a patron, or you can buy me a coffee 🙂

By Alex Devero

I'm Founder/CEO of DEVERO Corporation. Entrepreneur, designer, developer. My mission and MTP is to accelerate the development of humankind through technology.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.