.container
  .line Lorem ipsum dolor sit amet, consectetur adipisicing elit,
  .line sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
View Compiled
.container {
  .line {
    overflow: hidden;
    span {
      display: inline-block;
      transform: translateY(2rem);
      animation: slideText 1s forwards;
    }
  }
  .line:nth-of-type(1) {
    @for $i from 1 through 100 {
      span:nth-of-type(#{$i}) {
        animation-delay: #{$i * .02}s;
      }
    }
  }
  .line:nth-of-type(2) {
    @for $i from 1 through 100 {
      span:nth-of-type(#{$i}) {
        animation-delay: #{.25 + $i * .02}s;
      }
    }
  }
}

@keyframes slideText {
  100% { transform: translateY(0); }
}
View Compiled
/**
 * @class SpanWrapText
 * @description テキストを1文字ずつspanで囲む
 * @argument target 対象のテキストを含む要素
 */
class SpanWrapText {
  constructor(target) {
    this.target = target;
    this.nodes = this.target.childNodes;
    this.convert();
  }

  /**
   * @method convert
   * @description テキストを1文字ずつspanで囲む
   */
  convert() {
    let spanWrapText = '';

    this.nodes.forEach((node) => {
      if (node.nodeType == 3) { // テキストの場合
        // 改行コードを削除
        const text = node.textContent.replace(/\r?\n/g, '');
        // spanタグで囲んで連結
        spanWrapText = spanWrapText + text.split('').reduce((accumulator, currentValue) => {
          currentValue = currentValue.replace(' ', ' ');
          return accumulator + `<span>${currentValue}</span>`;
        }, '');
      } else { // テキスト以外の場合
        // brなどの要素はそのまま連結
        spanWrapText = spanWrapText + node.outerHTML;
      }
    });

    this.target.innerHTML = spanWrapText;
  }
}

document.addEventListener('DOMContentLoaded', event => {
  document.querySelectorAll('.container .line').forEach(element => {
    new SpanWrapText(element);
  });
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.