JSFiddle - React, Tailwind, and code Playground

by bgrins

HTML

<div class='container'>
    <textarea></textarea>
    <pre><div></div></pre>
</div>

CSS

.container {
    border: solid 1px;
    position:relative;
    overflow:hidden;
    display: inline-block;
}

.container textarea,
.container pre {
    border: solid 0;
    margin: 0;
    padding: 0;
    white-space: pre-wrap;
    display: block;
}

.container pre {
    position: absolute;
    top: 0; left: 0; width: 100%; height: 100%;
    pointer-events: none;
    overflow:hidden;
}
.container textarea { color: #222; }

/* XXX: Should only style certain elements */
pre div {
    color: red;
}

JavaScript

function update() {

    var textarea = document.querySelector("textarea");
    var clone = document.querySelector("pre");
    var value = textarea.value;
    value = value.replace(/\r\n/g, "\n");
    document.querySelector("pre div").textContent = value;
       
    _copyTextareaStylesToClone($(textarea), $(clone));
    /// xxx put each 'foo' string inside of a styled span
    
    
    clone.scrollTop = textarea.scrollTop;
    
    
    //document.querySelector("pre div").scrollTo( document.querySelector("textarea").scrollLeft, document.querySelector("textarea").scrollTop);
    console.log(document.querySelector("pre").scrollTop, document.querySelector("pre").scrollHeight);
}

document.querySelector("textarea").addEventListener("input", update);
document.querySelector("textarea").addEventListener("change", update);
document.querySelector("textarea").addEventListener("keyup", update);
document.querySelector("textarea").addEventListener("scroll", update);
document.querySelector("textarea").addEventListener("resize", update);


// https://bgrins.github.io/ExpandingTextareas/expanding.js
    function _copyTextareaStylesToClone (textarea, clone) {
      var properties = [
          'lineHeight', 'textDecoration', 'letterSpacing',
          'fontSize', 'fontFamily', 'fontStyle',
          'fontWeight', 'textTransform', 'textAlign',
          'direction', 'wordSpacing', 'fontSizeAdjust',
          'wordWrap', 'word-break',
          'borderLeftWidth', 'borderRightWidth',
          'borderTopWidth','borderBottomWidth',
          'paddingLeft', 'paddingRight',
          'paddingTop','paddingBottom', 'maxHeight'];

      $.each(properties, function(i, property) {
        var val = textarea.css(property);

        // Prevent overriding percentage css values.
        if(clone.css(property) !== val) {
          clone.css(property, val);
          if(property === 'maxHeight' && val !== 'none') {
            clone.css('overflow', 'hidden');
          }
        }
      });
   ...