Javascript / textarea dynamic height response (stop at max.)

What I'm trying to achieve is a text box that starts as one line, but grows to 4 lines and at that moment starts to scroll if the user continues to enter text. I have a partial solution that works, it grows and then stops when it reaches its maximum, but if you delete the text, it does not shrink as I want.

This is what I still have.

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 scrollHeight problem scrollHeight not decrease when height set to something more. Any suggestion on how I can fix this will also be shortened if the text is deleted?

+7
source share
4 answers

You can use autosize for this.

Live demo

 import React, { Component } from 'react'; import autosize from 'autosize'; class App extends Component { componentDidMount(){ this.textarea.focus(); autosize(this.textarea); } render(){ const style = { maxHeight:'75px', minHeight:'38px', resize:'none', padding:'9px', boxSizing:'border-box', fontSize:'15px'}; return ( <div>Textarea autosize <br/><br/> <textarea style={style} ref={c=>this.textarea=c} placeholder="type some text" rows={1} defaultValue=""/> </div> ); } } 

or if you prefer to respond modules https://github.com/andreypopp/react-textarea-autosize

+12
source

ANOTHER SIMPLE APPROACH (without 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 text and the text area is not compressed is that you forgot to set this line

 e.target.style.height = 'inherit'; 

Try using onKeyDown because it works for all keys while others cannot ( w3schools )

In case you have padding or border top or bottom . ( link )

 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 can help.

+1
source

You can even do this with abstract links. how to set a link to an element

 <textarea ref={this.textAreaRef}></textarea> // after react 16.3 <textarea ref={textAreaRef=>this.textAreaRef = textAreaRef}></textarea> // before react 16.3 

and update the height to componentDidMount or componentDidUpdate as you need. with,

 if (this.textAreaRef) this.textAreaRef.style.height = this.textAreaRef.scrollHeight + "px"; 
0
source

The above answer of ANOTHER SIMPLE APPROACH (without an additional package) seems to have the problem that if I press the enter key, it increases the height of the text area, even if there is no data inside the text area. Does anyone have any solution to this?

0
source

All Articles