What I'm trying to achieve is a textarea that starts out as a single line but will grow up to 4 lines and at that point start to scroll if the user continues to type. I have a partial solution kinda working, it grows and then stops when it hits the max, but if you delete text it doesn't shrink like I want it to.
This is what I have so far.
export class foo extends React.Component {
constructor(props) {
super(props);
this.state = {
textareaHeight: 38
};
}
handleKeyUp(evt) {
// Max: 75px Min: 38px
let newHeight = Math.max(Math.min(evt.target.scrollHeight + 2, 75), 38);
if (newHeight !== this.state.textareaHeight) {
this.setState({
textareaHeight: newHeight
});
}
}
render() {
let textareaStyle = { height: this.state.textareaHeight };
return (
<div>
<textarea onKeyUp={this.handleKeyUp.bind(this)} style={textareaStyle}/>
</div>
);
}
}
Obviously the problem is scrollHeight
doesn't shrink back down when height
is set to something larger. Any suggestion for how I might be able to fix this so it will also shrink back down if text is deleted?
To set the height of a text area dynamically with JavaScript and React, we can set the height of the text area when we type into it. to set the onKeyDown prop to the handleKeyDown function. In it, we set the height of the text area to the e. target.
To disable the resizing (drag thumb) just use resize: none; . To restrict size max(min)-width and height should do the trick. Show activity on this post. You can set the resize property as horizontal and vertical or set it as default(the user can stretch in both ways).
To prevent a text field from being resized, you can use the CSS resize property with its "none" value. After it you can use the height and width properties to define a fixed height and width for your <textarea> element.
ANOTHER SIMPLE APPROACH (without an additional package)
export class foo extends React.Component {
handleKeyDown(e) {
e.target.style.height = 'inherit';
e.target.style.height = `${e.target.scrollHeight}px`;
// In case you have a limitation
// e.target.style.height = `${Math.min(e.target.scrollHeight, limit)}px`;
}
render() {
return <textarea onKeyDown={this.handleKeyDown} />;
}
}
The problem when you delete the text and textarea doesn't shrink back is because you forget to set this line
e.target.style.height = 'inherit';
Consider using onKeyDown because it works for all keys while others may not (w3schools)
In case you have padding
or border
of top
or bottom
. (reference)
handleKeyDown(e) {
// Reset field height
e.target.style.height = 'inherit';
// Get the computed styles for the element
const computed = window.getComputedStyle(e.target);
// Calculate the height
const height = parseInt(computed.getPropertyValue('border-top-width'), 10)
+ parseInt(computed.getPropertyValue('padding-top'), 10)
+ e.target.scrollHeight
+ parseInt(computed.getPropertyValue('padding-bottom'), 10)
+ parseInt(computed.getPropertyValue('border-bottom-width'), 10);
e.target.style.height = `${height}px`;
}
I hope this may help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With