PolGraphic
PolGraphic

Reputation: 3364

How to achive certain overlapping layout when there is not enough space in parent container?

I have <div class="parent" style="position: relative; width: 100%; height: 25vh;">...</div> that contains some amount of <div class="child"></div> elements (the number of them vary between sub-pages). As you see the size of .parent is known but not fixed. The .child size is fixed to e.g. 100px x 170px.

When there is enough space for all children in .parent, I want to place them one next to another, row by row (it's easy with e.g. float: left;): enter image description here

But when there are too many children for .parent, I want the excessive elements to be put "above" others, with small offset (so we can see that there's something below them - in a bit similar way to a Patience card game):

enter image description here

Note the order and that those excessive elements don't have to be on any "layer"/z-index, they should just overlap the divs that are before them.

Also, there is none fixed number of cards per row, as the .parent width is 100% of client width.

How can I achieve such behavior with CSS, without JavaScript (I know I could just compute absolute x/y based on child's index in JavaScript)?

Upvotes: 1

Views: 59

Answers (1)

Matt Greenberg
Matt Greenberg

Reputation: 2330

I believe I found a pure CSS solution that might work for you. From what I understand, you the Parent Div container and a random number of child divs that represent cards.

Disclaimer: I used pixels for this to show proof of concept, but the same effect can be done by using all percents if you work out the math.

Basic HTML Layout

// I am using the <!-- comments --> to remove whitespace between divs
// This is important because we don't want to being floating elements
// So each pixel is going to count
<div class="parent">
     <div class="child">card 1</div><!--
  --><div class="child">card 2</div><!--
  --><div class="child">card 3</div><!--
  --><div class="child">card 4</div><!--
  --><div class="child">card 5</div><!--
  --><div class="child">card 6</div>
</div>

For demonstration purposes, I made the cards a nice 100px by 150px. This just helps visual the math in my opinion. Here is the basic CSS we need to layout the field.

CSS

// normalize div elements
*{ box-sizing: border-box; margin: 0; padding: 0; }

.parent{
  position: relative;
  width: 480px; //4 cards wide with 10px of margin on each side (4*100)+(4*20)
  background: blue;
  height: 340px;
  overflow:hidden;
  margin: 0px auto;
}
.child{
  position: relative;
  width: 100px;
  height: 150px;
  border:1px solid #000;
  background: #333;
  color: white;
  margin: 10px;
  display: inline-block;
}

Now that the grid is setup, we just need to move the third and forth row up.

One of the great things about CSS is you can apply styles to elements that may of may not exist on the page. Using the nth-child selector will help us target these unknown elements.

MOAR CSS

.child:nth-child(n+9){
  // move cards from their origin up 330px and left 5px
  transform: translateY(-330px) translateX(-5px);
}

The only thing you need is to create enough rules to match the multiple outcomes you may have.

Example: I need to support a possibility of 18 cards. Just add another rule!

.child:nth-child(n+17){
  // all we have to do is double the increments
  transform: translateY(-660px) translateX(-10px);
}

Hope that helps.

Working JSFiddle

Upvotes: 1

Related Questions