5

I have some span with some words in it, like

        <span id="phrase">Here are some words</span>

I need to color all the 'e' characters red.

I think of taking the span.innerText property, remove text node from span element and add some more spans inside (or instead), and give them necessary style.

Is it the only way, or it could be solved in a more elegant way?

Dmitry Samoylov
  • 1,228
  • 3
  • 17
  • 27

6 Answers6

8

You can surely do it with javascript:

var span = document.getElementById('phrase'),
    text = span.innerHTML.split('').map(function(el) {
        return '<span class="char-' + el.toLowerCase() + '">' + el + '</span>';
    }).join('');
  
span.innerHTML = text;
.char-e {
    color: red;
}
<span id="phrase">Here are some words</span>

For convenience it wraps each character with a span with corresponding class name, which makes it easy to assign individual styles.

Warning: However I would not recommend doing this with large texts because the code above replaces innerHTML it can break your HTML if it contains other nested elements. But for small titles with only text this is not going to be a problem.

If you want to work with more complex HTML markup (with children elements) the function needs to be improved to work recursively on child items text content.

dfsq
  • 191,768
  • 25
  • 236
  • 258
3

More complex implementation (which contain dfsq code) which keep tags:

function addColor(domNode, color, letter){
 if(domNode.nodeType!=1||!domNode.hasAttribute('edited')){
  if(domNode.nodeType==3){
   var newText=document.createElement('span');    
   newText.innerHTML=domNode.textContent;
   newText.setAttribute('edited', true);
   var text = newText.innerHTML.split('').map(function(el){
     if(el==letter){
    return '<i style=\"color:'+color+'\">'+el+'</i>';
     }
     else{
    return el;
     }
    }).join('');
    newText.innerHTML=text;
    domNode.parentNode.replaceChild(newText,domNode);
  }
  for(var i=0; i<domNode.childNodes.length;i++){
   addColor(domNode.childNodes[i], color, letter);
  }
 }
} 

addColor(document.getElementById('phrase'), 'red', 'e');
<span id="phrase">Here are <a href="#"> test</a>  some text <p> some text again </p> some woreds</span>

With a fiddle: http://jsfiddle.net/e6c3yy0j/

Superdrac
  • 1,208
  • 17
  • 29
  • I improved it if you wanna change **more than one** type of character. [http://jsfiddle.net/e6c3yy0j/10/](http://jsfiddle.net/e6c3yy0j/10/) ( note: Attempt 7 and below are not mine, but I laughed so hard at them :D ) – Tominator Aug 25 '17 at 07:17
2

I think it's not so ugly to use javascript :

$(document).ready(function() {
   console.log( "ready!" );
   var text = $("#phrase").html().replace(/e/g, '<span class="red">e</span>');
    $("#phrase").html(text)
});

jsfiddle example

Thomas Leduc
  • 1,092
  • 1
  • 20
  • 44
  • Did you saw jQuery in the tags ? – Superdrac Oct 21 '14 at 11:58
  • 1
    Breaks as soon as there is something else than text. [updated fiddle](http://jsfiddle.net/vzxebauw/1/) That should at least be mentioned. – MildlySerious Oct 21 '14 at 11:59
  • 1
    @Superdrac jQuery is javascript, so please don't be ironic ... it's just the fastest way I found to show it. I could have demonstrated it with dart, angular or whatever, it still javascript ... MildySerious Do you need this example fixed with html inside or it's just to promote your answer ? – Thomas Leduc Oct 21 '14 at 16:17
2

Split each character in the string and if the character is 'e', then give the red color using fontcolor function.

Code

var s1 = document.getElementById("phrase");
var str = s1.innerHTML;
var newText = "";
for (var i = 0; i < str.length; i++) {
     if (str[i] == 'e') {
     newText+= str.charAt(i).fontcolor("red");
     }
     else {
        newText += str[i];
    }
}
s1.innerHTML = newText;

Find Fiddle Here

Ullas
  • 11,450
  • 4
  • 33
  • 50
1

You can't target specific letters in a text (except for the first one using :first-letter). So yes, your only option is to wrap them with an element. A span would work, the guys from FontAwesome like to use i instead.

So, for example, you could do this:

<span id="phrase">H<i>e</i>r<i>e</i> are som<i>e</i> words</span>

And add this to your CSS:

.phrase i {
    font-style: normal; /* Because I is italic by default */
    color: red;
}
MildlySerious
  • 8,750
  • 3
  • 28
  • 30
-1

If this you only need 1 known string to be red then you don't need javascript:

html

<span id="phrase">H<span class="my-class">e</span>r<span class="my-class">e</span> ar<span class="my-class">e</span> som<span class="my-class">e</span> words</span>

css:

.my-class {
    color: red
}
Rich Tier
  • 9,021
  • 10
  • 48
  • 71
  • Notice the Javascript tag. I'm guessing OP doesn't want to manually add classes to every e – Turnip Oct 21 '14 at 11:39
  • true, but putting it out there - javascript is not needed if the string is known. lets see what OP says. – Rich Tier Oct 21 '14 at 11:41
  • Of course, i need all that stuff to work dynamically. The thing is contents of the span are changing dynamically and so I need to apply transformation with javascript each time. – Dmitry Samoylov Oct 21 '14 at 11:44