Сохранить анимацию css
function eCr(Type, atr = {}){
let element = document.createElement(Type);
for (var idx in atr)
idx == 'html' ? (element.innerHTML = atr[idx]) : (idx == 'append' || idx == 'before' ? atr[idx][idx](element) : element.setAttribute(idx, atr[idx]));
return element;
}
let ul = document.querySelector('ul');
c.onclick = e => [1, 2, 3].forEach(() => eCr('li', {html: '<li>texttexttext</li><li>texttexttext</li>', append:ul}));
ul {
overflow: hidden;
border-radius: 5px;
background: rgb(28 28 28 / 90%);
width: min-content;
color: rgb(255 255 255 / 70%);
white-space: nowrap;
transition: all 2150ms ease-in-out;
}
<div id='c'>КЛИК</div>
<ul>
<li>Текст</li>
<li>Текст</li>
</ul>
Как сделать, чтобы анимация работала тогда когда добавляем блоки. То есть и на высоту анимация и на ширину, ширина и высота блока относительно дочерних блоков.
Желательно с сохранением свойства transition
Ответы (1 шт):
Решение с сохранением свойства transition:
- Добавляем к списку CSS-свойство
box-sizing: border-box. - Перед добавлением элементов устанавливаем свойства
max-widthиmax-heightв значения полной внутренней ширины и высоты (scrollWidth,scrollHeight). - Добавляем элементы в список.
- Повторяем шаг 2, чтобы актуализировать max-width и max-height и инициировать transition.
c.onclick = e => {
let ul = document.querySelector('ul');
ul.style.maxWidth = ul.scrollWidth + 'px';
ul.style.maxHeight = ul.scrollHeight + 'px';
for (let i = 0; i < 3; i++) {
let li = document.createElement('li');
li.innerText = 'Текст Текст Текст Текст Текст';
ul.appendChild(li);
}
ul.style.maxWidth = ul.scrollWidth + 'px';
ul.style.maxHeight = ul.scrollHeight + 'px';
};
ul {
border-radius: 5px;
background: rgb(28 28 28 / 90%);
width: min-content;
color: rgb(255 255 255 / 70%);
white-space: nowrap;
transition: all 1s ease-in-out;
box-sizing: border-box;
overflow: hidden;
}
<div id="c">КЛИК</div>
<ul>
<li>Текст</li>
<li>Текст</li>
</ul>
UPD
Код выше работает, если мы добавляем элементы.
Ситуация с удалением сложнее, потому что удаленный элемент сразу исчезает из DOM, и анимировать это не представляется возможным. Т.е. нам нужно зафиксировать текущие размеры (getComputedStyles()) свойствами min-width и min-height, удалить элементы списка, а затем инициировать transition.
Но как мы реализуем transition, если нам неизвестны конечные размеры с уже удаленными элементами? Тут оказался рабочим подход, когда после удаления мы сбрасываем лимиты, получаем размеры, и откатываем состояние. Это происходит достаточно быстро, так что визуально всё происходит гладко.
Таким образом, алгоритм при удалении:
- Получаем текущие размеры.
- Сбрасываем inline стили и transition (может еще не закончится анимация после добавления).
- Фиксируем размеры, задав min-width и min-height (значения от шага 1).
- Удаляем элементы.
- Сбрасываем все лимиты, получаем конечные размеры с учетом удаленных элементов, откатываем лимиты.
- Задаем конечные min-width и min-height, инициируем transition.
add.onclick = e => {
let ul = document.querySelector('ul');
setMaxLimits(ul);
for (let i = 0; i < 3; i++) {
let li = document.createElement('li');
li.innerText = 'Текст Текст Текст Текст Текст';
li.className = 'added';
ul.appendChild(li);
}
setMaxLimits(ul);
};
del.onclick = () => {
let ul = document.querySelector('ul');
let cw = getComputedStyle(ul).width;
let ch = getComputedStyle(ul).height;
// останавливаем transition и сбрасываем inline стили
ul.setAttribute('style', '');
// Начальные значения от текущего размера
ul.style.minWidth = cw;
ul.style.minHeight = ch;
// удаляем
[...document.querySelectorAll('.added')].every(e => e.remove() || true);
// сбрасываем лимиты, чтобы выяснить размеры после удаления
ul.classList.toggle('reset');
let w = ul.offsetWidth;
let h = ul.offsetHeight;
ul.classList.toggle('reset');
void ul.offsetHeight; // хак, чтобы transition сработал
ul.style.minWidth = w + 'px';
ul.style.minHeight = h + 'px';
}
function setMaxLimits(el) {
el.style.maxWidth = el.scrollWidth + 'px';
el.style.maxHeight = el.scrollHeight + 'px';
}
ul {
border-radius: 5px;
background: rgb(28 28 28 / 90%);
width: min-content;
color: rgb(255 255 255 / 70%);
white-space: nowrap;
transition: all 1s ease-in-out;
box-sizing: border-box;
overflow: hidden;
}
ul.reset {
min-width: initial !important;
min-height: initial !important;
}
<button id="add">Добавить</button>
<button id="del">Удалить</button>
<ul>
<li>Текст</li>
<li>Текст</li>
</ul>
Можно поиграть активно кнопками, чтобы увидеть, как хорошо адаптируется анимация. Ничего лучше придумать не смог, может еще кто-то поделится своим решением.