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 Kitty 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);
}
}
}
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?
hello sir can you help me how to rotate this circle automatic
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?
you can change here:
$item-count: 8 e.g. $item-count: 10
and add another line(s): to
<
ul> -> …
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!
Hi, any chance to get this spinning in circle while maintaining objects orientation?
Hey Matteo! You could try adding an animation to the container that rotates it. https://codepen.io/geoffgraham/pen/LajvrK
If you want to extend this beautiful design to next level, you can play with the angle of the circle.
| $angle: (360 / $item-count);
190 degrees will make like a neckless.
680 degrees will make a circle with two nodes at 4 equal sections.
Hi.
I looked so much around for a solution like that, that’s amazing. Look at the example ok this page, how can I have some text in the middle of the circle and having it changing by clicking on each item? See example on this page, scroll little down
https://kriesi.at/
Thanks for this technique! I have updated it to make it fully responsive by not depending on the circle size nor item size nor item count. You can check out here: https://codepen.io/sntran/pen/rNVoEZB
The mixin is in LESS instead of Sass because I’m more familiar with it, but the logic is the same. A few techniques to make it possible:
Use
height: 0; padding-bottom: 100%
to make the responsive circle.Make
item-size
a percentage of the circle’s diameter.Use quantity queries (https://alistapart.com/article/quantity-queries-for-css/#section5) to have rules based on actual number of items in the listing.
Enjoy!
is it possible to make this circle responsive so it deosnt expand the page when viewing from a mobile device for example?
I have also need for that. I might have to go down the JavaScript route
I’ve not seen an example anywhere that is truly responsive yet. All examples I’ve been seeing have a fixed-width of the overall height/width.
It is either too small for desktop or too big for phones.
Anyone got a post CSS version of this?
You can click the button “View Compiled” at the center Bottom to get the vanilla CSS
Here’s a LESS version of the items on a circle