Размещение элементов на странице по кругу
Всем привет! Не получается разместить карточки по кругу:
.cards_wrapper {
display: flex;
justify-content: space-between;
align-items: flex-end;
flex-direction: column;
position: absolute;
top: 20%;
right: 15%;
}
.card {
width: 61px;
height: 52px;
text-align: center;
}
.card_title,
.card_rating {
margin: 0;
}
.card:nth-child(1) {
transform: translateX(50deg);
}
<section class="cards">
<div class="container">
<div class="cards_wrapper">
<div class="card">
<img class="card_img" src="images/profile2.1.png" alt="">
<h4 class="card_title">Иванов Сергей</h4>
<p class="card_rating">4.9</p>
</div>
<div class="card">
<img class="card_img" src="images/profile2.1.png" alt="">
<h4 class="card_title">Иванов Сергей</h4>
<p class="card_rating">4.9</p>
</div>
<div class="card">
<img class="card_img" src="images/profile2.1.png" alt="">
<h4 class="card_title">Иванов Сергей</h4>
<p class="card_rating">4.9</p>
</div>
<div class="card">
<img class="card_img" src="images/profile2.1.png" alt="">
<h4 class="card_title">Иванов Сергей</h4>
<p class="card_rating">4.9</p>
</div>
<div class="card">
<img class="card_img" src="images/profile2.1.png" alt="">
<h4 class="card_title">Иванов Сергей</h4>
<p class="card_rating">4.9</p>
</div>
</div>
</div>
Как сделать вот такое размещение?
Ответы (2 шт):
Один из вариантов верстки: Взять position: relative блок размером 0x0 px, расположив его по центру, вставить в него необходимое количество картинок position: absolute, указывая им соответствующие координаты в top: px; left: px;
Но было бы приятно не считать их руками, а чтобы JS сам всё посчитал и вставил для любого количества картинок)
Для справки:
Т.к. в браузере ось y перевернута (y растет в направлении «вниз»), нужно будет брать отрицательные значения: - R * sin(a). Изменение знака x будет влиять на расположение «по» часовой стрелке или «против».
Реализация (сохранена исходная разметка карточек из вопроса, текст не выровнен):
(function() {
let data = [
{ name: 'a', rate: 1, src: 'https://imgur.com/PXsAs3a.png' },
{ name: 'b', rate: 2, src: 'https://imgur.com/PXsAs3a.png' },
{ name: 'c', rate: 3, src: 'https://imgur.com/PXsAs3a.png' },
{ name: 'd', rate: 4, src: 'https://imgur.com/PXsAs3a.png' },
{ name: 'e', rate: 5, src: 'https://imgur.com/PXsAs3a.png' },
];
/***/
const R = 80;
const IMG_SIZE = 40;
/***/
let parent = document.querySelector(".js-center");
for (let i = 0; i < data.length; i++) {
let radian = i * (2 * Math.PI / data.length) - 0.5 * Math.PI;
let x = R * Math.cos(radian) - IMG_SIZE / 2;
let y = R * Math.sin(radian) - IMG_SIZE / 2;
let params = Object.assign({x, y}, data[i]); // (*1)
create_card(params);
}
/***/
function create_card(obj) {
let root = document.createElement("div");
let img_style = `style="width: ${IMG_SIZE}px; height: ${IMG_SIZE}px;"`;
root.innerHTML = (`
<div class="card">
<img class="card_img" src="${obj.src}" ${img_style}>
<h4 class="card_title">${obj.name}</h4>
<p class="card_rating">${obj.rate}</p>
</div>
`);
let card = root.firstElementChild;
card.style.left = obj.x + "px";
card.style.top = obj.y + "px";
parent.appendChild(card);
}
})();
.js-center {
position: relative;
width: 0;
height: 0;
margin: 80px;
}
.card {
position: absolute;
}
.card_img {
border-radius: 50%;
border: 2px solid orange;
}
.circle {
position: relative;
width: 160px;
height: 160px;
margin: 40px;
border: 5px solid #f50;
border-radius: 50%;
}
<div class="circle">
<div class="js-center"></div>
</div>
(*1) let params = Object.assign({x, y}, data[i]);
{ x: x, y: y } создание такого объекта можно сократить до {x, y}, в случае, если название ключа совпадает с названием переменной, использованной как значение. Object.assign добавляет все свойства из объекта data[i] в первый объект. Получается объект с ключами { x, y, name, rate, src }, который передается как параметр функции.
Лучше было бы, если задействовать SVG и JS, но т.к. в метках вопроса указаны только HTML и CSS, то вот Вам приближенный вариант:
body {
margin: 0;
height: 100vh;
background-color: #fff;
display: flex;
justify-content: space-around;
align-items: center;
}
.cards_wrapper {
position: relative;
height: 485px; width: 485px;
font: bold 11px/1em "Arial", sans-serif;
background-image: radial-gradient( circle at center, #fff0 53px, #fff 54px, #fff 57px, #abd2ee 58px, #abd2ee 60px, #fff 61px, #fff 106px, #d5e1ec 107px, #d5e1ec 143px, #fff0 144px, #fff0 169px, #d5e1ec 170px, #d5e1ec 172px, #fff0 173px), url(https://thispersondoesnotexist.com/image);
background-position: 0 0, center;
background-size: auto, 110px;
background-repeat: no-repeat;
}
.cards_wrapper::before {
content: "";
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: calc(100% - 66px);
height: calc(100% - 66px);
box-sizing: border-box;
border-radius: 50%;
border: 3px dashed #d5e1ec;
}
.cards_wrapper::after {
content: "★ 4.9";
position: absolute;
top: 50%; left: 50%;
transform: translate(50%, -66px);
padding: 6px 12px;
box-sizing: border-box;
border-radius: 4px;
background-color: #4facf1;
color: #fff;
}
.angle_wrapper {
position: absolute;
left: calc(50% - 50px);
height: 50%;
transform-origin: 50% 100%;
}
.angle_wrapper:nth-child(2) { transform: rotate(60deg); }
.angle_wrapper:nth-child(3) { transform: rotate(120deg); }
.angle_wrapper:nth-child(4) { transform: rotate(180deg); }
.angle_wrapper:nth-child(5) { transform: rotate(240deg); }
.angle_wrapper:nth-child(6) { transform: rotate(300deg); }
.card {
position: relative;
display: inline-flex;
flex-flow: column nowrap;
justify-content: start;
align-items: center;
text-align: center;
height: 100px; width: 100px;
transform-origin: 50% 33px;
}
.angle_wrapper:nth-child(2) .card { transform: rotate(-60deg); }
.angle_wrapper:nth-child(3) .card { transform: rotate(-120deg); }
.angle_wrapper:nth-child(4) .card { transform: rotate(-180deg); }
.angle_wrapper:nth-child(5) .card { transform: rotate(-240deg); }
.angle_wrapper:nth-child(6) .card { transform: rotate(-300deg); }
.card_img {
width: 66px; height: 66px;
box-sizing: border-box;
border-radius: 50%;
border: 3px solid #d5e1ec;
}
.card_title, .card_rating {
margin: 0;
color: #696d78;
}
.card_rating {
position: absolute;
top: 0; right: 0;
padding: 4px;
border-radius: 4px;
background-color: #abd2ee;
}
<section class="cards">
<div class="container">
<div class="cards_wrapper">
<div class="angle_wrapper">
<div class="card">
<img class="card_img" src="https://thispersondoesnotexist.com/image" alt="">
<h4 class="card_title">Иванов Сергей</h4>
<p class="card_rating">★ 4.9</p>
</div>
</div>
<div class="angle_wrapper">
<div class="card">
<img class="card_img" src="https://thispersondoesnotexist.com/image" alt="">
<h4 class="card_title">Иванов Сергей</h4>
<p class="card_rating">★ 4.9</p>
</div>
</div>
<div class="angle_wrapper">
<div class="card">
<img class="card_img" src="https://thispersondoesnotexist.com/image" alt="">
<h4 class="card_title">Рождественский Сергей</h4>
<p class="card_rating">★ 4.9</p>
</div>
</div>
<div class="angle_wrapper">
<div class="card">
<img class="card_img" src="https://thispersondoesnotexist.com/image" alt="">
<h4 class="card_title">Иванов Сергей</h4>
<p class="card_rating">★ 4.9</p>
</div>
</div>
<div class="angle_wrapper">
<div class="card">
<img class="card_img" src="https://thispersondoesnotexist.com/image" alt="">
<h4 class="card_title">Ким Ли</h4>
<p class="card_rating">★ 4.9</p>
</div>
</div>
<div class="angle_wrapper">
<div class="card">
<img class="card_img" src="https://thispersondoesnotexist.com/image" alt="">
<h4 class="card_title">Иванов Сергей</h4>
<p class="card_rating">★ 4.9</p>
</div>
</div>
</div>
</div>
</section>

