Set different font color based on array for all spans in a document?

Viewed 1554

Using JavaScript I would like to change the style of each <span> from an array of colors. Here is an example:

HTML:

        <span>H</span>
        <span>E</span>
        <span>L</span>
        <span>L</span>
        <span>O</span>

JS:

colors=['red', 'orange', 'yellow', 'blue','green'];
[...document.querySelectorAll('span')].map( sp => {
         sp.style.color = colors[0];
         colors.shift();
});

Now my current thought is to spread my selection and use map so that I can iterate through each object. At the moment I am deleting elements in the colors as they are being used. I could also create an iterator to keep track of the colors so they do not get deleted. Assuming the number of objects and number of colors are the same I could also just step through with a for loop and set colors.

How can I accomplish this?

2 Answers

Because map() returns a new array and you are not using it forEach() will be the better choice here.

You can parse to the arrow function inside your forEach() as by map() the current element and also as optional but here very useful the index of the current element. This index you can use as indice for your colors array.

Note: There is no need for shift() here so I removed it.

Not asked here but good to know, when you have more <span> elements than colors you can use the remainder operator % to give the additional elements the right color. (Begin from the start of the colors array again)

colors = ['red', 'orange', 'yellow', 'blue', 'green'];
document.querySelectorAll('span').forEach((sp, ind) => {
  sp.style.color = colors[ind];
});
<span>H</span>
<span>E</span>
<span>L</span>
<span>L</span>
<span>O</span>

As you noted in your question, shift() works, but destroys the color array at the same time. Also, Array.prototype.map() returns a new array, which you aren't using and also requires that you convert your NodeList to an array.

To solve all of these problems you can use the NodeList.prototype.forEach()) method provided by the returned NodeList to iterate the list, and use the passed index to access the colors array.

(In your question the length of the colors array and the number of spans are the same, but if the number of spans increases any passed 5 won't be assigned colors. To solve this you can loop through the array by using the remainder % operator on the passed index colors[i % colors.length])

colors = ['red', 'orange', 'yellow', 'blue', 'green'];
document.querySelectorAll('span').forEach((sp, i) => {
  sp.style.color = colors[i % colors.length];
});
<span>H</span>
<span>E</span>
<span>L</span>
<span>L</span>
<span>O</span>
<span>W</span>
<span>O</span>
<span>R</span>
<span>L</span>
<span>D</span>

As tacoshy noted in the comments you can also achieve this with CSS using functional notation within an :nth-child() pseudo-class rule. see: Select every Nth element in CSS for more discussion.

span:nth-child(5n+1) {
   color: red;
}
span:nth-child(5n+2) {
   color: orange;
}
span:nth-child(5n+3) {
   color: yellow;
}
span:nth-child(5n+4) {
   color: blue;
}
span:nth-child(5n+5) {
   color: green;
}
<div class="container">
  <span>H</span>
  <span>E</span>
  <span>L</span>
  <span>L</span>
  <span>O</span> 
  <span>W</span>
  <span>O</span>
  <span>R</span>
  <span>L</span>
  <span>D</span>
</div>

Related