По клику на div сделать его поверх остальных

Есть несколько дивов с абсолютным позиционированием и накладываающиеся друг на друга. Я пытаюсь сделать так, чтобы при нажатии на div он становился поверх остальных.

 let divs = document.querySelectorAll("div");
  for (const div of divs) {
    div.addEventListener("click", function () {
      console.log(div.style.position);
      if (div.style.position === "absolute")
        div.style.position = "relative";
      else div.style.position = "absolute";
    });
  }
  <div style="background-color: 'red'; position: absolute">vfvf</div>
<div style="position: absolute">dasdasdasdasdasd</div>

Я пытался и через z-index, и так как в коде выше, но, видимо, я невнимательно читаю документацию, ибо ничего не получатся


Ответы (5 шт):

Автор решения: Dev18

по-моему надо использовать z-index, чтоб div был поверх остальных div-ов

let divs = document.querySelectorAll("div");
let maxZIndex = 1; //максимальный z-index

for (const div of divs) {
  div.addEventListener("click", function() {
    maxZIndex++; //увеличиваем индекс
    div.style.zIndex = maxZIndex;
  });
}
div {
  width: 100px;
  height: 100px;
  position: absolute;
}

.red {
  background-color: red;
  top: 50px;
  left: 50px;
}

.blue {
  background-color: blue;
  top: 100px;
  left: 100px;
}

.green {
  background-color: green;
  top: 150px;
  left: 150px;
}
<div class="red">Red</div>
<div class="blue">Blue</div>
<div class="green">Green</div>

→ Ссылка
Автор решения: stylok

Для того, чтобы элемент оказался поверх других можно обойтись и без индексного позиционирования, если манипулировать DOM.

С учётом того, что изначально все div свалены в body... достаточно и такого кода.

document.addEventListener('click', (e) => {
  if(e.target.localName === 'div') document.body.append(e.target);
});
div {
  width: 100px;
  height: 100px;
  position: absolute;
}
.red {
  background-color: red;
  top: 50px;
  left: 50px;
}
.blue {
  background-color: blue;
  top: 100px;
  left: 100px;
}
.green {
  background-color: green;
  top: 150px;
  left: 150px;
}
.gold {
  background-color: gold;
  top: 200px;
  left: 200px;
}
<div class="red">Red</div>
<div class="gold">Gold</div>
<div class="green">Green</div>
<div class="blue">Blue</div>

В случае с близкими к реальности условиями, когда есть обёртка, то одной строкой больше:

const wrapper = document.querySelector('.wrapper')
wrapper.addEventListener('click', (e) => {
  wrapper.append(e.target)
});
div {
  width: 100px;
  height: 100px;
  position: absolute;
}
.red {
  background-color: red;
  top: 50px;
  left: 50px;
}
.blue {
  background-color: blue;
  top: 100px;
  left: 100px;
}
.green {
  background-color: green;
  top: 150px;
  left: 150px;
}
.gold {
  background-color: gold;
  top: 200px;
  left: 200px;
}
<div class="wrapper">
  <div class="red">Red</div>
  <div class="gold">Gold</div>
  <div class="green">Green</div>
  <div class="blue">Blue</div>
</div>

→ Ссылка
Автор решения: Owlly

Использование DOM-иерархии (перемещение элемента в конец контейнера) - один из простых способов поднять элемент поверх остальных — это переместить его в конец контейнера (родительского элемента). Визуально он окажется выше других элементов, так как в HTML порядок рендера элементов сверху вниз.

let divs = document.querySelectorAll("#container div");

for (const div of divs) {
  div.addEventListener("click", function() {
    div.parentNode.appendChild(div); // Перемещаем элемент в конец контейнера
  });
}
div {
  width: 100px;
  height: 100px;
  position: absolute;
}

.red {
  background-color: rgb(167, 8, 8);
  top: 50px;
  left: 50px;
}

.blue {
  background-color: rgb(13, 13, 152);
  top: 100px;
  left: 100px;
}

.green {
  background-color: rgb(10, 189, 10);
  top: 150px;
  left: 150px;
}
<div id="container">
  <div class="red">Div 1</div>
  <div class="blue">Div 2</div>
  <div class="green">Div 3</div>
</div>

→ Ссылка
Автор решения: Andrei Fedorov

Не уверен, что я правильно понял задание, вроде просили без z-index. Вот что получилось. В chrome и ff работает.

const item1 = document.querySelector(".item:nth-child(1)");
const item2 = document.querySelector(".item:nth-child(2)");
const item3 = document.querySelector(".item:nth-child(3)");
const item4 = document.querySelector(".item:nth-child(4)");

const items = document.querySelectorAll(".item");

function clearActive() {
  items.forEach((item) => {
    item.classList.remove("active");
  });
}

item1.addEventListener("click", () => {
  clearActive();
  item1.classList.add("active");
});

item2.addEventListener("click", () => {
  clearActive();
  item2.classList.add("active");
});

item3.addEventListener("click", () => {
  clearActive();
  item3.classList.add("active");
});

item4.addEventListener("click", () => {
  clearActive();
  item4.classList.add("active");
});
.box {
  display: flex;
  width: 500px;
  height: 500px;
  align-items: flex-start;
}

.item:nth-child(1) {
  background-color: #f25022;
}

.item:nth-child(2) {
  background-color: #7fba00;
  translate: -100px 100px;
}

.item:nth-child(3) {
  background-color: #01a4ef;
  translate: -200px 200px;
}

.item:nth-child(4) {
  background-color: #c83232;
  translate: -300px 300px;
}

.item {
  min-width: 200px;
  min-height: 200px;
}

.active {
  order: 1;
}

.item:nth-child(1).active {
  translate: -600px 0;
}

.item:nth-child(1).active+.item {
  translate: 100px 100px;
}

.item:nth-child(1).active+.item+.item {
  translate: 0 200px;
}

.item:nth-child(1).active+.item+.item+.item {
  translate: -100px 300px;
}

.item:nth-child(2).active {
  translate: -500px 100px;
}

.item:nth-child(2).active+.item {
  translate: 0 200px;
}

.item:nth-child(2).active+.item+.item {
  translate: -100px 300px;
}

.item:nth-child(3).active {
  translate: -400px 200px;
}

.item:nth-child(3).active+.item {
  translate: -100px 300px;
}
<div class="box">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

UPDATE: После замечаний от коллеги @stylok небольшой апдейт. Вот так немного получше. Селекторы классов работают быстрее, однако :nth-child удобнее при сборке кода.

const box = document.querySelector(".box");
box.addEventListener("click", (e) => {
  document.querySelector(".box > .active").classList.remove("active");
  e.target.classList.add("active");
});
.box {
  display: flex;
  align-items: flex-start;
  width: 500px;
  height: 500px;
}

.box>div {
  min-width: 200px;
  min-height: 200px;
}

.active {
  order: 1;
}

.red {
  background-color: #f25022;
}

.green {
  background-color: #7fba00;
  translate: -100px 100px;
}

.blue {
  background-color: #01a4ef;
  translate: -200px 200px;
}

.brown {
  background-color: #c83232;
  translate: -300px 300px;
}

.red.active {
  translate: -600px 0;
}

.active~.green {
  translate: 100px 100px;
}

.green.active {
  translate: -500px 100px;
}

.active~.blue {
  translate: 0 200px;
}

.blue.active {
  translate: -400px 200px;
}

.active~.brown {
  translate: -100px 300px;
}
<div class="box">
  <div class="red"></div>
  <div class="green"></div>
  <div class="blue"></div>
  <div class="brown active"></div>
</div>

UPDATE_2: Еще немного улучшил, выяснив, что order работает и в grid, но позиционирование элементов при этом облегчается.

const box = document.querySelector(".box");
box.addEventListener("click", (e) => {
  if (e.target.parentNode === box) {
    document.querySelector(".box > .active").classList.remove("active");
    e.target.classList.add("active");
  }
});
.box {
  display: grid;
  grid-template: repeat(5, 1fr)/repeat(5, 1fr);
  width: 500px;
  height: 500px;
}

.active {
  order: 1;
}

.red {
  background-color: #f25022;
  grid-area: 1/1/3/3;
}

.green {
  background-color: #7fba00;
  grid-area: 2/2/4/4;
}

.blue {
  background-color: #01a4ef;
  grid-area: 3/3/5/5;
}

.brown {
  background-color: #c83232;
  grid-area: 4/4/6/6;
}
<div class="box">
  <div class="red"></div>
  <div class="green"></div>
  <div class="blue"></div>
  <div class="brown active"></div>
</div>

UPDATE3: Спасибо @puffleeck натолкнул на хорошую мысль, только предлагаю использовать не :focus, а :target.

.box {
  display: grid;
  grid-template: repeat(5, 1fr) / repeat(5, 1fr);
  width: 500px;
  height: 500px;
}

.box>a:target {
  order: 1;
}

#red {
  background-color: #f25022;
  grid-area: 1/1/3/3;
}

#green {
  background-color: #7fba00;
  grid-area: 2/2/4/4;
}

#blue {
  background-color: #01a4ef;
  grid-area: 3/3/5/5;
}

#brown {
  background-color: #c83232;
  grid-area: 4/4/6/6;
}
<div class="box">
  <a href="#red" id="red"></a>
  <a href="#green" id="green"></a>
  <a href="#blue" id="blue"></a>
  <a href="#brown" id="brown"></a>
</div>

→ Ссылка
Автор решения: puffleeck

как на счет фокуса? © джокер

.box {
  display: grid; width: 600px; height: 150px;
  grid-template: repeat(7, 1fr)/repeat(7, 1fr);
}
.box >*:nth-child(3n+2):focus{
  transform: translateZ(1px);
  display: list-item;
  list-style: 'та да! он приподнялся!' inside;
}
.box >*:nth-child(3n+1):hover{filter: hue-rotate(180deg);}
.box >*:nth-child(3n+1):hover:after{content: "может метод от противно...положного?";}
.box >*:nth-child(3n):active{order: 2;}
.box >*:nth-child(3n):active:before{content: "FREEZE! у меня ORDER на ваш экран!";}

i{background: pink;grid-area: 1/1/3/3;}
.violet{background: violet;grid-area: 6/6/8/8;}
.red {
  background-color: #f25022;
  grid-area: 2/2/4/4;
}
.green {
  background-color: #7fba00;
  grid-area: 3/3/5/5;
}
.blue {
  background-color: #01a4ef;
  grid-area: 4/4/6/6;
}
.brown {
  background-color: #c83232;
  grid-area: 5/5/7/7;
}
<div class="box">
  <i>Feel the magic of pure CSS</i>
  <div tabindex='1' class="red"></div>
  <div tabindex='2' class="green"></div>
  <div tabindex='3' class="blue"></div>
  <div tabindex='4' class="brown"></div>
  <div tabindex='5' class="violet"></div>
</div>

p.s. в целом тут копия последнего варианта от @Andrei Fedorov, но с некоторыми бонусами :3

→ Ссылка