Home > Blockchain >  How to stack divs by click on image
How to stack divs by click on image

Time:05-09

Is there any way to make a div appear stacked on top of another one, by clicking on a button/image?

The problem I have:
I want a poster to appear if I click on it in the selector.
I want it to stay, once I click on another poster, which then will stack on top of the previous one.
Is it possible to make this a loop, so no matter how often I click different objects the old divs will always stay below the newest one?

(See pictures attached)

first click: enter image description here

second click: enter image description here

and so on...

Thanks in advance!

CodePudding user response:

  1. Create a div called preview, and makes its position relative. This is necessary because this creates a new stacking context.
  2. Create another container that will hold the list of images to choose from. I choose a section with an unordered list which will contain these images as list elements.
  3. Set overflow-x auto, so a scrollbar appears once the amount of images exceed the container width.
  4. In your stylesheet, select the images which are child of our preview div, and make their position absolute, with a top margin of 0. This makes sure that all images are stacked in the same x-y direction. This works because the preview div also has display: flex, with align-items: center as well as justify-content: center.
  5. In your script file, select these list images - I called them posters.
const posters = document.querySelectorAll(".poster");
  1. Create two variables called zIndex ( = 1) and rotated ( = true).
  2. Attach an event listener to each of the poster image inside this list of images, using a for...of loop.
for (const poster of posters) {
  poster.addEventListener("click", () => onPosterClicked(poster));
}
  1. In this event handler, we select the preview div, and clone the clicked image using cloneNode() method. We also give it class of shown so, our styling for images inside preview work.
  2. We then increment the z-index, and assign this incremented z-index to this cloned image's style.
cloned.style.zIndex =   zIndex;
  1. For decorational purposes, we switch between rotated and non-rotated transforms, so each image new image added is rotated differently to our previous image.
if (rotated) {
    cloned.style.transform = "rotate(-5deg)";
}
rotated = !rotated;

Note: We can achieve this rotation directly through CSS, by using nth-child selectors.

  1. Finally, we append this cloned image to our preview div.
preview.appendChild(cloned);

The complete code looks like this:

function onPosterClicked(poster) {
  const preview = document.querySelector(".preview");
  const cloned = poster.cloneNode();
  cloned.classList = "shown";
  cloned.style.zIndex =   zIndex;

  if (rotated) {
    cloned.style.transform = "rotate(-5deg)";
  }
  rotated = !rotated;
  preview.appendChild(cloned);
}

const posters = document.querySelectorAll(".poster");
let zIndex = 1;
let rotated = true;

for (const poster of posters) {
  poster.addEventListener("click", () => onPosterClicked(poster));
}
*,
*::before,
*::after {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

body {
  width: 100%;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.preview {
  width: 100%;
  height: 70vh;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.shown {
  height: 100%;
  position: absolute;
  top: 0;
  border: 2px solid black;
}

.list {
  width: 100%;
  padding: 4rem 2rem;
}

.list ul {
  display: flex;
  flex-flow: row nowrap;
  gap: 5px;
  overflow-x: auto;
  list-style: none;
}

.poster {
  max-height: 300px;
  object-fit: cover;
}
<body>
  <div >
    <img  src="https://picsum.photos/seed/picsum/200/300" alt="test image" />
  </div>
  <section >
    <ul>
      <li>
        <img  src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
      </li>
      <li>
        <img  src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
      </li>
      <li>
        <img  src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
      </li>
      <li>
        <img  src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
      </li>
      <li>
        <img  src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
      </li>
      <li>
        <img  src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
      </li>
      <li>
        <img  src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
      </li>
      <li>
        <img  src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
      </li>
    </ul>
  </section>
  <script async defer src="main.js"></script>
</body>

CodePudding user response:

I will cut down the explaination to some documentations such as how to create an element through JS. Teachign every single step would blow the scope of Stackoverflow.

If you know how to create an element through JS you need a variable such as counter in my code that is raised by every single time you run the script with: counter = counter 1

You set a z-index through JS with element.style.zIndex = variableand thanks to the rising counter it will set the new element over the other element (z-axis-wise).

To rotate the element you can use transform: rotate() which I randomized by calling a variable: rotation = Math.round(Math.random() * 40 - 20); which will randomize a number between -20 and 20.

var preview = document.querySelector('.preview'),
    counter = '1';
    picture = ''
    
function addRed() {
  picture = 'red';
  addPicture();
}

function addGreen() {
  picture = 'green';
  addPicture();
}

function addBlue() {
  picture = 'blue';
  addPicture();
}

function addYellow() {
  picture = 'yellow';
  addPicture();
}

function addPicture() {
  var img = document.createElement('img'),
      rotation = Math.round(Math.random() * 40 - 20);
  switch (picture) {
    case 'red':
      img.src = 'https://via.placeholder.com/350.jpg/FF0000';
      break;
    case 'green':
      img.src = 'https://via.placeholder.com/350.jpg/00FF00';
      break;
    case 'blue':
      img.src = 'https://via.placeholder.com/350.jpg/0000FF';
      break;
    case 'yellow':
      img.src = 'https://via.placeholder.com/350.jpg/FFFF00';
      break;
  }
  img.style.position = 'absolute';
  img.style.top = '50%';
  img.style.left = '50%';
  img.style.transform = 'translate(-50%, -50%) rotate('   rotation   'deg)';
  img.style.zIndex = counter;  
  preview.appendChild(img);
  
  var counter = counter   1;
}
.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-gap: 10px;
}

.preview {
  grid-column: 1 / -1;
  aspect-ratio: 1 / 1;
  position: relative;
}

.selector {
  padding: 10px;
}

.selector > img {
  display: block;
  object-fit: contain;
  width: 100%;
}
<div >
  <div ></div>
  <div ><img src="https://via.placeholder.com/100.jpg/FF0000" onclick="addRed()"></div>
  <div ><img src="https://via.placeholder.com/100.jpg/00FF00" onclick="addGreen()"></div>
  <div ><img src="https://via.placeholder.com/100.jpg/0000FF" onclick="addBlue()"></div>
  <div ><img src="https://via.placeholder.com/100.jpg/FFFF00" onclick="addYellow()"></div>
</div>

  • Related