Конечный результат, который я хочу, — это это , а результат, который я могу получить, — это это.
По сути, я хочу, чтобы карты перекрывались с фиксированной шириной, когда они переполняют своего родителя. И когда он не переполнен, я хочу, чтобы они сохраняли ширину в соответствии с соотношением сторон. Я зафиксировал высоту, поэтому ширина также должна быть постоянной.
Вы можете нажать на каждую карточку и она будет удалена в каждой ссылке. Но во второй/не рабочей ссылке карта становится слишком большой и это тоже проблема.
Как я могу это решить?
<div class = "container">
<div class = "player player-1"> p1 </div>
<div class = "card_area card_area-1">card-1</div>
<div class = "player player-2">p2</div>
<div class = "card_area card_area-2">card-2</div>
<div class = "player player-3">p3</div>
<div class = "card_area card_area-3">card-3</div>
<div class = "player player-4">p4</div>
<div id = "render_cards" class = "card_area card_area-4">
<div class = "card card-odd card-1">card-1</div>
<div class = "card card-even card-2">card-2</div>
<div class = "card card-odd card-3">card-3</div>
<div class = "card card-even card-4">card-4</div>
<div class = "card card-odd card-5">card-5</div>
<div class = "card card-even card-6">card-6</div>
<div class = "card card-odd card-7">card-7</div>
<div class = "card card-even card-8">card-8</div>
<div class = "card card-odd card-9">card-9</div>
<div class = "card card-even card-10">card-10</div>
<div class = "card card-odd card-11">card-11</div>
<div class = "card card-even card-12">card-12</div>
<div class = "card card-odd card-13">card-13</div>
</div>
</div>
.container {
width: 60%;
margin: 5px auto;
border: 2px solid green;
aspect-ratio: 3/2;
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: repeat(6, minmax(0, 1fr));
}
.player {
display: flex;
align-items: center;
justify-content: center;
background-color: bisque;
}
.player-1 {
grid-row: 1;
grid-column: 3;
}
.card_area-1 {
grid-row: 1;
grid-column: 4;
}
.player-2 {
grid-row: 4;
grid-column: 6;
}
.card_area-2 {
grid-row: 3;
grid-column: 6;
}
.player-3 {
grid-row: 3;
grid-column: 1;
}
.card_area-3 {
grid-row: 4;
grid-column: 1;
}
.player-4 {
grid-row: 6;
grid-column: 2;
}
.card_area-4 {
grid-row: 6;
grid-column: 3/6;
}
.card_area {
background-color: rgb(232, 127, 127);
}
.card:hover {
background-color: aqua;
}
.card-odd {
background-color: gray;
}
.card-even {
background-color: darkkhaki;
}
.card_area-4 {
width: 100%;
}
.card:last-child {
flex: 0 0 auto;
}
.card {
flex: 1;
aspect-ratio: 2/3;
text-align: center;
height: 110%;
transform: translateY(-10%);
flex-start: start;
min-width: 100px;
max-width: auto;
}
.card {
display: flex;
justify-content: center;
align-items: center;
}
.card_area-4 {
display: flex;
justify-content: center;
}
let cards = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
const card_els = Array.from(document.getElementsByClassName("card"));
console.info(cards)
card_els.forEach((card) => {
card.addEventListener("click", (e) => {
e.target.remove();
console.info("haha")
});
});
Вы не можете перекрывать гибкие элементы напрямую, но вы можете добавлять к этим гибким элементам абсолютно позиционированные дочерние элементы, и эти дочерние элементы могут перекрываться.
Таким образом, вы можете получить довольно хорошее решение CSS, используя дополнительный элемент-оболочку для каждой карточки. Внешний элемент каждой карты позиционируется и сжимается с помощью flexbox; внутренний элемент позиционируется абсолютно и имеет фиксированную ширину, что приводит к перекрытию (это то, что вам нужно).
Карты подходят к контейнеру примерно, но не совсем. Я добавил в контейнер правый отступ размером 50 пикселей (две трети ширины одной карточки), чтобы карточки подходили для большинства сценариев. Чтобы получить точное соответствие, нам потребуется рассчитать правильное заполнение на основе количества карточек, находящихся в контейнере; это невозможно в CSS. Но приблизительного соответствия, вероятно, будет достаточно для ваших целей.
body {
background: #888;
}
.cards {
display: flex;
margin-bottom: 1em;
border: 3px dashed white;
width: 250px;
color: white;
justify-content: start;
padding-right: 50px;
}
.cards > div {
height: 100px;
flex-basis: 75px;
position: relative;
border: 3px solid black;
box-sizing: border-box;
}
.cards > div > div {
position: absolute;
top: 0;
left: 0;
width: 75px;
height: 100%;
transform: rotate(-5deg);
padding: 5px;
box-sizing: border-box;
}
.cards > div:nth-child(odd) > div {
background: #ff0000df;
}
.cards > div:nth-child(even) > div {
background: #0000ffdf;
}
.wider {
width: 350px;
}
<!-- 5 cards -->
<div class = "cards">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<!-- 5 cards -->
<div class = "cards">
<div><div>1</div></div>
<div><div>2</div></div>
<div><div>3</div></div>
<div><div>4</div></div>
<div><div>5</div></div>
</div>
<!-- 8 cards -->
<div class = "cards">
<div><div>1</div></div>
<div><div>2</div></div>
<div><div>3</div></div>
<div><div>4</div></div>
<div><div>5</div></div>
<div><div>6</div></div>
<div><div>7</div></div>
<div><div>8</div></div>
</div>
<!-- 11 cards -->
<div class = "cards">
<div><div>1</div></div>
<div><div>2</div></div>
<div><div>3</div></div>
<div><div>4</div></div>
<div><div>5</div></div>
<div><div>6</div></div>
<div><div>7</div></div>
<div><div>8</div></div>
<div><div>9</div></div>
<div><div>10</div></div>
<div><div>11</div></div>
</div>
<!-- 8 cards in a wider container -->
<div class = "cards wider">
<div><div>1</div></div>
<div><div>2</div></div>
<div><div>3</div></div>
<div><div>4</div></div>
<div><div>5</div></div>
<div><div>6</div></div>
<div><div>7</div></div>
<div><div>8</div></div>
</div>
<!-- 4 cards in a wider container -->
<div class = "cards wider">
<div><div>1</div></div>
<div><div>2</div></div>
<div><div>3</div></div>
<div><div>4</div></div>
</div>
Для получения совершенно точных результатов вы можете использовать Javascript, чтобы точно определить, сколько карточек находится в каждом контейнере, и рассчитать точное смещение для каждой из них.
document.querySelectorAll('.contained').forEach(c => {
const cards = Array.from(c.children)
// calculate the total width of the cards, assuming they are all same width
const widthOfCards = cards[0].clientWidth * cards.length
// calculate the offset as the difference between the total width of the cards and the width of the container, divided by one less than the number of cards
const offset = (widthOfCards - c.clientWidth) / (cards.length - 1)
c.insertAdjacentHTML('afterbegin', `<span>container: ${c.clientWidth}<br>cards: ${widthOfCards}<br>offset: ${offset > 0 ? Math.round(offset * 1000) / 1000 : 'none'}</span>`)
// if the container is wider than the cards, no adjustment is necessary
if (offset <= 0) return
for (i = 0; i < cards.length; i++) {
const x = cards[i]
x.style.left = `${-1 * i * offset}px`
}
})
body {
background: #888;
}
.cards {
display: flex;
margin-bottom: 1em;
border: 3px dashed white;
width: 250px;
color: white;
position: relative;
}
.cards > div {
width: 75px;
height: 100px;
transform: rotate(-5deg);
flex-shrink: 0;
padding: 5px;
box-sizing: border-box;
}
.cards > div:nth-child(odd) {
background: #ff0000df;
}
.cards > div:nth-child(even) {
background: #0000ffdf;
}
.contained > div {
position: relative;
}
.wider {
width: 350px;
}
.cards > span {
font-size: 0.8em;
position: absolute;
left: 1em;
bottom: 1em;
z-index: 1;
}
<!-- normal scenario, cards overflow container -->
<div class = "cards">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
<!-- 5 cards contained -->
<div class = "cards contained">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
<!-- 8 cards contained -->
<div class = "cards contained">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
</div>
<!-- 8 cards contained in a wider container -->
<div class = "cards contained wider">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
</div>
<!-- 4 cards contained in a wider container -->
<div class = "cards contained wider">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
</div>
Я разработал решение CSS и обновил свой ответ. Решение CSS работает довольно хорошо, но дает лишь приблизительные, а не точные результаты. Если вам достаточно приблизительной подгонки, возможно, это то, что вам нужно.
Привет, спасибо за ответ. Я сделал то же самое, что вы сделали по первой прикрепленной мной ссылке. Но мне нужно, чтобы это было сделано только с помощью CSS. Проблема в том, что я визуализирую интерфейс из бэкэнда (для точности я использую Phoenix LiveView).