Mayeenul Islam
Mayeenul Islam

Reputation: 4762

Circular-like dynamic menu - CSS3

I'm using LESS. I designed my <li>s, with every proceedings, taking a different id with a PHP loop. And in CSS I've written a code like:

  li.page-2{
    margin-left: 15px;
  }

  li.page-3{
    margin-left: 25px;
  }

  li.page-4{
    margin-left: 22px;
  }

  li.page-5{
    margin-left: 18px;
  }

  ...

I've two questions regarding this, so, first of all, I want to share my intention: Circular Menu Design

I want to design a dynamic circular menu like this.

Q#1: How can I minimize the CSS coding dynamically, as I'm actually first, increasing the value, and after some places, decreasing the value of margin-left.
Q#2: Is there any other way I can do such circular dynamic menu?

Upvotes: 1

Views: 1620

Answers (3)

KennyV
KennyV

Reputation: 832

The best way is to use some simple JavaScript as described here:

Animated radial menu with CSS3 and JavaScript

var items = document.querySelectorAll('.circle a');

for(var i = 0, l = items.length; i < l; i++) {
  items[i].style.left = (50 - 35*Math.cos(-0.5 * Math.PI - 2*(1/l)*i*Math.PI)).toFixed(4) + "%";

  items[i].style.top = (50 + 35*Math.sin(-0.5 * Math.PI - 2*(1/l)*i*Math.PI)).toFixed(4) + "%";
}

document.querySelector('.menu-button').onclick = function(e) {
   e.preventDefault(); document.querySelector('.circle').classList.toggle('open');
}

You can use CSS3 to animate the menu, still (this is better, performance-wise). You could add any number of elements and the JS will position them dynamically

Upvotes: 1

Shiva Avula
Shiva Avula

Reputation: 1836

Creating redundant css styles for dynamic code is not a good practice. I suggest you to look into the javascript way. If anyone wants the JS way look into this approach. I have written the code in Jquery.

HTML

<ul id='circularMenu'>
    <li>Page 1</li>
    <li>Page 2</li>
    <li>Page 3</li>
    <li>Page 4</li>
    <li>Page 5</li>
    <li>Page 6</li>
</ul>

Javascript

var childCount = $('#circularMenu li').length();
var diff = 10; // The difference in margin for each item
var marginLeft = 0;
var currentChild = 1;

$('#circularMenu li').each(function(){
    //Skip condition, as we style this element within center elements section
    if(childCount%2 && currentChild == Math.ceil(childCount/2)) coutinue; 

    //Top half of the menu where margin is increased
    if(currentChild < childCount/2) {
        marginLeft += diff;
        this.css('margin-left', marginLeft+'px');
    }

    //Bottom half of the menu where margin is decreased
    else if(currentChild > childCount/2) {
        marginLeft -= diff;
        this.css('margin-left', marginLeft+'px');
    }

    //The center element, this is tricky as there can be one or two center elements
    else if(currentChild == Math.floor(childCount/2)) {
        marginLeft += diff;
        this.css('margin-left', marginLeft+'px');
        if(childCount%2){
            this.next().css('margin-left', marginLeft+'px');
        }
    }
});

This is untested code, there might be some errors. Please comment for any issues. The above code can be minified a lot, i just elaborated so you can understand the concept.

Upvotes: -1

Mr. Alien
Mr. Alien

Reputation: 157334

You can anyways minify this using LESS or SASS, as far as traditional CSS goes, than use CSS Positioning techniques to achieve so..

Demo

Explanation : Here, am using position: relative; container, further nesting absolute span elements which I later position using top and left properties.


If you are creating dynamic menus, than you need to nudge the nth elements using LESS as and when the menu items increase.

HTML

<div>
    <span>Page 1</span>
    <span>Page 2</span>
    <span>Page 3</span>
    <span>Page 4</span>
    <span>Page 5</span>
</div>

CSS

div {
    height: 150px;
    width: 150px;
    margin: 100px;
    border: 2px solid #000;
    border-radius: 50%;
    position: relative;
}

div span {
    font-family: Arial;
    font-size: 12px;
    position: absolute;
    width: 100px;
}

div span:nth-of-type(1) {
    left: 135px;
}

div span:nth-of-type(2) {
    left: 155px;
    top: 30px;
}

div span:nth-of-type(3) {
    left: 160px;
    top: 60px;
}

div span:nth-of-type(4) {
    left: 155px;
    top: 90px;
}

div span:nth-of-type(5) {
    left: 145px;
    top: 120px;
}

Upvotes: 1

Related Questions