How to highlight the difference of two texts with css? [closed]

I know how to highlight part of a text with CSS using this script:

span.highlight {
    background-color: #B4D5FF;
}

Now I want to highlight the difference of two strings. For example given the following two strings:

this is number 123

and

that is number 124

I need to have a text highlighted like what I've shown here. Could somebody help me achieve this?

span.highlight {background-color: #B4D5FF}
<p>this is number 123</p>
<p>
th<span class="highlight">at</span> is number 12<span class="highlight">4</span>
</p>

Answers:

Answer

You need to get all character of new string using split() method and iterate every character and compare it with character of old string.

highlight($("#new"), $("#old"));

function highlight(newElem, oldElem){ 
  var oldText = oldElem.text(),     
      text = '';
  newElem.text().split('').forEach(function(val, i){
    if (val != oldText.charAt(i))
      text += "<span class='highlight'>"+val+"</span>";  
    else
      text += val;            
  });
  newElem.html(text); 
}
.highlight {background-color: #B4D5FF}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="old">this is number 123</p>
<p id="new">that is number 124</p>

Also you can use simpler code as shown in bottom

highlight($("#new"), $("#old"));

function highlight(newElem, oldElem){ 
  newElem.html(newElem.text().split('').map(function(val, i){
    return val != oldElem.text().charAt(i) ?
      "<span class='highlight'>"+val+"</span>" : 
      val;            
  }).join('')); 
}
.highlight {background-color: #B4D5FF}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="old">this is number 123</p>
<p id="new">that is number 124</p>

And if you want to use less span check bottom code

highlight($("#new"), $("#old"));

function highlight(newElem, oldElem){ 
  var oldText = oldElem.text(),     
      text = '',
      spanOpen = false;  
  newElem.text().split('').forEach(function(val, i){  
    if (val != oldText.charAt(i)){   
      text += !spanOpen ? "<span class='highlight'>" : "";
      spanOpen = true;
    } else {       
      text += spanOpen ? "</span>" : "";
      spanOpen = false;  
    }  
    text += val;
  });
  newElem.html(text); 
}
.highlight {background-color: #B4D5FF}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="old">this is number 123</p>
<p id="new">that is number 124</p>

Answer

So you'll have to use Javascript to accomplish this, since it involves a fair bit of logic. As mentioned in the other answer(s), detecting difference in text is a little bit more complicated than just checking character by character.

However, for curiosity's sake, I put together this naive implementation:

CodePen

Here's what the function that gets the differences looks like:

function getDiff(text1,text2){
  //Takes in two strings 
  //Returns an array of the span of the differences 
  //So if given:
  // text1: "that is number 124"
  // text2: "this is number 123"
  //It will return:
  // [[2,4],[17,18]]
  //If the strings are of different lengths, it will check up to the end of text1 
  //If you want it to do case-insensitive difference, just convert the texts to lowercase before passing them in 
  var diffRange = []
  var currentRange = undefined
  for(var i=0;i<text1.length;i++){
    if(text1[i] != text2[i]){
      //Found a diff! 
      if(currentRange == undefined){
        //Start a new range 
        currentRange = [i]
      }
    }
    if(currentRange != undefined && text1[i] == text2[i]){
      //End of range! 
      currentRange.push(i)
      diffRange.push(currentRange)
      currentRange = undefined
    }
  }
  //Push any last range if there's still one at the end 
  if(currentRange != undefined){
    currentRange.push(i)
    diffRange.push(currentRange)
  }
  return diffRange;
}

The function getDiff takes in two strings, and returns the ranges at which they differ. This works great as long as the two strings are of the same length.

So to use this, all I do is:

var text1 = "that is number 124"
var text2 = "this is number 123"
var diffRange = getDiff(text1,text2)

Try changing the texts there in the CodePen and watch it update!

Once it gets these ranges, it then generates the html and inserts the <span> tags, and adds the element to the page. If you know your strings will always be the same, this could be enough. Otherwise, it would be best to look at a Javascript diff libary! (Jsdiff seems like a good library)

Answer

'Diffing' text is more complicated than it might seem at first glance. It depends on exactly how you want to detect each difference, but in general, you want to detect:

  • changes at the character level (123 vs. 124)
  • Additions of text ('I have been to Sydney' vs. 'I have never been to Sydney).
  • Removal of text (reverse of previous example).

The tricky bit is detecting the differences and commonalities between the two strings. A naive implementation might just compare the strings character by character. The problem with that is, as soon as one character is added or removed, the rest of the string will appear as a difference, even though it's actually the same as the original text.

Your best bet is to use an existing diffing library. There are a lot out there for Javascript. This: https://github.com/kpdecker/jsdiff looks good, though it might be overkill for what you need. Basically though - don't try to invent this yourself unless you want to learn a lot about text parsing!

Answer

Of course the previous answer is correct, but if you have a very specific format to compare against and don't want to use an external framework a javascript like this could be used to group your characters and style them with css:

<html>

<style type="text/css">
.highlighted{
    background-color:blue;
}
</style>

<script type="text/javascript">

function init(){
    var output = document.getElementById("output");
    output.appendChild(highlightChanges("12777345aaaabbbbb","1277845abaababababababadsrfgadsg"));
}

var highlightChanges = function(str, compareStr){
    var strlength = str.length > compareStr.length ? compareStr.length : str.length;
    var allStr = document.createElement("span");
    var hl = null;
    var nohl = null;
    for(i = 0; i < strlength ; i++){
        if(str.charAt(i) != compareStr.charAt(i)){
            if(nohl != null){ 
                allStr.appendChild(nohl);
                nohl = null;
            }
            if(hl != null) hl.innerHTML += str.charAt(i);
            else{
                hl = document.createElement("span");
                hl.classList.add("highlighted");
                hl.innerHTML = str.charAt(i);
            } 
        }
        else{
            if(hl != null){
                allStr.appendChild(hl);
                hl = null;
            }
            if(nohl != null) nohl.innerHTML += str.charAt(i);
            else{
                nohl = document.createElement("span");
                nohl.innerHTML = str.charAt(i);
            } 
        }
    }
    return allStr;
}

</script>

<body onload="init()">
    <div id="output"></div>
</body>

</html>

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.