web-dev-qa-db-fra.com

Faire en sorte que les éléments flexibles se chevauchent

Je voudrais montrer une série horizontale d'un nombre inconnu de cartes à jouer. Pour ce faire, ils devront se chevaucher s’il y en a trop. J'ai du mal à convaincre une boîte souple de faire chevaucher les cartes sans les réduire. L'exemple ci-dessous rétrécit les cartes. J'ai essayé flex-shrink: 0, mais alors max-width n'était pas respecté.

.cards {
  display: flex;
  max-width: 300px;
}

.card {
  width: 50px;
  height: 90px;
  border: 1px solid black;
  border-radius: 3px;
  background-color: rgba(255, 0, 0, 0.4);
}
<div class='cards'>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
</div>

7
Michael Arrison

Vous pouvez créer un chevauchement d'éléments avec une structure flexible à l'aide de transform: translateX(-10px), mais cela ne résoudra pas la disposition que vous essayez d'obtenir. Je ne pense pas que vous puissiez faire cela dans Flexbox. Mais vous pouvez facilement le faire avec JS.

var parentEl = document.getElementById("cards");

function sortCards() {
  var cards = document.getElementsByClassName("card"),
      cw = parentEl.clientWidth,
      sw = parentEl.scrollWidth,
      diff = sw - cw,
      offset = diff / (cards.length - 1);

  for (var i = 0; i < cards.length; i++) {
    i != 0 && (cards[i].style.transform = "translateX(-" + offset * i + "px)");
  }
}

sortCards();

var b = document.getElementById("button");
b.addEventListener("click", function() {
  var div = document.createElement("div");
  div.classList.add("card");
  parentEl.appendChild(div);
  sortCards();
});
.cards {
  display: flex;
  max-width: 300px;
}

.card {
  height: 90px;
  border: 1px solid black;
  border-radius: 3px;
  background-color: rgba(255, 0, 0, 0.4);
  flex: 0 0 50px;
  background: red;
  transition: transform .25s;
}
<div><button id="button">addcards</button></div>
<div class='cards' id="cards">
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
</div>

11
Michael Coker

Voici comment je ferais cela en utilisant flexbox.

.cards {
  display: flex;
  align-content: center;
  max-width: 35em;
}

.cardWrapper {
  overflow: hidden;
}

.cardWrapper:last-child, .cardWrapper:hover {
    overflow: visible;
}

.card {
    width: 10em;
    min-width: 10em;
    height: 6em;
    border-radius: 0.5em;
    border: solid #666 1px;
    background-color: #ccc;
    padding: 0.25em;
  
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}
<div class="cards">
  <div class="cardWrapper">
    <div class="card">card 1 blah blah blah</div>
  </div>
  <div class="cardWrapper">
    <div class="card">card 2 blah blah blah</div>
  </div>
  <div class="cardWrapper">
    <div class="card">card 3 blah blah blah</div>
  </div>
  <div class="cardWrapper">
    <div class="card">card 4 blah blah blah</div>
  </div>
  <div class="cardWrapper">
    <div class="card">card 5 blah blah blah</div>
  </div>
</div>

Notez que techniquement, les cartes ne se chevauchent pas, elles sont simplement en train d'être coupées. Mais ils ont l'air comme s'ils se chevauchaient. L'astuce consiste à envelopper chaque carte dans un autre élément avec débordement: caché.

Les éléments d’emballage sont réduits pour s’adapter à l’espace disponible et un maximum de cartes est affiché dans cet espace.

J'inclus la règle: hover juste pour montrer comment afficher complètement une carte du milieu de la "pile", mais dans un vrai projet, je le ferais probablement pour des cartes sélectionnées plutôt que pour celles survolées.

8
FTWinston

Un conteneur flexible est conçu pour aligner des éléments le long des axes X et Y. 

Vous parlez d'alignement le long de l'axe Z.

La Flexbox n’est pas conçue pour l’alignement sur l’axe des z (superposition). 

Tout chevauchement devrait provenir de marges négatives, de positionnement absolu, de CSS Grid Layout, de JavaScript ou de quelque chose d'autre. La propriété z-index peut également avoir besoin de jouer un rôle.

Voici un exemple de base utilisant CSS Grid:

.cards {
  display: grid;
  grid-template-columns: repeat(30, 10px);
  grid-template-rows: 90px;
  max-width: 300px;
}

.card {
  grid-row-start: 1;
  background-color: lightgreen; 
  border: 1px solid black;
}

.card:nth-child(1) { grid-column: 1 / 6; }
.card:nth-child(2) { grid-column: 4 / 9; }
.card:nth-child(3) { grid-column: 7 / 12; }
.card:nth-child(4) { grid-column: 10 / 15; }
.card:nth-child(5) { grid-column: 13 / 18; }
.card:nth-child(6) { grid-column: 16 / 21; }
.card:nth-child(7) { grid-column: 19 / 24; }
.card:nth-child(8) { grid-column: 22 / 27; }
.card:nth-child(9) { grid-column: 25 / 30; }
<div class='cards'>
  <div class='card'>1</div>
  <div class='card'>2</div>
  <div class='card'>3</div>
  <div class='card'>4</div>
  <div class='card'>5</div>
  <div class='card'>6</div>
  <div class='card'>7</div>
  <div class='card'>8</div>
  <div class='card'>9</div>
</div>

Les cartes se chevauchent en utilisant un placement basé sur les lignes. Dans ce cas, la propriété grid-column est utilisée pour faire en sorte que les pistes de colonnes se chevauchent.

Néanmoins, certains scripts seraient nécessaires si le nombre de cartes variait de manière dynamique, car la quantité de chevauchement devrait varier afin que toutes les cartes s’insèrent parfaitement dans le conteneur à largeur fixe.

3
Michael_B

Je suis venu avec une solution générique, basée sur CSS. Cependant, avec quelques mises en garde:

  1. La dernière carte déborde du conteneur .cards.
  2. Un élément enfant de .card est nécessaire pour produire l'effet de chevauchement.

.cards {
  display: flex;
  max-width: 300px;
}

.card {
  position: relative;
  flex-basis: 50px;
  height: 90px;
}

.card::before {
  content: '';
  display: block;
  position: absolute;
  width: 50px;
  height: 100%;
  border: 1px solid black;
  border-radius: 3px;
  background-color: rgba(255, 0, 0, 0.4);
  box-sizing: border-box;
}
<div class='cards'>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
</div>

2
Nate Whittaker

Vous pouvez le faire en utilisant seulement css en utilisant grid au lieu de flex.

.hand{
  width: 50%;
  margin-left: auto;
  margin-right: auto;
  justify-content: center;
  display: grid;
  grid-template-columns: repeat(auto-fit,  minmax(10px, max-content)) ;
}
.card{
  width: 3em;
  height: 2.4em;
  padding: 3px;
  margin: 2px;
  background-color: lightgreen;
  border-style: solid;
  transform: rotate(3deg);  /*makes it easier to see the overlap*/
}
<div class="hand"> 
  <div class="card"> card </div>
  <div class="card"> card </div>
  <div class="card"> card </div>
  <div class="card"> card </div>
  <div class="card"> card </div>
  <div class="card"> card </div>
  <div class="card"> card </div>
  <div class="card"> card </div>
</div>

2
Max Garber

div.card-area
{
    height: 16vh; /* whatever */
    display: flex;
}
div.card-area > div
{
    flex: 1 0 0;
    overflow-x: hidden;
}
div.card-area > div:last-of-type
{
    flex: 0 0 auto;
}
div.card-area img
{
    height: 100%;
}
<div class="card-area N">
    <div><img src="img/cards/AH.png"></div>
    <div><img src="img/cards/KH.png"></div>
    <div><img src="img/cards/QH.png"></div>
    <div><img src="img/cards/JH.png"></div>
    <div><img src="img/cards/10H.png"></div>
    <div><img src="img/cards/9H.png"></div>
    <div><img src="img/cards/8H.png"></div>
    <div><img src="img/cards/7H.png"></div>
    <div><img src="img/cards/6H.png"></div>
    <div><img src="img/cards/5H.png"></div>
    <div><img src="img/cards/4H.png"></div>
    <div><img src="img/cards/3H.png"></div>
    <div><img src="img/cards/2H.png"></div>
</div>

0
Cuse70