 <p>I was having the same problem today, highlighting the selected tags ranging over multiple tags. The solution: </p> <ol> <li><strong>Find a way to extract the selected portion along with the HTML tags</strong>. </li> <li><strong>Wrap the extracted portion with a span element and put it back in the DOM</strong> . </li> </ol> <p>Refer the code below , for further clarification. </p> <pre><code>function getRangeObject(selectionObject){ try{ if(selectionObject.getRangeAt) return selectionObject.getRangeAt(0); } catch(ex){ console.log(ex); } } document.onmousedown = function(e){ var text; if (window.getSelection) { /* get the Selection object */ userSelection = window.getSelection() /* get the innerText (without the tags) */ text = userSelection.toString(); /* Creating Range object based on the userSelection object */ var rangeObject = getRangeObject(userSelection); /* This extracts the contents from the DOM literally, inclusive of the tags. The content extracted also disappears from the DOM */ contents = rangeObject.extractContents(); var span = document.createElement("span"); span.className = "highlight"; span.appendChild(contents); /* Insert your new span element in the same position from where the selected text was extracted */ rangeObject.insertNode(span); } else if (document.selection &amp;&amp; document.selection.type != "Control") { text = document.selection.createRange().text; } }; </code></pre>