In this tutorial, we will learn how to create radial menus, using
nothing but CSS + HTML. In a future update, I will show you how you
can also create "tabs" connected to the menu. For the sake of mobile
users, I will include an option for turning the radial menu into a
list on smaller devices. I will also include a way to create a "pie"
menu using a similar method, also in a future update.
Please note: I'm using custom fonts on this page, so your menu will
look slightly different.
Why use a radial menu? Well, first of all, it just looks cool,
especially with the use of images
(example)
.
Radial menus are more intuitive than standard drop-down menus, and
have the added benefit of being easily memorized, making them a great
way to boost your website/application user experience (UX). Perhaps
the only downside, is that radial menus require a lot more work on
the backend, than a standard "list of items" would require.
As you should notice, there's not much happening here, because most of
the "work" is done in your CSS code. Where you place each menu item
doesn't matter. Also, you can use ids as opposed to
classes. The only limitation of using ids is that if you have
multiple menus in a single site, you'll have more work to do.
Almost everything about the menu container in this example is
optional, and by optional, I mean you can tweak it to your own design.
However, in order for the radial menu to work as intended,
you need to keep some basic things in mind:
Your container should (preferably) be a true circle. You can of
course create any shape you'd like, but it will make the math
involved a bit more tricky to figure out, and it's not as easy to
use.
You need an adequate margin for your menu items. I don't recommend
having your menu overlap other elements, as this can cause
issues with interaction and rarely, even visual artefacts.
Your menu should have some form of a visible hover state, so as to
hint to users of your site or application that can be interacted
with. This is true even if you use a label + checkbox
combo(I will explain how to do this in a future update).
to create a clickable menu.
First, we start by setting some defaults for every item. Instead of
duplicating a bunch of rules for each class, we can group them all
together, and only define their exact positions and transitions
separately. These have to be defined separately, or you will not have
your menu items will not move, and you won't get a smooth animation.
This simple rule will set your menu items to be visible on hover. Now,
we will give them a hover state, so that it's clear when you're about
to use a item from the menu, it's actually clickable.
Now that we've given the menu items hover states, it's time for the
real fun - making them actually move into their positions. Since
we've already taken care of styling, we simply need position each
item at the center of the container element, and then it's as simple
as inverting their position, and using a transition to make it smooth.
If you've made it this far, give yourself a high five! Okay, not a
high five, put that crack back! Hopefully you've been testing
your work along the way, and hopefully, you've realized something
isn't right. Before I give away the answer, can you guess it is?
what's wrong?
Try moving between items while the menu is hovered. Notice how they
collapse before you can reach them? This happens because we're
reliant on the menu container being hovered in order for the menu
items to be visible. We can easily fix this using a pseudo-element.
.menu::before{/*Required*/
border-radius: 100%;
position: absolute;
content: " ";
z-index: -1;/*Highly Recommended, but you could find another use for this element, so it's optional:*/
opacity: 0;/*Recommended, but flexible:*/
bottom: -2.5%;/*Always use half the amount if you're going above 100% for width+height*/
transition: 1;/*If you want, you can increase this slightly.*/
height: 105%;
width: 105%;}.menu:hover:before{/*Required*/
z-index: 1;/*Recommended, but flexible:*/
bottom: -47.5%;/*Always use half the amount if you're going above 100% for width+height*/
height: 195%;
width: 195%;}
What is happening here?
Our pseudo-element acts as a kind of "buffer zone," allowing
you travel between menu items (within a certain range), without
losing the "attention" of the menu-container.
Since child elements trigger or maintain the their parent's
"hover" event, the ::before pseudo-element can be used
to add this functionality, without having to add anything else to
your HTML code.
The other bonus, is that you can tweak this element so that it
adds even more visual pizazz to your radial menu! For example, if
you add a border, and leave the background of this element
transparent, you can add an outline to the open menu, showing its
physical boundaries. One drawback, however, is that you can't add
a box-shadow (at least not on Chromium-based browsers), without
causing rendering artefacts (I tested this).
That's it for now!
Look out for updates to land in the near future!