JSFiddle - React, Tailwind, and code Playground

by vjeux

HTML

<p style="width: 300px;">TextMateTextMateTextMateTextMateTextMateTextMateTextMateTextMate is heavily biased toward UTF-8. UTF-8 is an ASCII compatible encoding, so using it should give no problems with existing tools such as grep, diff, ruby (the interpreter), gcc (the compiler) etc.</p>

CSS

body {
    margin: 8px;
}
char {
  position: absolute;
}

JavaScript

function draw(opt) {
  var pos = {
    left: 0,
    top: 0
  }

  var letters = opt.text.split('').map(function (char) {
    var isWhiteSpace = char === ' ';

    var node = document.createElement('char');
    node.innerHTML = isWhiteSpace ? '&nbsp;' : char;
    document.body.appendChild(node);

    var width = node.getBoundingClientRect().width;

    return {
      isWhiteSpace: isWhiteSpace,
      node: node,
      width: width
    }
  });

  function getWordWidth(letters, i) {
    var width = 0;
    for (; i < letters.length && !letters[i].isWhiteSpace; ++i) {
      width += letters[i].width + opt.letterSpacing;
    }
    return width - opt.letterSpacing;
  }

  for (var i = 0; i < letters.length; ++i) {
    var letter = letters[i];
    if (!letter.isWhitespace &&
        i !== 0 && letters[i - 1].isWhiteSpace &&
        pos.left + getWordWidth(letters, i) >= opt.width) {
      pos.left = 0;
      pos.top += opt.lineHeight;
    }

    letter.node.style.left = (opt.left + pos.left) + 'px';
    letter.node.style.top = (opt.top + pos.top) + 'px';
    pos.left += letter.width + opt.letterSpacing;
  }
}

draw({
  letterSpacing: 0,
  lineHeight: 20,
  text: 'TextMateTextMateTextMateTextMateTextMateTextMateTextMateTextMate is heavily biased toward UTF-8. UTF-8 is an ASCII compatible encoding, so using it should give no problems with existing tools such as grep, diff, ruby (the interpreter), gcc (the compiler) etc.',
  left: 8,
  top: 8,
  width: 300
});