Как плавно добавить динамически создаваемый элемент в DOM только с помощью CSS3?

Моя потребность довольно проста, но я не мог найти подходящего решения.

Я создаю элементы и добавляю их в DOM в виде списка элементов, каждый новый элемент добавляется перед старыми. Хочется, чтобы новые элементы добавлялись «плавно». height каждого элемента является динамическим, поэтому должны быть правила CSS.

Я думаю, что мне нужно использовать CSS animations и keyframes, из того, что я прочитал, я не могу использовать transitions, потому что иногда он не отображается браузером. Я не хочу использовать Javascript, поэтому предпочитаю избегать решения с setTimeout() или jQuery. Я уверен, что это можно сделать правильно, используя современный CSS, но мне еще нужно найти правильный способ сделать это.

У меня есть начало решения (см. Ниже), но все еще жестко закодирован в CSS max-height: 1000px, и я хотел бы избежать этого, но я не знаю, как это сделать, потому что замена его на auto или unset нарушает анимацию (см. GIF-файлы в конце поста).

Как бы вы реализовали элегантный переход для добавления новых элементов в DOM, подобного этому (не обязательно с использованием предоставленного мной кода)?


Попробуйте код на JSFiddle

    function addElement() {
        let dynamicHeight = Math.ceil(Math.random() * 30) + 100;
        let newElem = `<div class='elem' style='height: ${dynamicHeight}px'></div>`;
        let elements = document.getElementById("elements");
        elements.insertAdjacentHTML("afterbegin", newElem);
    }

    let button = document.getElementById("button")
    button.addEventListener("click", addElement);
    .elem {
      background-color: blue;
      margin: 5px;
      animation-duration:0.5s;
      animation-name: slidein;
    }
    
    
    @keyframes slidein {
      from {
        max-height: 0px;
        transform: scale(0);
        opacity: 0;
      }
    
      to {
        max-height: 1000px;
        transform: scale(1);
        opacity: 1;
      }
    }
    <button id = "button">Add element</button>
    <div id = "elements"></div>

С жестко заданной максимальной высотой (выглядит красиво):Как плавно добавить динамически создаваемый элемент в DOM только с помощью CSS3?

С неустановленным max-height (выглядит неуклюже):Как плавно добавить динамически создаваемый элемент в DOM только с помощью CSS3?

вы пробовали использовать высоту: авто; ?

manAbl 09.06.2018 19:42

@ManuelBlanco Да, я пробовал с auto, unset и 100%, и это было "неуклюже" для всех из них.

Delgan 09.06.2018 19:44

@ibrahimmahrir Что вы имеете в виду под «сокращением времени второй анимации»? Как я могу это сделать? Эффект «корявости» возникает из-за того, что старый элемент «спрыгивает» вместо того, чтобы плавно перемещаться вниз.

Delgan 09.06.2018 19:48

@Delgan А! Я понимаю. Ну, вы либо используете max-height, либо javascript, иначе это невозможно: вы не можете анимировать или переходить от числовых значений к нечисловым и наоборот.

ibrahim mahrir 09.06.2018 19:54

У меня всегда было впечатление, что использование max-height для скользящего элемента может быть переоценено, потому что он просто переходит на расчетную высоту. Если скольжение линейное, то будет резкость, но ослабление может сгладить рывки завышенного max-height, возможно (не тестировалось)

zer00ne 10.06.2018 07:01
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
9
5
2 666
1

Ответы 1

Поскольку вы определяете фиксированную высоту, решение состоит в том, чтобы анимировать высоту от 0 пикселей до фиксированного значения. Уловка здесь заключается в том, чтобы полагаться на переменную CSS, чтобы иметь возможность динамической анимации элементов в зависимости от их высоты:

function addElement() {
  let dynamicHeight = Math.ceil(Math.random() * 100) + 40;
  let newElem = `<div class='elem' style='--h: ${dynamicHeight}px'></div>`;
  let elements = document.getElementById("elements");
  elements.insertAdjacentHTML("afterbegin", newElem);
}

let button = document.getElementById("button")
button.addEventListener("click", addElement);
.elem {
  background-color: blue;
  margin: 5px;
  animation: slidein 0.5s forwards;
}

@keyframes slidein {
  from {
    height: 0px;
    transform: scale(0);
    opacity: 0;
  }
  to {
    height:var(--h); /*This will change for each element */
    transform: scale(1);
    opacity: 1;
  }
}
<button id = "button">Add element</button>
<div id = "elements"></div>

Про var() не знал, спасибо! К сожалению, мой реальный вариант использования - это элементы, у которых нет фиксированной высоты, это просто «блочные» элементы с содержимым переменной длины.

Delgan 09.06.2018 23:42

@Delgan, хорошо, дай мне подумать по-другому;)

Temani Afif 09.06.2018 23:44

Спасибо за вашу помощь! Кстати, если вам удастся сделать какой-нибудь «плавный» переход, я, вероятно, с этим не откажусь, даже если нет масштабной трансформации или чего-то еще. Это немного расплывчато, но пока добавление новых элементов выглядит «красиво», а старые «скатываются вниз», я буду счастлив. :)

Delgan 09.06.2018 23:49

Другие вопросы по теме