CSS-only Radial Menu Experiments

I have been working on a slow and plodding redesign of my personal site and am playing around with some navigation ideas.

I wanted to create a JavaScript-free and image-free radial menu, an idea I toyed with a couple years ago and abandoned due to the lack of CSS support to do what I wanted in current browsers at the time. I decided to give it another shot last weekend while recovering from being pleasant for two days.

If you aren’t familiar with radial menus or are curious about why they are popping up as a topic lately, check out Josh Clark’s Touch Means a Renaissance for Radial Menus. You can expect to see them more as Windows 8 is released in a couple months.

I threw together a simple five item navigation list, attached no classes or IDs, and decided to see how far I could get before it became untenable (or I got bored).

Single Level CSS-only Radial Menu

.html {
  background-color: #6D695C;
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAACVBMVEUAAAAAAAAAAACDY+nAAAAAA3RSTlMmDQBzGIDBAAAAG0lEQVR42uXIIQEAAADCMHj/0NdkQMws0HEeAqvwAUGJthrXAAAAAElFTkSuQmCC); }

body{
  margin: 0;
  font-family: Arial, Helvetica, sans-serif;
  /*font-size: 2.5em;*/ }

nav {
  width: 5em;
  height: 8em;
  float: right;
  padding: 0;
  overflow: hidden; }

nav:hover {
  background-color: rgba(0, 0, 0, 0.4);
  width: 16em;
  height: 15em;
  border-radius: 0 0 0 15em; }

body {
  background-color: #eee; }

nav h1 {
  position: relative;
  top: -.75em;
  right: -.5em;
  margin: 0;
  background-color: #000;
  color: #000;
  z-index: 1;
  font-size: 2em;
  line-height: 100%;
  width: 1em;
  padding: 1em .5em 1.25em 1em;
  border-radius: 3.0em 0 0 3.0em;
  -webkit-transform: rotate(-45deg);
  -moz-transform: rotate(-45deg);
  -ms-transform: rotate(-45deg);
  -o-transform: rotate(-45deg);
  transform: rotate(-45deg);
  overflow: hidden; }

nav h1::before {
  content: "AB";/*« «*/
  /*content: "21D0";*//*⇐ ⇐*/
  color: #fff;
  -webkit-transform: rotate(-45deg);
  transform: rotate(-45deg); }

nav:hover h1 {
  display: none; }

nav ol {
  margin: 0;
  padding: 0;
  list-style-type: none; }

a {
  display: block;
  position: absolute;
  top: -10em;
  right: 0em;
  border-radius: 4em;
  border: .15em solid #fff;
  padding: 1.5em 0;
  width: 4.5em;
  text-align: center;
  box-shadow: .45em 0 1.5em rgba(50, 50, 50, 0.75);
  -webkit-transition: all 0.2s ease-in;
  -moz-transition: all 0.2s ease-in;
  -ms-transition: all 0.2s ease-in;
  -o-transition: all 0.2s ease-in;
  transition: all 0.2s ease-in; }

nav:hover a {
  /*display: block;*/ }

a:link, a:hover, a:focus, a:active, a:visited {
  text-decoration: none;
  color: #ddd;
  background-color: #000; }

a:hover, a:focus, a:active {
  background-color: #222;
  color: #fff;
  text-shadow: 0em 0em 0.2em rgba(255, 255, 255, 0.8);}

nav:hover li:nth-child(1) a {
  right: 13.5em;
  top: .2em; }

nav:hover li:nth-child(2) a {
  right: 12em;
  top: 4.75em; }

nav:hover li:nth-child(3) a {
  right: 9.0em;
  top: 8.5em; }

nav:hover li:nth-child(4) a {
  right: 4.75em;
  top: 11em; }

nav:hover li:nth-child(5) a {
  right: 0;
  top: 12em; }Check out this Pen!

View this directly on the Codepen site.

Note the style for the body. If you uncomment the style /*font-size: 2.5em;*/, you will see that entire menu scales up. You can put any text size in there you want and the menu will scale up and down. All the sizing (text, borders, positioning, padding, etc.) is based off ems, which makes it easier to scale each part of the menu proportionally.

You may note that I put an onclick = "void(0);" on the h1. Without this, the menu just wouldn’t work on iOS. Otherwise I am relying on my Android devices to read a touch as a hover.

You may also see that there is an image on the page. This is a striped background that made it easier for me to see where elements aligned. It is not used in the menu itself, but I do like how it looks so I kept it.

I opted for CSS positioning changes instead of CSS animations since the support is consistent. The menu works in IE9, though without animations. Since the menu uses HTML5 elements, and since it is an experiment, I am not testing older than IE9 (yet).

Then I was curious how hard it would be to add another level into the menu and how it would feel as a user…

Two Level CSS-only Radial Menu

<!-- Original pen (~July 2012) lost by CodePen, this is a recreation with their assistance to get the old code. -->
<nav role="navigation">
  <h1 onclick = "void(0);">Menu</h1>
  <ol>
    <li><a href="#">Bio</a>
      <ol onclick = "void(0);">
        <li><a href="#">Bio One</a></li>
        <li><a href="#">Bio Two</a></li>
        <li><a href="#">Bio 3</a></li>
      </ol>
    </li>
    <li><a href="#">Blog</a></li>
    <li><a href="#">Books</a></li>
    <li><a href="#">Articles</a></li>
    <li><a href="#">Contact</a></li>
   </ol>
</nav>

<!--
The onclick attributes are to allow Safari on iOS to see these otherwise non-clickable elements as clickable so it can then apply the hover styles as if they were clicks.
-->
Check out this Pen!

View this directly on the Codepen site.

I forked the single-level menu and put another level under the first item (“Bio”). With only three items it was still time consuming to style the positioning of elements and get the animation look that I wanted.

I also had to put an onclick = "void(0);" into the nested ol in order for iOS to recognize it as a clickable element. Sadly, that means that “Bio 3” always gets the focus on touch devices because it’s at the top of the stack when the focus is applied through a tap.

On desktop browsers however, it works well.

Wrap-up

Drawbacks for both of these menus are many. For example, using my positioning method it can be very hard to calculate where additional menus should appear, making this tedious to code into a CMS. The menu items also all rely on very short navigation text in order to fit into the almost-circular navigation items. The collective shadows from nested items make for an interesting shadow stack obscuring subsequent menu items.

However, given the real-life feedback I’ve gotten I figured there might be some ideas or code chunks others might find useful. Even better would be if someone gets inspired to take this to the next level and clean it up, fixing my own shorthand tricks and making it more robust.

Corrections, suggestions, feedback, and forking are all welcome.

2 Comments

Reply

I’ve used your menu because it looks great.
I used it but I never be able to use 6 submenu’s, I can only use 4.

On my page you can see on menu item 2 I wrote 5 sub-menus but “Flevokust” will not work.

Can you help me?

In response to Martin. Reply

Martin, I see the problem. The “Contact” link, as all the links do, has a large right margin. Because the “Contact” link comes after “Flevokust” in the source order, that margin overlaps “Flevokust” and blocks the hover. That is an unfortunate mistake in my code.

Leave a Reply to Adrian Roselli Cancel response

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>