JSFiddle - React, Tailwind, and code Playground
HTML
<textarea onkeydown="textarealimit(this, 4, 43, 'textarea_rowsleft', 'textarea_charsleft');" onkeyup="textarealimit(this, 4, 43, 'textarea_rowsleft', 'textarea_charsleft');" onpaste="textarealimit(this, 4, 43, 'textarea_rowsleft', 'textarea_charsleft');" rows="4" style="overflow: hidden; resize: none;">
</textarea>
<div>
Rows left: <span id="textarea_rowsleft">4</span>
Characters left: <span id="textarea_charsleft">43</span>
</div>
JavaScript
function textarealimit(textarea, rows, chars, rowsleft_id, charsleft_id) {
var newValue;
var valueSegments = textarea.value.split('\n');
if(rows != undefined && valueSegments.length > rows) { // too many rows
newValue = valueSegments.slice(0, rows).join("\n");
}
if(chars != undefined && textarea.value.length > chars) { // too many chars
if(newValue != undefined)
newValue = newValue.substring(0, chars);
else
newValue = textarea.value.substring(0, chars);
}
if(newValue != undefined) textarea.value = newValue;
if(rowsleft_id != undefined) {
if(textarea.value == "") document.getElementById(rowsleft_id).innerHTML = rows;
else if(rows - valueSegments.length >= 0) document.getElementById(rowsleft_id).innerHTML = rows - valueSegments.length;
}
if(charsleft_id != undefined) {
if(chars != undefined) document.getElementById(charsleft_id).innerHTML = chars - textarea.value.length;
}
}