Как сделать плавное открытие карточек?

Как сделать плавное появление карточек по клику на кнопку?

const showMore = document.querySelector('.btn-download');
const cards = document.querySelectorAll('.wrapper-card').length;

let items = 10;

showMore.addEventListener('click', () => {
  items += 4;
  const array = Array.from(document.querySelector('.wrapper').children);
  const visItems = array.slice(0 , items);

  visItems.forEach(el => el.classList.add('is-visible'));
    
  if(visItems.length === cards) {
    showMore.style.display = 'none';
  }
});
function getLastVisibleDiv() {
    return Array.from(document.querySelectorAll('.wrapper-card'))
                .reverse()
                .find(div => div.offsetParent !== null);
  }
.wrapper {
    display: flex;
    flex-direction: column;
    gap: 20px;
}
.wrapper-card {
    width: 100px;
    height: 50px;
    background: red;
}
.wrapper-card:nth-child(n+3) {
    display: none;
}
.wrapper-card.is-visible {
    display: flex;
    
}
    <div class="wrapper">
        <div class="wrapper-card"></div>
        <div class="wrapper-card"></div>
        <div class="wrapper-card"></div>
        <div class="wrapper-card"></div>
        <div class="wrapper-card"></div>
        <div class="wrapper-card"></div>
        <div class="wrapper-card"></div>
    </div>

<button class="btn-download">
    Показать еще
</button>


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

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

Как сделать плавное открытие карточек?

Вот такой вот вариант (как идея) подойдет тебе?

const showMore = document.querySelector('.btn-download');
const cards = document.querySelectorAll('.wrapper-card').length;

let items = 10;

showMore.addEventListener('click', () => {
  items += 4;
  const array = Array.from(document.querySelector('.wrapper').children);
  const visItems = array.slice(0, items);
  (async _ => {
    for (const el of visItems) {
      await test(el)
    }
    if (visItems.length === cards) {
      showMore.style.display = 'none';
    }
  })()
});

function getLastVisibleDiv() {
  return Array.from(document.querySelectorAll('.wrapper-card'))
    .reverse()
    .find(div => div.offsetParent !== null);
}
//
function test(el) {
  return new Promise(res => setTimeout(_ => {
    el.classList.add('is-visible')
    res()
  }, 100))
}
.wrapper {
  display: flex;
  flex-direction: column;
  gap: 20px;
  border: 1px solid;
}

.wrapper-card {
  width: 100px;
  height: 50px;
  background: red;
  transition: all 1s linear;
  animation: fadeInOut 0.1s ease-in-out;
}

.wrapper-card:nth-child(n+3) {
  display: none;
  opacity: 0;
  height: 0;
}

.wrapper-card.is-visible {
  /*
  display: flex;
  */
  opacity: 1;
  height: 50px;
  display: block;
}
@keyframes fadeInOut {
    0% {
        height: 0;
        display: none;
    }

    1% {
        height: 0;
        display: block;
    }

}
<div class="wrapper">
  <div class="wrapper-card"></div>
  <div class="wrapper-card"></div>
  <div class="wrapper-card"></div>
  <div class="wrapper-card"></div>
  <div class="wrapper-card"></div>
  <div class="wrapper-card"></div>
  <div class="wrapper-card"></div>
</div>

<button class="btn-download">
    Показать еще
</button>

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

Можно с помощью классического аккордеона (почти)

const menu = document.querySelector('.sub-menu-short');

document.querySelector('.button').addEventListener('click', () => {
    menu.classList.toggle('sub-menu-short_hidden');
    menu.style.maxHeight = menu.classList.contains('sub-menu-short_hidden') ? 0 : `${menu.scrollHeight}px`;
});
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

.page {
    background-color: #333;
}

.menu {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
}

.menu-base {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;

    padding-block: 20px;
    padding-inline: 50px;

    border: 1px solid #999;
    overflow: hidden;
}

.sub-menu {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
}

.sub-menu-short {
    position: relative;
    max-height: 0;
    overflow: hidden;
    transition: .2s ease-in;
}

.children {
    width: 400px;
    min-height: 80px;
    background-color: #666;
}

.button {
    display: block;
    width: 100px;
    height: 50px;
    background-color: #444;
    border: none;
    color: #fff;
    cursor: pointer;
}

.button:hover {
    background-color: #777;
}

.button:active {
    background-color: #444;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="index.css">
</head>
<body class="page">
    <div class="menu">
        <div class="menu-base">
            <div class="sub-menu">
                <div class="children"></div>
                <div class="children"></div>
                <div class="children"></div>
            </div>
            <div class="sub-menu sub-menu-short sub-menu-short_hidden">
                <div class="children"></div>
                <div class="children"></div>
                <div class="children"></div>
                <div class="children"></div>
                <div class="children"></div>
                <div class="children"></div>
            </div>
        </div>
        <button type="button" class="button">show more</button>
    </div>

    <script src="main.js"></script>
</body>
</html>

→ Ссылка