You can use CSS rotation to put each circle in its correct position without having to do any geometrical calculatons yourself.
For example, in this snippet we have 10 items, each 15% the width of the parent container and 50% high. Each starts at the top, center of the parent but they are rotated depending on their position as a child.
The main trick is to rotate them about the same point, the center of the parent container.
The second thing we then need to do is rotate the contents of each circle back by an equivalent amount so the text (and images if you have them) in each circle appears vertical to the reader.
In this snippet the CSS variable –num is set to the number of circles. All the required angles of rotation can be then calculated within CSS.
This snippet gives this result – each item has been given a border to make it clearer what is happening.
.bigCircle {
--num: 10;
width: 90vmin;
aspect-ratio: 1 / 1;
position: relative;
margin: 0;
padding: 0;
}
.bigCircle .item {
box-sizing: border-box;
width: 15%;
height: 50%;
border: 1px solid black;
position: absolute;
left: 50%;
transform: translateX(-50%) rotate(calc(360deg / var(--num) * (var(--n) - 1)));
transform-origin: center bottom;
top: 0;
margin: 0;
padding;
0;
}
.bigCircle .item:nth-child(1) {
--n: 1;
}
.bigCircle .item:nth-child(2) {
--n: 2;
}
.bigCircle .item:nth-child(3) {
--n: 3;
}
.bigCircle .item:nth-child(4) {
--n: 4;
}
.bigCircle .item:nth-child(5) {
--n: 5;
}
.bigCircle .item:nth-child(6) {
--n: 6;
}
.bigCircle .item:nth-child(7) {
--n: 7;
}
.bigCircle .item:nth-child(8) {
--n: 8;
}
.bigCircle .item:nth-child(9) {
--n: 9;
}
.bigCircle .item:nth-child(10) {
--n: 10;
}
.circle {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%) rotate(calc(-360deg / var(--num) * (var(--n) - 1)));
width: 100%;
aspect-ratio: 1 / 1;
border-radius: 50%;
border: solid 5px red;
justify-content: center;
align-items: center;
flex-direction: column;
display: flex;
}
<div class="bigCircle">
<div class="item">
<div class="circle">1</div>
</div>
<div class="item">
<div class="circle">2</div>
</div>
<div class="item">
<div class="circle">3</div>
</div>
<div class="item">
<div class="circle">4</div>
</div>
<div class="item">
<div class="circle">5</div>
</div>
<div class="item">
<div class="circle">6</div>
</div>
<div class="item">
<div class="circle">7</div>
</div>
<div class="item">
<div class="circle">8</div>
</div>
<div class="item">
<div class="circle">9</div>
</div>
<div class="item">
<div class="circle">10</div>
</div>
</div>
Now we want to add the lines and small dot going from the edge of each circle towards the center of the container.
There are various ways to do this, including background images. This snippet uses pseudo elements to draw from the bottom of a circle towards the center of the container. Obviously you will want to change the dimensions of things to suit your use case.
.bigCircle {
--num: 10;
width: 90vmin;
aspect-ratio: 1 / 1;
position: relative;
margin: 0;
padding: 0;
}
.bigCircle .item {
box-sizing: border-box;
width: 15%;
height: 50%;
position: absolute;
left: 50%;
transform: translateX(-50%) rotate(calc(360deg / var(--num) * (var(--n) - 1)));
transform-origin: center bottom;
top: 0;
margin: 0;
padding;
0;
}
.bigCircle .item:nth-child(1) {
--n: 1;
}
.bigCircle .item:nth-child(2) {
--n: 2;
}
.bigCircle .item:nth-child(3) {
--n: 3;
}
.bigCircle .item:nth-child(4) {
--n: 4;
}
.bigCircle .item:nth-child(5) {
--n: 5;
}
.bigCircle .item:nth-child(6) {
--n: 6;
}
.bigCircle .item:nth-child(7) {
--n: 7;
}
.bigCircle .item:nth-child(8) {
--n: 8;
}
.bigCircle .item:nth-child(9) {
--n: 9;
}
.bigCircle .item:nth-child(10) {
--n: 10;
}
.circle {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
aspect-ratio: 1 / 1;
border-radius: 50%;
border: solid 5px red;
display: flex;
justify-content: center;
align-items: center;
}
.circle::before {
content: '';
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
width: 2px;
height: calc(100% - 15%);
background-color: red;
}
.circle::after {
content: '';
position: absolute;
top: calc(100% + 100% - 15%);
width: 10px;
aspect-ratio: 1 / 1;
background: red;
border-radius: 50%;
}
.circleContent {
position: absolute;
justify-content: center;
align-items: center;
flex-direction: column;
display: flex;
transform: translateX(-50%) rotate(calc(-360deg / var(--num) * (var(--n) - 1)));
}
<div class="bigCircle">
<div class="item">
<div class="circle">
<div class="circleContent">1</div>
</div>
</div>
<div class="item">
<div class="circle">
<div class="circleContent">2</div>
</div>
</div>
<div class="item">
<div class="circle">
<div class="circleContent">3</div>
</div>
</div>
<div class="item">
<div class="circle">
<div class="circleContent">4</div>
</div>
</div>
<div class="item">
<div class="circle">
<div class="circleContent">5</div>
</div>
</div>
<div class="item">
<div class="circle">
<div class="circleContent">6</div>
</div>
</div>
<div class="item">
<div class="circle">
<div class="circleContent">7</div>
</div>
</div>
<div class="item">
<div class="circle">
<div class="circleContent">8</div>
</div>
</div>
<div class="item">
<div class="circle">
<div class="circleContent">9</div>
</div>
</div>
<div class="item">
<div class="circle">
<div class="circleContent">10</div>
</div>
</div>
</div>