JSFiddle - React, Tailwind, and code Playground

by Christian Sonne

HTML

<p contenteditable>Look at me, I have content, blah blah blah, lorem ipsum, pretty long text, maybe I'll wrap a few lines</p>
<button id="run">Run</button>

CSS

p {
  font-size: 3em;
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.l {
  animation: rotate;
  animation-duration: 1s;
}

JavaScript

function markup(el) {
	let {top, left, width, height} = el.getBoundingClientRect();
  let ctop = top, cleft = left;
  el.style.width = width + "px";
  el.style.height = height + "px";
  window.getComputedStyle(el);
  el.style.padding = 0;
	let text = el.innerText;
  let words = text.split(" ");
  el.innerHTML = words.map(w => w.split("").map(l => `<span class="l">${l}</span>`).join("")).join(" ");
  el.style.position = "relative";
  let letters = el.querySelectorAll(".l");
  for (let letter of letters) {
  	let {top, left} = letter.getBoundingClientRect();
    letter.style.left = (left - cleft) + "px";
    letter.style.top = (top - ctop) + "px";
    //letter.style.position = "absolute";
    window.setTimeout(function() {this.style.position = "absolute";}.bind(letter), 0)
    
  }
}

run.addEventListener("click", function() {markup(document.querySelector("p"))});