JavaScript Math to dynamically shift elements within a div for fit

I’m working on a card game in JS. The player’s cards are dynamically displayed as elements inside a div of a set width. As cards are added to the player’s hand, I’m using right: % and z-index to shift all cards left and have them overlap each other, thereby making room to display more cards within the div (which is set to white-space: nowrap so content inside it won't break to a new line).

I’m using JS to calculate and set the percentage for the cards to shift left, based on each card’s original position and the total number of cards that need to be displayed.

The general plan is working, but I’m having trouble figuring out how to calculate a percentage that will work for any number of cards. Ideally, I'd like the cards to shift left just enough so that no matter how many there are they never extend outside the div but always fill it completely.

I thought the following would work:

function displayHand(cards) {
  for(var i = 0; i < cards.length; i++) {
    var cardDiv = document.createElement("div");
    document.getElementById(“playerHand”).appendChild(cardDiv);
    if(cards.length > 7) {
      cardDiv.setAttribute("style", "z-index: " + i + "; right: " 
        + (i * cards.length) * (0.04815 * cards.length) + "%");
    }
}

However, I seem to be getting this formula wrong: (i * cards.length) * (0.04815 * cards.length). (Note that the 0.04815 number came from tinkering and trying to get the percentage right.)

By increasing the 0.04815 number I can make a small number of cards (i.e. 8-12) fit well but a larger number will be shifted much too close together, filling only a small portion of the div. If I decrease the number, 12 cards will overflow the div but a larger number will fit well inside it.

Answer:1

The problem comes from the fact that you don't need the first card to move. Your cards.length factor is too high.

Instead, you need only consider cards.length-1.

For instance, let's say I can fit in two cards exactly. To add a third card, I would need to move the cards left for a total of 1 card width by the time two cards (after the first) have been placed. That is, at 50% and 100%. Adding a fourth card would result in the cards being shifted at 1/3, 2/3 and 3/3. And so on.

So it should simply be a case of moving it by i * (cards.length-1) * (card width here)

Answer:2

I'm trying to use an example of fixed-data-table, and bundle it with webpack. I'm using babel-loader and my code otherwise bundles without issues. Running webpack points to an error which to my ...

I'm trying to use an example of fixed-data-table, and bundle it with webpack. I'm using babel-loader and my code otherwise bundles without issues. Running webpack points to an error which to my ...

I'm new to coding and I replaced some repetitive HTML with JavaScript and now the images, which used to display 4 across, are no longer displaying horizontally. They now display on the left only. I've ...

I'm new to coding and I replaced some repetitive HTML with JavaScript and now the images, which used to display 4 across, are no longer displaying horizontally. They now display on the left only. I've ...

  1. replacing html with jquery
  2. replacing html with javascript
  3. replacing html text with javascript
  4. replacing html tables with divs

How do I find vertices positions of a mesh after I used .fromGeometry(); code? I created a buffergeometry from a geomtery that I used for a mesh. Here is an example. var geom = new THREE.BoxGeometry(...

How do I find vertices positions of a mesh after I used .fromGeometry(); code? I created a buffergeometry from a geomtery that I used for a mesh. Here is an example. var geom = new THREE.BoxGeometry(...

Here is my input <input type="text" class="ChampionInput" list="champions" name="champion[]"`placeholder="Champion" required> And here is my js document.forms["first_form_champions"].oninput ...

Here is my input <input type="text" class="ChampionInput" list="champions" name="champion[]"`placeholder="Champion" required> And here is my js document.forms["first_form_champions"].oninput ...

  1. firefox displays html code instead of page