# \[TEXT ANIMATION] làm hiệu ứng chữ dòng trên xuất hiện trước rồi mới đến dòng dưới (ok)

![](/files/srh3V3hxfHbpvs6AajZV)

```
<div class='animation'>
  text comes here
</div>
<button class='restart'>
  restart
</button>
```

```
.animation__elem {
  display: inline-block;
  margin-right: 0.3em;
  transition: transform 0.8s, opacity 0.8s;
}
.animation__elem.hidden {
  transform: translateX(100%);
  visibility: hidden;
  opacity: 0;
}
/*---------------*\
 * only for show *
\*---------------*/
body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100vh;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  font-weight: 200;
}
.animation {
  display: block;
  font-size: 2em;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.restart {
  position: absolute;
  right: 1em;
  bottom: 1em;
  padding: 1rem;
  font-size: 1em;
  text-transform: uppercase;
  color: #678;
  border: 1px solid #678;
  background-color: transparent;
  cursor: pointer;
}
/*--------------*/

```

```
(function (doc) {
   // this party startet
   textAnim();

   function textAnim() {
      var con = doc.querySelector(".animation");

      if (con) {
         // get the text
         var str = con.innerHTML;
         var arr = str.split(" ");
         //delete the text from container
         con.innerHTML = "";
         // create individual elements and add them to the container
         arr.forEach(function (el) {
            if (el != "\n") {
               var newHTMLel = doc.createElement("span");
               newHTMLel.innerHTML = el;
               newHTMLel.classList.add("animation__elem", "hidden");
               con.appendChild(newHTMLel);
            }
         });

         // get the individual elements back an show them piece by piece
         var list = con.childNodes;
         var timer = 0;

         list.forEach(function (el) {
            setTimeout(function () {
               el.classList.remove("hidden");
            }, (timer += 200));
         });
      }
   }

   /*---------------*\
    * only for show *
   \*---------------*/

   var btn = doc.querySelector(".restart");

   btn.addEventListener("click", function () {
      doc.querySelector(".animation").innerHTML = "text comes here";
      textAnim();
   });
})(document);

```

Ví dụ 2: <https://codepen.io/rachsmith/details/BNKJme>

```
<div class="text">
  <p>Nachos are</p>
  <p>
    <span class="word wisteria">tasty.</span>
    <span class="word belize">wonderful.</span>
    <span class="word pomegranate">fancy.</span>
    <span class="word green">beautiful.</span>
    <span class="word midnight">cheap.</span>
  </p>
</div>
```

```
@import url(https://fonts.googleapis.com/css?family=Open+Sans:600);

body {
  font-family: 'Open Sans', sans-serif;
  font-weight: 600;
  font-size: 40px;
}

.text {
  position: absolute;
  width: 450px;
  left: 50%;
  margin-left: -225px;
  height: 40px;
  top: 50%;
  margin-top: -20px;
}

p {
  display: inline-block;
  vertical-align: top;
  margin: 0;
}

.word {
  position: absolute;
  width: 220px;
  opacity: 0;
}

.letter {
  display: inline-block;
  position: relative;
  float: left;
  transform: translateZ(25px);
  transform-origin: 50% 50% 25px;
}

.letter.out {
  transform: rotateX(90deg);
  transition: transform 0.32s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}

.letter.behind {
  transform: rotateX(-90deg);
}

.letter.in {
  transform: rotateX(0deg);
  transition: transform 0.38s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.wisteria {
  color: #8e44ad;
}

.belize {
  color: #2980b9;
}

.pomegranate {
  color: #c0392b;
}

.green {
  color: #16a085;
}

.midnight {
  color: #2c3e50;
}
```

```
var words = document.getElementsByClassName('word');
var wordArray = [];
var currentWord = 0;

words[currentWord].style.opacity = 1;
for (var i = 0; i < words.length; i++) {
  splitLetters(words[i]);
}

function changeWord() {
  var cw = wordArray[currentWord];
  var nw = currentWord == words.length-1 ? wordArray[0] : wordArray[currentWord+1];
  for (var i = 0; i < cw.length; i++) {
    animateLetterOut(cw, i);
  }
  
  for (var i = 0; i < nw.length; i++) {
    nw[i].className = 'letter behind';
    nw[0].parentElement.style.opacity = 1;
    animateLetterIn(nw, i);
  }
  
  currentWord = (currentWord == wordArray.length-1) ? 0 : currentWord+1;
}

function animateLetterOut(cw, i) {
  setTimeout(function() {
    cw[i].className = 'letter out';
  }, i*80);
}

function animateLetterIn(nw, i) {
  setTimeout(function() {
    nw[i].className = 'letter in';
  }, 340+(i*80));
}

function splitLetters(word) {
  var content = word.innerHTML;
  word.innerHTML = '';
  var letters = [];
  for (var i = 0; i < content.length; i++) {
    var letter = document.createElement('span');
    letter.className = 'letter';
    letter.innerHTML = content.charAt(i);
    word.appendChild(letter);
    letters.push(letter);
  }
  
  wordArray.push(letters);
}

changeWord();
setInterval(changeWord, 4000);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://javascriptuse.gitbook.io/advanced/text-animation-lam-hieu-ung-chu-dong-tren-xuat-hien-truoc-roi-moi-den-dong-duoi-ok.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
