Underline Individual Words

There is no CSS for applying an underline (text-decoration: underline;) only to individual words in a multiple-word element. The best way would be to wrap each word in a span (not the spaces, just the words) in spans and apply underline to those spans. Here's jQuery to do that to h1 elements.

$('h1').each(function() {

	var words = $(this).text().split(' ');

	$(this).empty().html(function() {

		for (i = 0; i < words.length; i++) {
			if (i == 0) {
				$(this).append('<span>' + words[i] + '</span>');
			} else {
				$(this).append(' <span>' + words[i] + '</span>');
			}
		}
	
	});

});

Then you could do:

h1 span {
  text-decoration: underline;
}

Similar and slightly more robust solution: Lettering.js

Reference URL

Comments

  1. User Avatar
    Jan-Marten de Boer
    Permalink to comment#

    For the raw JS version:

    var h1s = document.getElementsByTagName('h1');
    for(var i=0; i < h1s.length; i++) {
        var t = h1s[i];
        t.innerHTML = '<span>' + t.innerHTML . split(' ') . join('</span><span>') +  '</span>'; 
    }

    I believe I reduced the footprint a little too. Although your version is a lot more abstract and uses better maintainable code.

    • User Avatar
      Jan-Marten de Boer
      Permalink to comment#

      Whoah, sorry :P There should be a space between </span> and <span>

      join('</span> <span>')
  2. User Avatar
    Jan-Marten de Boer
    Permalink to comment#

    Just a note: If you do a for loop, you should declare the i variable with the var keyword. See here why.

    Furthermore, if this for-loop sees the length is 0, it will never reach the inside of the for loop and breaks off before initiating the code inside. Therefore, your if-else-statement is completely ignored, since only the else case can be true. If will never be reached, because the for loop breaks off before then.

  3. User Avatar
    Adam
    Permalink to comment#

    The code in the reference is correct, but that code on this page is missing the span tags within append().

  4. User Avatar
    TeMc
    Permalink to comment#

    Although the raw JS version isn’t too bad either. There’s some performance to be gained in the jQuery version as wel. Why call $.fn.each, $.fn.empty, $.fn.html and then a dozen times $.fn.append ?

    
    function htmlEsc(txt){
      return txt.replace(/&/g, "&").replace(//g, ">");
    }
    $('h1').each(function() {
    
            var $el = $(this),
                words = $el.text().split(' '),
                newHtml = '',
                i = 0, 
                len = words.length;
    
            for ( ; i < len; i++) {
                    if (i < 0) {
                           newHtml += ' '; // space
                    }
                    newHtml += '' + htmlEsc( words[i] ) + '';
            }
    
            $(this).html( newHtml );
    
    });
    

    * the empty() is simply redundant
    * the calls to append() don’t make sense inside html. Either build outside and call $(this).append() a few times, or build it inside and call $(this).html( stuff ); The latter is recommended.
    * You’re using text() to retrieve the value but using html()/append() to put it back. This is very dangerous when working with user input and can also destroy your layout if there is anything like HTML in your titles. You must escape html here when building the strings (or use $.fn.text)
    * Don’t forget ‘var’ instead of i in the for loop. Or move it to the list of vars outside the for-loop, that way you save a few bits in not starting two var statements (those are all one var statement, not how they are separated by a comma.

  5. User Avatar
    TeMc
    Permalink to comment#

    Although the raw JS version isn’t too bad either. There’s some performance to be gained in the jQuery version as wel. Why call $.fn.each, $.fn.empty, $.fn.html and then a dozen times $.fn.append ?

    
    function htmlEsc(txt){
      return txt.replace(/&/g, "&").replace(//g, ">");
    }
    $('h1').each(function() {
    
            var $el = $(this), words = $el.text().split(' '), newHtml = '',  i = 0,  len = words.length;
    
            for ( ; i < len; i++) {
                    if (i < 0) { newHtml += ' ';  } // add space between words
                    newHtml += '' + htmlEsc( words[i] ) + '';
            }
    
            $(this).html( newHtml );
    });
    

    * the empty() is simply redundant
    * the calls to append() don’t make sense inside html. Either build outside and call $(this).append() a few times, or build it inside and call $(this).html( stuff ); The latter is recommended.
    * You’re using text() to retrieve the value but using html()/append() to put it back. This is very dangerous when working with user input and can also destroy your layout if there is anything like HTML in your titles. You must escape html here when building the strings (or use $.fn.text)
    * Don’t forget ‘var’ instead of i in the for loop. Or move it to the list of vars outside the for-loop, that way you save a few bits in not starting two var statements (those are all one var statement, not how they are separated by a comma.

  6. User Avatar
    Ecatherina
    Permalink to comment#

    Chris, tell me please how to put in the script, not only h1, but more and h2.
    Thank you in advance , Ecatherina.

  7. User Avatar
    Deji
    Permalink to comment#

    thanks

  8. User Avatar
    Deji
    Permalink to comment#

    i need some css code pls oga

  9. User Avatar
    ilham
    Permalink to comment#

    Your tutor is very nice guys…
    like it’s..

  10. User Avatar
    Buy Cheap Diablo 3 Identify
    Permalink to comment#

    Nice game! The thing that really irks us a lot is having if an individual online connection to play in solo mode. I mean seriously wtf?

  11. User Avatar
    Yukulélé
    Permalink to comment#

    my version accept non-final nodes !

    gist :

    pen :

  12. User Avatar
    josh
    Permalink to comment#

    anyway to do this with an if then statement? ie change the first word red ONLY if there are more than 1 words? I want to have the span ‘word1’ be red only if there are multiple words in the title, the remaining words would be black. Otherwise word1 will be black.

Posting Code

You may write comments in Markdown. This makes code easy to post, as you can write inline code like `<div>this</div>` or multiline blocks of code in triple backtick fences (```) with double new lines before and after.

Code of Conduct

Absolutely anyone is welcome to submit a comment here. But not all comments will be posted. Think of it like writing a letter to the editor. All submitted comments will be read, but not all published. Published comments will be on-topic, helpful, and further the discussion or debate.

Want to tell us something privately?

Feel free to use our contact form. That's a great place to let us know about typos or anything off-topic.

Submit a Comment

icon-closeicon-emailicon-linkicon-menuicon-searchicon-tag