Line Break inside the P tag does not work

Asked

Viewed 78 times

5

I am making an animation in Javascript so that the text has the effect of being typed. I am using a single tag <p> for text, and Gostaria that broke the line in the tags <br>, but they are being added as text in HTML.

Follow code below + Codepen link

Link: https://codepen.io/Sr-RIcci/pen/ExWdbBX

function typeWriter(elemento) {
  const textoArray = elemento.innerHTML.split('');
  elemento.innerHTML = "";
  textoArray.forEach((letra, i) => {
    setTimeout(() => elemento.innerHTML += letra, 75 * i);
  });
}

const titulo = document.querySelector('p');
typeWriter(titulo);
p::after {
  content: "|";
  margin-left: 5px;
  opacity: 1;
  animation: pisca 0.7s infinite;
}

@keyframes pisca {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}
<p>Olá mundo <br> Olá Universo <br> Olá Vida </p>

  • Dennis, I edited my answer with an example without regex and without split.

2 answers

6


This is because the split() divides the <br> also, what you can do is use a regular expression, so instead of split() you can use String.prototype.match, see how the array looks after:

console.log("a b c d <br> foo bar <br> asd".match(/<\w+?>|./g))

The first part of the expression is to pick up the tags <\w+?> and the . after the pipe (|) is to pick up any other character (up to spaces.

However you could also make a for() well designed to join characters when it is a tag, navigating character by character, and not even need split, for example (see comments within code):

const elemento = document.querySelector("p");
const texto = elemento.innerHTML;

let hasOpenTag = false;
let tmpTag;

//Limpa o campo
elemento.innerHTML = '';

for (let i = 0, j = texto.length; i < j; i++) {
    let letra = texto[i];

    /*
      Se o caractere for "<" então executa o continue;
      para que o setTimeout não seja executado e armazenará
      os próximos caracteres até encontrar o ">"
    */
    if (letra === '<') {
      tmpTag = letra;
      hasOpenTag = true;
      continue;
    }
    
    /*
      Se encontrar o ">" e antes dele teve um "<"
      então junta a tag toda na variável tmpTag e irá
      adicionar ao setTimeout
    */
    if (hasOpenTag && letra === '>') {
        letra = tmpTag + letra;
        hasOpenTag = false;
    }

    /*
      Se a variavel hasOpenTag for true irá armazenar
      todos próximos caracteres para formar a tag, até
      encontrar o ">" (da if anterior)
      adicionar ao setTimeout
    */
    if (hasOpenTag) {
       tmpTag += letra;
       continue;
    }

    setTimeout(() => elemento.innerHTML += letra, 75 * i);
}
p::after {
  content: "|";
  margin-left: 5px;
  opacity: 1;
  animation: pisca 0.7s infinite;
}

@keyframes pisca {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}
<p>Olá mundo <br> Olá Universo <br> Olá Vida</p>

4

Where you use the property Element.innerHTML use the property Node.innerText which represents the "rendered" textual content of a node and its descendants it means that line breaks are converted and understood as \n.

function typeWriter(elemento) {
  const textoArray = elemento.innerText.split('');
  elemento.innerText = "";
  textoArray.forEach((letra, i) => {
    setTimeout(() => elemento.innerText += letra, 75 * i);
  });
}

const titulo = document.querySelector('p');
typeWriter(titulo);
p::after {
  content: "|";
  margin-left: 5px;
  opacity: 1;
  animation: pisca 0.7s infinite;
}

@keyframes pisca {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}
<p>Olá mundo <br> Olá Universo <br> Olá Vida </p>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.