It can be quite challenging to place items on a circle with CSS. Usually, we end up relying on JavaScript because some plugins do it all right away. However more often than not there is no good reason to do it in JavaScript rather than CSS. This is presentational purpose, let's go the CSS way.
The Mixin
Ana Tudor explained how she managed to do it in a Stack Overflow answer, using chained CSS transforms. Thereafter I turned her solution into a Sass mixin to make everything a breeze.
/// Mixin to place items on a circle
/// @author Hugo Giraudel
/// @author Ana Tudor
/// @param {Integer} $item-count - Number of items on the circle
/// @param {Length} $circle-size - Large circle size
/// @param {Length} $item-size - Single item size
@mixin on-circle($item-count, $circle-size, $item-size) {
position: relative;
width: $circle-size;
height: $circle-size;
padding: 0;
border-radius: 50%;
list-style: none;
> * {
display: block;
position: absolute;
top: 50%;
left: 50%;
width: $item-size;
height: $item-size;
margin: -($item-size / 2);
$angle: (360 / $item-count);
$rot: 0;
@for $i from 1 through $item-count {
&:nth-of-type(#{$i}) {
transform:
rotate($rot * 1deg)
translate($circle-size / 2)
rotate($rot * -1deg);
}
$rot: $rot + $angle;
}
}
}
Caution! Vendor prefixes have been omitted from this code snippet. Be sure to prefix transform
if you do not use Autoprefix.
Demo
For demo purposes, we'll consider a list of 8 images but basically anything could work.
<ul class='circle-container'>
<li><img src='http://lorempixel.com/100/100/city' alt="..." /></li>
<li><img src='http://lorempixel.com/100/100/nature' alt="..." /></li>
<li><img src='http://lorempixel.com/100/100/abstract' alt="..." /></li>
<li><img src='http://lorempixel.com/100/100/cats' alt="..." /></li>
<li><img src='http://lorempixel.com/100/100/food' alt="..." /></li>
<li><img src='http://lorempixel.com/100/100/animals' alt="..." /></li>
<li><img src='http://lorempixel.com/100/100/business' alt="..." /></li>
<li><img src='http://lorempixel.com/100/100/people' alt="..." /></li>
</ul>
.circle-container {
@include on-circle($item-count: 8, $circle-size: 20em, $item-size: 6em);
margin: 5em auto 0;
border: solid 5px tomato;
img {
display: block;
max-width: 100%;
border-radius: 50%;
filter: grayscale(100%);
border: solid 5px tomato;
transition: .15s;
&:hover,
&:active {
filter: grayscale(0);
}
}
}
See the Pen Items on circle by Hugo Giraudel (@HugoGiraudel) on CodePen.
this is good but no working in IE
It is actually fairly easy to do in IE. Check the original article: http://hugogiraudel.com/2013/04/02/items-on-circle/.
Is it possible to position this item’s using Bootstrap grid system?
Thanks for this article Hugo, it’s really cool. Is there a way to position an image in the middle of the circle?
Never mind – I just found you Centering With Sass article. You’re my new favourite writer :)
Hugo,
I love this example, it helped greatly in an experiment I am doing where I have a angular data set that may require any where from one element in the circle to eight. Therefore I put some additional logic in the SASS to generate c1 through c8 where the number is the amount of circles.
http://codepen.io/stegel/details/RWqpwO/
I noticed that if I add an n+1 element, it gets automatically centered. Was that intentional?
What I am trying to figure it how to animate one of the outside elements moving to the center. Do you have any suggestions on this?
Nice article Hugo, thanks! I was wondering how can we make the element rotate along the circle with out giving rotate transform to the parent wrapper.
thats a cool circle!, but i need to know…is it possible to pass parameters from html to the ‘@include on-circle($item-count: 8, $circle-size: 20em, $item-size: 6em);’ fanction?, lets say i want to control tha value of ‘item-count’, how can i do this?
where is the variable $i defined ?
It is working good. But I have a Problem! I applied CSS Animation to the entire container and it was working. But I can’t apply Animations for the elements inside the circle. what I haveto do now?
I am trying to place 6 divs around circle and text showing when hovering on the divs.
I have this: https://jsfiddle.net/zwsck7gm/2/
and this: http://jsfiddle.net/ytwL7g81/ but I am having difficulty to merge them into one thing.
Can you please help.
Thanks a lot Hugo & Ana , this snippet saved me a lot of headaches and pointed me to the right direction!