Search code examples
borderinlinecssunderline

Add a border only to the bottom of wrapped text


I'm trying to achieve an underline on some wrapped text that fits to the width of the bottom row of text whilst only appearing underneath that bottom line. Figure 1 illustrates the desired effect

Figure 1

how it should be

Using this HTML:

<h2><span class="inline-block">optatur, volendit inum simolor</span></h2>

and setting the span to display:inline; I can get the underline to fit perfectly with the width of the text but it underlines all of the text.

Or, setting the span to display:inline-block; I can get the underline to only appear under the bottom line but it then fills the whole width of the parent.

See this JSfiddle for the above examples: http://jsfiddle.net/PWDV7/1/

Is there any way to achieve the result of figure 1?


Solution

  • With a good leg up from this answer to a questions about finding line wraps, I managed to come up with this solution (in short, it involves using JS to find where a line wrap has occurred and wraps a span around all the text that sits on the last line):

    function underLineText () {
        $underlined_text.each(function(){
            var $this = $(this);
            var text = $this.text();
            var originalText = text;
            var breakWords = new Array();
    
            //split the words into individual strings 
            var words = text.split(' ');
    
            //find the height of the first word
            $this.text(words[0]);
            var height = $this.height();
    
            //if there is more than one word
            if (words.length > 1) {
                //loop through all the words
                for(var i = 1; i < words.length; i++){
                    $this.text($this.text() + ' ' + words[i]);
    
                    //check if the current word has a different height from the previous word
                    //if this is true, we have witnessed a word wrap!
                    if($this.height() > height){
                        height = $this.height();
                        //add the first word after the wrap to a predefined array
                        breakWords.push(words[i]);
                    }
    
                    //on the last iteration on the loop...
                    if (i === words.length - 1) {
                        if (breakWords.length > 0) {
                            //select the last word of the breakWords array
                            //(this is to handle cases where there there are more than one line or word wraps)
                            var breakStartAt = breakWords[breakWords.length - 1];
                            //add a span before the last word
                            var withSpan = '<span>'+breakStartAt;
                            //replace the last occurrence of this word with the span wrapped version
                            //(this is to handle cases where there are more than one occurrences of the last word)
                            originalText = originalText.replaceLast(breakStartAt,withSpan);
                            //close the last line with a span
                            originalText += "</span>";
    
                        }
                    }
                }
            }
            //if there are no word wraps, wrap the whole text in spans
            else {
                originalText = '<span>'+originalText+'</span>';
            }
    
            //replace the original text with the span-wrapped mod
            $(this).html(originalText);
        });
    }
    

    You can see it working here: http://jsfiddle.net/PWDV7/5/