<div id="container">
  <div id="text">Lorem ipsum <b>dolor</b> sit amet, <small>consectetuer adipiscing elit</small>.</div>
  <div id="shadings"></div>
</div>
html,
body {
  margin: 0;
  padding: 0;
  width: 100vw;
  height: 100vh;
  background-color: #cae9ff;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  font-size: 3.5vw;
}

#text,
#shadings {
  height: 1.5em;
  padding-bottom: 0.25em;
}

#text {
  whitespace: pre;
  display: inline;
  width: fit-content;
}

small {
  font-size: 0.6em;
}

#shadings {
  position: relative;
  mix-blend-mode: multiply;
  transition: 0.5s ease-in-out transform;
}

#shadings div {
  position: absolute;
  height: 1em;
  background-color: #00fff5;
  left: 0;
}

#shadings div:nth-child(2n) {
  background-color: #3cdbd3;
}

#shadings div:last-child {
  position: relative;
  opacity: 0;
}

#container:hover #shadings {
  transform: translateY(-1em);
}
/**
 * A generator that recursively find all text nodes in a subtree rooted at el.
 */
function* recursivelyFindTextNode(el: Node): Generator<Node> {
  if (el.nodeType === Node.TEXT_NODE) {
    yield el;
  } else if (el.nodeType === Node.ELEMENT_NODE) {
    for (let i = 0; i < el.childNodes.length; i++) {
      yield* recursivelyFindTextNode(el.childNodes[i]);
    }
  }
}

function measure(el: Node): number[] {
  const result: number[] = [];
  const range = document.createRange();
  range.setStartBefore(el);

  // expand all text nodes found.
  const nodes = [...recursivelyFindTextNode(el)];

  for (const textNode of nodes) {
    const textLength = [...textNode.textContent].length;
    for (let i = 0; i < textLength; i++) {
      range.setEnd(textNode, i);
      const rect = range.getBoundingClientRect();
      if (rect.width !== 0) result.push(rect.width);
    }
  }

  // Get the total length of the text
  range.setEndAfter(nodes.length > 0 ? nodes[nodes.length - 1] : el);
  const rect = range.getBoundingClientRect();
  result.push(rect.width);

  return result;
}

const el = document.getElementById("text");
const cont = document.getElementById("shadings");
const lengths = measure(el);

for (const l of lengths) {
  const d = document.createElement("div");
  d.style.width = `${l}px`;
  cont.prepend(d);
}

// text width placeholder
const d = document.createElement("div");
d.style.width = `${lengths[lengths.length - 1]}px`;
cont.appendChild(d);
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.