работа с DOM js анимация

моих знаний основ на js не достаточно , чтобы реализовать следующее: на странице есть несколько раскрывающихся блоков и нужно добавить небольшую анимацию переворота стрлки на 180 градусов , сейчас я реализовал это так : я добавил обработчик событий на блок в котором есть та самая анимированная стрелка и с помощью метода toggle при клике добавляю и удаляю класс в котором пописан стиль rotate(180 deg) , работает , но только для первого блока (обращался к ним по общему классу) вопрос: как задействовать все эти элемента но чтобы они анимировались все только при клике , писать функцию для каждого точно не вариант , так что я пришел спросить как такое реализуется


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

Автор решения: OPTIMUS PRIME

>> learn.javascript.ru/

Это решается самым обычным циклом...

let arrow = document.querySelectorAll('.arrow');

for( let i = 0; i < arrow.length; i++ ) {
  arrow[i].addEventListener('click', function() {
    this.classList.toggle('rotate');
  });
}
.arrow {
  display: inline-block;
  color: red;
  font-size: 100px;
  line-height: 100px;
  
  transition: 0.5s;  
  cursor: pointer;
}

.arrow:hover {
  color: #800;
}

.arrow.rotate {
  transform: rotate(180deg);
}
<div class="arrow">▼</div>
<div class="arrow">▼</div>
<div class="arrow">▼</div>
<div class="arrow">▼</div>

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

JSFiddle / CodePen

// Выбираем все стрелки в пределах .block
const arrows = document.querySelectorAll('.block .arrow');

// Перебираем все стрелки и вызываем при клике обработчик
arrows.forEach(arrow => arrow.onclick = arrowClickHandle);

// Обработчик
function arrowClickHandle() {
	// Выбираем родительский .block
	const block = this.closest('.block');
	// Выбираем блок .content
	const content = block.querySelector('.content');
	
	// Проверяем есть ли активный класс у элемента
	const isActive = block.classList.contains('active');
	
	// Переключаем класс
	block.classList.toggle('active');
	
	// Анимируем появление/исчезновение блока
	gsap.fromTo(content, {
		height: isActive ? content.scrollHeight : 0
	},{
		duration: 0.5,
		height: isActive ? 0 : content.scrollHeight
	});
}
.block {
	margin-bottom: 20px;
	font-family: Arial;
}

.arrow {
  display: inline-block;
  color: #2ecc71;
  font-size: 30px;
  line-height: 30px;
  user-select: none;
  transition: transform 0.5s, color 0.5s;
  cursor: pointer;
  transform: rotate(-90deg);
}

.content {
	width: 50%;
	height: 0;
	overflow: hidden;
}

.block.active .arrow {
  transform: rotate(0deg);
  color: #e74c3c;
}

.block.active .content {
	height: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js"></script>
<div class="block">
	<div class="arrow">▼</div>
	<div class="content">
		Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda quos, tempore in harum. Officiis nisi aliquam nemo consequuntur, illo, quidem quos eaque vitae velit ratione repellat reprehenderit officia asperiores in.
	</div>
</div>
<div class="block active">
	<div class="arrow">▼</div>
	<div class="content">
		Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda quos, tempore in harum. Officiis nisi aliquam nemo consequuntur, illo, quidem quos eaque vitae velit ratione repellat reprehenderit officia asperiores in.
	</div>
</div>
<div class="block">
	<div class="arrow">▼</div>
	<div class="content">
		Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda quos, tempore in harum. Officiis nisi aliquam nemo consequuntur, illo, quidem quos eaque vitae velit ratione repellat reprehenderit officia asperiores in.
	</div>
</div>

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

Для решения вашей задачи JavaScript не требуется вообще! Всё можно сделать нативным HTML/CSS:

details {
  position: relative;
  margin-bottom: 0.5rem;
  min-height: 1rem;
  max-height: 3rem;
  transition: min-height 0.15s linear, max-height 0.5s linear;
  will-change: max-height;
  overflow: hidden;
}
details summary {
  display: inline-block;
  padding-left: 1.5em;
  transition: color 0.12s;
}
details summary span {
  border-bottom: 1px currentColor dotted;
}
details summary::before {
  content: "";
  left: 0;
  top: 1px;
  position: absolute;
  background: url("data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjM0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIzNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNOC41OSAxNi4zNGw0LjU4LTQuNTktNC41OC00LjU5TDEwIDUuNzVsNiA2LTYgNnoiLz48L3N2Zz4=") no-repeat 50% 50%/1em 1em;
  width: 1em;
  height: 1em;
  transition: transform 0.1s linear;
}
details summary:hover {
  color: #d06c6c;
}
details summary ~ * {
  padding-left: 1.5em;
  opacity: 0;
  transition: opacity 0.15s linear;
}
details[open] {
  min-height: 2em;
  max-height: 20em;
}
details[open] summary {
  color: #d06c6c;
}
details[open] summary ~ * {
  opacity: 1;
}
details[open] summary:before {
  transform: rotate(90deg);
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/godlike.css/3.7.2/godlike.min.css" rel="stylesheet">

<details>
<summary tabindex="1"><span>Кликни на меня!</span></summary>
<p>Я открываюсь нативно без JavaScript и библиотек для анимаций!</p>
</details>

<details>
<summary tabindex="2"><span>В меня можно поместить картинку!</span></summary>
<p><img src="//picsum.photos/100/100/?random" alt="Картинка"></p>
</details>

<details>
<summary tabindex="3"><span>И моя разметка семантически верная для поисковиков!</span></summary>
<p><b>Lorem Ipsum</b> is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever <i>since the 1500s</i>, when an unknown printer took a galley of type and scrambled it to make a type...</p>
</details>

Более того, используя семантически верные теги мы можем улучшить видимость нашей вёрстки для поисковиков.

Также описанные предыдущими ораторами подходы полностью императивны, но в современной разработке хорошим тоном является использование декларативного подхода.

→ Ссылка