Applying Transition To Injected html in Javascript

Viewed 122

I've been working with JS for about two weeks, and I'm working on a little project. The goal was to be able to change the color on each individual character in a given string when pressing the button. I've gotten that far.

As you can see, I added spans to each character, so that I can individually edit them. I'm trying to apply a transition to the spans so that when I click the button, the color fades to another color instead of just instantaneously changing. Is that possible?

Here's the codepen:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="CSS/textColorV2.css">
</head>

<body>
<p id="letter">Color</p>
<button>Click ME</button>

<script type="text/javascript" src="JS/textColorV2.js"></script>

</body>
</html>

CSS

bodybody {
background-color: #FFE7E0;
}

span{
transition: all 4s;
}

#letter {
font-size: 9em;
position: absolute;
top: 30%;
left: 50%;
transform: translate(-50%, -50%);
color:blue;
}

JS

var letter = document.getElementById("letter");
var text = letter.innerHTML;
var button = document.querySelector("button");

button.addEventListener("click", function () {
  var newText = "";
  for (var i = 0; i < text.length; i++) {
    newText += '<span style="color:' + randomColor() + '">' + 
    text.charAt(i) + '</span>';
    letter.innerHTML = newText;
    letter.classList.add("trans");
    };
});

function randomColor() {
  //r
  var r = Math.floor(Math.random() * 256);
  //g
  var g = Math.floor(Math.random() * 256);
  //b
  var b = Math.floor(Math.random() * 256);
  return "rgb(" + r + " ," + g + " ," + b + ")";
}
2 Answers

This is absolutly possible. The key idea here is to separate your string into span elements (per character) at the start of your script, rather than during each click event.

Taking this approach will simplify your implementation - all you need to do in the button click handler is assign a new "random color" to each span element, and leave the CSS transition(s) to the browser to handle:

var letter = document.getElementById("letter");
var text = letter.innerHTML;
var button = document.querySelector("button");

// Convert inner text node to span nodes for each character
// at beginning of script
var text = letter.innerText;
letter.innerText = '';
for(var i = 0; i < text.length; i++) {
  var character = text[i]; 
  letter.innerHTML += '<span style="color:' + randomColor() + '">' + character + '</span>';
}

button.addEventListener("click", function () {
  
  // For each span/character of #letter, assign a new random
  // color. This causes the browser to handle the CSS color 
  // transition for you
  for(var span of document.querySelectorAll('#letter span')) {
    span.style.color = randomColor();
  }
});

function randomColor() {

  var r = Math.floor(Math.random() * 256);
  var g = Math.floor(Math.random() * 256);
  var b = Math.floor(Math.random() * 256);
  
  return "rgb(" + r + " ," + g + " ," + b + ")";
}
span{
transition: all 4s;
}

#letter {
font-size: 9em;
position: absolute;
top: 30%;
left: 50%;
transform: translate(-50%, -50%);
color:blue;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="CSS/textColorV2.css">
</head>

<body>
<p id="letter">Color</p>
<button>Click ME</button>
 

</body>
</html>

Here is a more concise version of the same...

const letters = document.querySelectorAll('.letters');
const button = document.querySelector('button');

button.addEventListener('click', () => {
  letters.forEach(element => {
    element.style.transition = '1s';
    element.style.color = randomColor();
  });
});

const randomColor = () => {
  const r = Math.floor(Math.random() * 256);
  const g = Math.floor(Math.random() * 256);
  const b = Math.floor(Math.random() * 256);

  return `rgb(${r} ,${g},${b})`;
};
body {
  background-color: #ffe7e0;
}

#wrapper {
  font-size: 4em;
  position: absolute;
  top: 30%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: blue;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="index.css">
  <title>Document</title>
</head>

<body>

  <div id="wrapper">
    <span class="letters">C</span>
    <span class="letters">o</span>
    <span class="letters">l</span>
    <span class="letters">o</span>
    <span class="letters">r</span>
  </div>

  <button>Click ME</button>

  <script src="index.js"></script>
</body>

</html>

Related