Анимация набора абзаца по буквам

Рейтинг: 0Ответов: 1Опубликовано: 12.08.2025

Я бы хотел сделать анимацию набора абзаца в divi theme по буквам.Код приведу ниже. Этот код выводит только одну строку из абзаца. Помогите пожалуйста вывести весь абзац с помощью данной анимации.

.typing-effect {
  overflow: hidden; /* Скрываем переполнение */
  border-right: .15em solid orange; /* Добавляем курсор */
  white-space: nowrap; /* Запрещаем перенос строки */
  margin: 0 auto; /* Выравниваем по центру */
  letter-spacing: .15em; /* Добавляем небольшое расстояние между буквами */
  animation:
    typing 3.5s steps(40, end),
    blink-caret .75s step-end infinite;
}

/* Анимация набора текста */
@keyframes typing {
  from { width: 0 }
  to { width: 100% }
}

/* Анимация курсора */
@keyframes blink-caret {
  from, to { border-color: transparent }
  50% { border-color: orange; }
}

Ответы

▲ 2

Перенёс логику набора текста в JavaScript, так как это проще делается через JS.

Курсор автоматически исчезает после набора текста. Если не нужно исчезновение курсора в конце - можно удалить эту строчку opacity: var(--opacityCursor, 1);

Скорость печати одного символа задаётся CSS переменной --typing-speed: 20ms

class TypingEffect {
  constructor(element) {
    this.el = element;
    this.fullText = element.textContent;
    this.el.textContent = '';
    this.cursor = document.createElement('span');
    this.cursor.classList.add('typing-cursor');
    this.el.appendChild(this.cursor);
    this.index = 0;

    // Начинаем с курсором видимым
    this.cursor.style.setProperty('--opacityCursor', 1);

    const speedStr = getComputedStyle(this.el).getPropertyValue('--typing-speed').trim() || '50ms';
    this.speed = this.parseTime(speedStr);
  }

  parseTime(timeStr) {
    // Парсим строку с временем типа '50ms', '0.1s' и т.п.
    const match = timeStr.match(/^([\d.]+)(ms|s)$/);
    if (!match) return 50; // дефолт 50ms

    const value = parseFloat(match[1]);
    const unit = match[2];
    if (unit === 's') {
      return value * 1000;
    }
    // ms
    return value;
  }

  type() {
    if (this.index < this.fullText.length) {
      const char = this.fullText.charAt(this.index);
      this.cursor.insertAdjacentText('beforebegin', char);
      this.index++;
      setTimeout(() => this.type(), this.speed);
    } else {
      // Скрываем курсор после набора
      this.cursor.style.setProperty('--opacityCursor', 0);
    }
  }

  start() {
    this.type();
  }
}

const el = document.querySelector('.typing-element');
const typer = new TypingEffect(el);

typer.start();
.typing-cursor {
  display: inline;
  border-right: 2px solid orange;
  animation: blink-caret 0.75s step-end infinite;
  opacity: var(--opacityCursor, 1);
}

@keyframes blink-caret {
  0%, 100% {
    border-color: transparent;
  }

  50% {
    border-color: orange;
  }
}
<div class="typing-element" style="--typing-speed: 20ms;">
  Lorem ipsum dolor sit amet consectetur adipisicing elit. Sit assumenda neque quasi, iusto laudantium nemo architecto, earum.
</div>