JSFiddle - React, Tailwind, and code Playground
by ocanal
HTML
<div class="container" id="container">
<div class="backdrop" id="backdrop">
<div class="highlights" id="highlights"></div>
</div>
<textarea id="textarea">12 test 22 2</textarea>
</div>
CSS
@import url(https://fonts.googleapis.com/css?family=Open+Sans);
*, *::before, *::after {
box-sizing: border-box;
}
body {
margin: 30px;
background-color: #f0f0f0;
}
.container, .backdrop, textarea {
width: 460px;
height: 180px;
}
.highlights, textarea {
padding: 10px;
font: 20px/28px 'Open Sans', sans-serif;
letter-spacing: 1px;
}
.container {
display: block;
margin: 0 auto;
transform: translateZ(0);
-webkit-text-size-adjust: none;
}
.backdrop {
position: absolute;
z-index: 1;
border: 2px solid #685972;
background-color: #fff;
overflow: auto;
pointer-events: none;
transition: transform 1s;
}
.highlights {
white-space: pre-wrap;
word-wrap: break-word;
color: #000;
}
textarea {
display: block;
position: absolute;
z-index: 2;
margin: 0;
border: 2px solid #74637f;
border-radius: 0;
color: transparent;
caret-color: #000;
background-color: transparent;
overflow: auto;
resize: none;
transition: transform 1s;
}
.number {
border-radius: 3px;
color: red;
background-color:transparent;
}
button {
display: block;
width: 300px;
margin: 30px auto 0;
padding: 10px;
border: none;
border-radius: 6px;
color: #fff;
background-color: #74637f;
font: 18px 'Opens Sans', sans-serif;
letter-spacing: 1px;
appearance: none;
cursor: pointer;
}
.perspective .backdrop {
transform:
perspective(1500px)
translateX(-125px)
rotateY(45deg)
scale(.9);
}
textarea:focus, button:focus {
outline: none;
box-shadow: 0 0 0 2px #c6aada;
}
JavaScript
var $container = document.getElementById('container');
var $backdrop = document.getElementById('backdrop');
var $highlights = document.getElementById('highlights');
var $textarea = document.getElementById('textarea');
var $toggle = document.getElementById('button');
// yeah, browser sniffing sucks, but there are browser-specific quirks to handle that are not a matter of feature detection
var ua = window.navigator.userAgent.toLowerCase();
var isIE = !!ua.match(/msie|trident\/7|edge/);
var isWinPhone = ua.indexOf('windows phone') !== -1;
var isIOS = !isWinPhone && !!ua.match(/ipad|iphone|ipod/);
function applyHighlights(text) {
text = text
.replace(/\n$/g, '\n\n')
.replace(/\d/g, '<span class="number">$&</span>');
if (isIE) {
// IE wraps whitespace differently in a div vs textarea, this fixes it
text = text.replace(/ /g, ' <wbr>');
}
return text;
}
function handleInput() {
var text = $textarea.value;
var highlightedText = applyHighlights(text);
$highlights.innerHTML = highlightedText;
}
function handleScroll() {
var scrollTop = $textarea.scrollTop;
$backdrop.scrollTop = scrollTop;
var scrollLeft = $textarea.scrollLeft;
$backdrop.scrollLeft = scrollLeft;
}
function fixIOS() {
// iOS adds 3px of (unremovable) padding to the left and right of a textarea, so adjust highlights div to match
//$highlights.css({
// 'padding-left': '+=3px',
// 'padding-right': '+=3px'
// });
}
function bindEvents() {
$textarea.oninput = handleInput;
$textarea.onscroll = handleScroll;
}
if (isIOS) {
fixIOS();
}
bindEvents();
handleInput();