Listening for changes to textareas #
First, let’s setup an event listener to detect changes to our textarea
element. We’ll use event delegation to listen to all input
events and then filter out ones that aren’t on a textarea.
document.addEventListener('input', function (event) {
if (event.target.tagName.toLowerCase() !== 'textarea') return;
}, false);
If the element is a textarea, we’ll call a new function we’re going to create, autoExpand()
, and pass in the element as an argument using event.target
.
document.addEventListener('input', function (event) {
if (event.target.tagName.toLowerCase() !== 'textarea') return;
autoExpand(event.target);
}, false);
Auto-expanding the textarea #
Now, we can setup our autoExpand()
function.
var autoExpand = function (field) {
// Do things...
};
First, we need to reset the height of the textarea so that we can calculate how tall the content is/should be.
var autoExpand = function (field) {
// Reset field height
field.style.height = 'inherit';
};
To calculate our height, we need to get both the height of the content, and any borders and padding on the textarea that will affect its overall height.
We’ll use window.getComputedStyle()
to get styles for the textarea, and scrollHeight
to calculate the height of the content itself.
We’ll run all of the values through parseInt()
to convert them to integers, and then add them up to get our total element height.
// Get the computed styles for the element
var computed = window.getComputedStyle(field);
// Calculate the height
var height = parseInt(computed.getPropertyValue('border-top-width'), 10)
+ parseInt(computed.getPropertyValue('padding-top'), 10)
+ field.scrollHeight
+ parseInt(computed.getPropertyValue('padding-bottom'), 10)
+ parseInt(computed.getPropertyValue('border-bottom-width'), 10);
Finally, we’ll set the height of our element using the style
property.
var autoExpand = function (field) {
// Reset field height
field.style.height = 'inherit';
// Get the computed styles for the element
var computed = window.getComputedStyle(field);
// Calculate the height
var height = parseInt(computed.getPropertyValue('border-top-width'), 10)
+ parseInt(computed.getPropertyValue('padding-top'), 10)
+ field.scrollHeight
+ parseInt(computed.getPropertyValue('padding-bottom'), 10)
+ parseInt(computed.getPropertyValue('border-bottom-width'), 10);
field.style.height = height + 'px';
};
Here’s the complete function snippet:
/*!
* Automatically expand a textarea as the user types
* (c) 2021 Chris Ferdinandi, MIT License, https://gomakethings.com
* @param {Node} field The textarea
*/
function autoExpand (field) {
// Reset field height
field.style.height = 'inherit';
// Get the computed styles for the element
let computed = window.getComputedStyle(field);
// Calculate the height
let height =
parseFloat(computed.paddingTop) +
field.scrollHeight +
parseFloat(computed.paddingBottom);
field.style.height = height + 'px';
}