You can create a function that replaces the target text with a span element. The span element will be used to display the underline. I created a function named replaceTextWithUnderline in the code snippets below that demonstrates the expected behavior.
I thought of two different approaches to display the underline. Hopefully, one of these approaches fits your use case:
Approach 1: Making the text color transparent and wrapping the target text in <span> tags
This approach is straightforward. It involves replacing the target text with the target text wrapped inside of <span> tags.
function replaceTextWithUnderline(words, targetText = 'text') {
const regex = RegExp(targetText, 'gi')
const styles = `
color: transparent;
border-bottom: 2px solid yellow;
`
return words.replace(regex, `<span style="${styles}">${targetText}</span>`)
}
function fReplace() {
const exampleEl = document.getElementById('Example')
const newExampleEl = document.getElementById('NewExample')
newExampleEl.innerHTML = replaceTextWithUnderline(exampleEl.innerText)
}
fReplace()
<div id='Example'>This is my first text, this is my second text and this is my third text.</div>
<div id='NewExample'></div>
Positive aspects to this approach are that the underline's width will be equal to the target text's width and that you can achieve the same result using classes and CSS. For example:
<!-- Generated HTML from Javascript -->
<span class="underline">target text</span>
/* Accompanying styles for generated HTML */
.underline {
color: transparent;
border-bottom: 2px solid yellow;
}
A negative aspect is that this may not be a solution if you do not want any text inside of the <span> tags.
Approach 2: Using ch to define the underline's width
If you do not want any text inside of the <span> tags, you can opt to using the following CSS:
/* To apply a width, we need to change the display from inline to inline-block. */
display: inline-block;
/* <number> represents the number of characters in the target text */
width: <number>ch;
function createUnderlineStyles(numberOfChars) {
return `
display: inline-block;
width: ${numberOfChars}ch;
border-bottom: 2px solid yellow;
`
}
function replaceTextWithUnderline(words, targetText = 'text') {
const regex = RegExp(targetText, 'gi')
const styles = createUnderlineStyles(targetText.length)
return words.replace(regex, `<span style="${styles}"></span>`)
}
function fReplace() {
const exampleEl = document.getElementById('Example')
const newExampleEl = document.getElementById('NewExample')
newExampleEl.innerHTML = replaceTextWithUnderline(exampleEl.innerText)
}
fReplace()
<div id='Example'>This is my first text, this is my second text and this is my third text.</div>
<div id='NewExample'></div>
This utilizes the ch unit. From MDN's documentation, the ch unit is:
The advance measure (width) of the glyph "0" of the element's font.
This approach can be used if you do not want any text inside of the <span> tags. However, downsides to this approach are that the underline's width will not exactly match the target text's width and you will most likely not be able to implement this with CSS due to the nature of the number of characters being dynamic.