The combination of flexible elements

I would like to show a horizontal series of an unknown number of playing cards. To do this, they will have to intersect if there are too many of them. I'm having trouble convincing a flexible box to overlay cards without compressing them. The example below compresses cards. I tried flex-shrink: 0 , but then max-width not respected.

 .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> 
+6
source share
7 answers

You can create elements in the overlay of the flexible layout with transform: translateX(-10px) , but this will not affect the layout you are trying to get. I do not think you can do this in flexbox. But you can easily do this with 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
source

This is how I will do it with 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> 

Please note that from a technical point of view, the cards do not overlap, they are simply cut off. But they seem to overlap. The trick is to wrap each card in a different element using overflow: hidden.

The wrapping elements are reduced to fit the available space, and as many maps as possible are displayed in that space.

I include the rule: hover, to show how you can fully display the map from the middle of the "stack", but in a real project I will probably do this for the selected maps instead of freezing ones.

+7
source

The flexible container is designed to align elements along the X and Y axes.

You are asking for alignment on the Z axis.

Flexbox is not designed to align with the z axis (overlap).

Any overlap should occur with negative margins, absolute positioning, CSS, JavaScript grid layout, or something else. The z-index property may also need a role.

Here is a basic example using 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> 

Cards are made for overlapping using linear placement. In this case, the grid-column property is used to overlap the column paths.

However, some scripts will be required if the number of cards changes dynamically, since the number of overlaps must change so that all cards match exactly in a container with a fixed width.

+3
source

I came up with a general CSS-based solution. However, with a few caveats:

  • The last card overflows the .cards container.
  • To create an overlap effect, you need a child element .card .

 .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> 
+1
source

You can do this using only CSS, using grid instead of 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> 
+1
source

 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
source

You can do this using the margin property and apply to the elements you want, manually or JS.

 .cards { display: flex; max-width: 300px; } .overl { margin-left:-10px; } .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 overl'></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> 
-1
source

All Articles