'Creating a circular menu with CSS
I'm trying to create a circular menu in CSS for a school project.
This is what the menu would look like:

I am not looking for the complete source just an idea how you experienced developers would do it.
I was thinking to create 8 triangles and then the middle to place a circlular div with position absolute; but the triangles, since they're created with borders, when you hover them they are not absolutely selectable. It's kinda buggy.
Is it even possible to create this with no images?
EDIT:
The menu will after by animated using jQuery; thus I will be using jQuery and jQuery UI but no other library and no images (i dont need the icons anyway). As for compatibility, should work on IE9+ / Chrome / Opera 11.52+ / Firefox 4+.
Solution 1:[1]
The following is a way to do it with HTML canvas, and it detects where the mouse is perfectly. It doesn't look the exact same as yours though, and I didn't add the icons or dividing lines (although anti-aliasing allows the background to show through a little between regions creating the illusion of lines being drawn).
http://jsfiddle.net/jcubed111/xSajL/
Edit - Bug Fix: http://jsfiddle.net/jcubed111/xSajL/2/
With more work you could make the canvas version look the same as your mock-up, my version is only to get the functionality down.
You could also make it look right with css, then overlay a clear a to detect mouse position and provide linking functionality. Of course, then you couldn't use :hover to change the look of the regions.
I've tested in Chrome 19 only.
Here's the full code below in case the link goes down:
HTML:
<a id='link'><canvas id='c' width='224' height='224' onmousemove="update(event);"></canvas></a>
<input id='i' />????????
CSS:
#c{
width:224px;
height:224px;
}?
JS (run on page load and uses jquery):
ctx = $('#c')[0].getContext('2d');
function update(E) {
ctx.clearRect(0, 0, 224, 224);
if (E === false) {
mx = 112;
my = 112;
} else {
mx = E.clientX;
my = E.clientY;
}
mangle = (-Math.atan2(mx-112, my-112)+Math.PI*2.5)%(Math.PI*2);
mradius = Math.sqrt(Math.pow(mx - 112, 2) + Math.pow(my - 112, 2));
$('#i').val("Not over any region");
$('#link').attr('href', '');
for (i = 0; i < 8; i++) {
angle = -Math.PI / 8 + i * (Math.PI / 4);
if (((mangle > angle && mangle < (angle + Math.PI / 4)) || (mangle > Math.PI*15/8 && i==0)) && mradius<=112 && mradius>=69) {
ctx.fillStyle="#5a5a5a";
$('#i').val("In region "+i);
$('#link').attr('href', '#'+i);
} else {
ctx.fillStyle="#4c4c4c";
}
ctx.beginPath();
ctx.moveTo(112, 112);
//ctx.lineTo(112+Math.cos(angle)*112, 112+Math.sin(angle)*112);
ctx.arc(112, 112, 112, angle, angle + Math.PI / 4, false);
ctx.lineTo(112, 112);
ctx.fill();
}
ctx.fillStyle = "#f2f2f2";
ctx.beginPath();
ctx.arc(112, 112, 69, 0, 2 * Math.PI, false);
ctx.fill();
}
update(false);?
Solution 2:[2]
It could be done with regular HTML+CSS, but for the sake of your sanity, don't even try. It's not worth it.
You'd be far better off doing stuff like this in Canvas or SVG. Especially if you don't need to support older versions of IE.
For both Canvas and SVG solutions, I recommend finding a suitable library. In the SVG world, I strongly recommend Raphael. For Canvas, mayby try Paper. You could get the basics up and running with either of these libraries in just a handful of lines of code.
If you must do this in CSS (maybe that's the criteria for your project, or maybe you're just a glutton for punishment), you'll need to start with using border-radius to make the circle. Then draw the segmentation line using 1px-wide boxes, and rotate them using transform. You get the picture; it's not easy, as you've probably already discovered. And getting the thing animated is going to be complete nightmare. It can be done, and as a demonstration piece of what can be achieved in CSS, it would be very clever. But when all your target browsers support SVG and Canvas, doing stuff like this in CSS really is just being clever for the sake of being clever.
Solution 3:[3]
HTML Code
<a class='button ctrl' href='#' tabindex='1'>?</a>
<ul class='tip ctrl'>
<li class='slice'><div>?</div></li>
<li class='slice'><div>?</div></li>
<li class='slice'><div>?</div></li>
<li class='slice'><div>?</div></li>
<li class='slice'><div>?</div></li>
</ul>
CSS Code
.ctrl {
position: absolute;
top: 75%; left: 50%;
font: 1.5em/1.13 Verdana, sans-serif;
transition: .5s;
}
a.ctrl, .ctrl div {
display: block;
opacity: .56;
background: #c9c9c9;
color: #7a8092;
text-align: center;
text-decoration: none;
text-shadow: 0 -1px dimgrey;
cursor: pointer;
}
.button {
z-index: 2;
margin: -.625em;
width: 1.25em; height: 1.25em;
border-radius: 50%;
box-shadow: 0 0 3px 1px white;
}
.tip {
z-index: 1;
/**outline: dotted 1px white;/**/
margin: -5em;
width: 10em; height: 10em;
transform: scale(.001);
list-style: none;
opacity: 0;
}
.slice {
overflow: hidden;
position: absolute;
/**outline: dotted 1px yellow;/**/
width: 50%; height: 50%;
transform-origin: 100% 100%;
}
Full code : CSSCodeLab
Solution 4:[4]
It depends on a couple of things. First, do you need the menu to be animated? Second do you need to strictly use css? Do you need the menu to work perfectly aligned?
If you don't need something 100% exact you could use divide the circle into small squares and use only css to accomplish it.
If you need it to be 100% exact and you don't have animations, you can try <map> map
If you want animations and 100% exact then you most likely be needing something like RaphaelJS
Hope it helps you out.
Solution 5:[5]
You can check the code of a lot of similar built-in menu libraries.
NGX Circular menu: Here's a sample using angular with custom CSS/SCSS. You can simple plug it in your application and use it: https://www.npmjs.com/package/ngx-circular-menu
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Spudley |
| Solution 3 | Pacific P. Regmi |
| Solution 4 | KoU_warch |
| Solution 5 | Evan MJ |
