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');
}
}
});
...