Как перекрывать гибкие элементы фиксированной ширины?

Конечный результат, который я хочу, — это это , а результат, который я могу получить, — это это.

По сути, я хочу, чтобы карты перекрывались с фиксированной шириной, когда они переполняют своего родителя. И когда он не переполнен, я хочу, чтобы они сохраняли ширину в соответствии с соотношением сторон. Я зафиксировал высоту, поэтому ширина также должна быть постоянной.

Вы можете нажать на каждую карточку и она будет удалена в каждой ссылке. Но во второй/не рабочей ссылке карта становится слишком большой и это тоже проблема.

Как я могу это решить?

<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")
  });
});
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
2
0
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете перекрывать гибкие элементы напрямую, но вы можете добавлять к этим гибким элементам абсолютно позиционированные дочерние элементы, и эти дочерние элементы могут перекрываться.

Таким образом, вы можете получить довольно хорошее решение 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. Проблема в том, что я визуализирую интерфейс из бэкэнда (для точности я использую Phoenix LiveView).

lorem1213 20.07.2024 12:55

Я разработал решение CSS и обновил свой ответ. Решение CSS работает довольно хорошо, но дает лишь приблизительные, а не точные результаты. Если вам достаточно приблизительной подгонки, возможно, это то, что вам нужно.

Brett Donald 22.07.2024 03:28

Другие вопросы по теме