Creating a Textarea with dynamic height using React and Typescript

Owen Herterich
2 min readJan 13, 2022

Introduction

In this article, I’ll show you how to create a <textarea> that automatically grows and shrinks depending on the content within. This solution can also be extracted to a React Hook, allowing it to be easily reused across multiple components and projects.

A preview of the finished product.

Background

There are several techniques out there for auto-sizing your <textarea> elements using Javascript. Some of these include:

  • Adding the contenteditable property to a different HTML element.
  • Count the number of line-breaks and and multiply by the line-height to get the overall height.
  • Use a psuedo-element to update the size of the element based on the content inside the <textarea>

In my opinion, all of the aforementioned solutions have some pretty serious trade-offs and could lead to some undesired bugs and quirks in the implementation.

Taking advantage of React

Instead of relying on hack-y solutions, we can use React to our advantage. One way to do this is to make your <textarea> a controlled component. This allows React to be the single source of truth for the value of the contents of the element. As a result, we can use the useEffect hook to wait for that value to change and subsequently calculate the correct height.

Setting the height

The secret here is to use the scrollHeight of the <textarea> to figure out exactly how tall that it should be. To do that, we simply need to set the height of the <textarea> to 0 momentarily to force the scrollHeight to equal the intrinsic height of the element.

Once we get that value, we can simply set the height of the element using the style property - this will force the <textarea> to take up the height of its contents.

Keep in mind that we need to do all of this inside of the same useEffect hook. If we try to use state or refs to store scrollHeight this trick won’t work.

Note: make sure the rows property of your <textarea> is set to 1 (it defaults to 2 ). This will ensure that the initial height of the element is correct.

Creating a reusable hook

I also extracted this logic to a reusable hook — useAutosizeTextArea. This isn’t strictly necessary, but I felt it was a useful, compact way to bring this functionality to other components in the future.

To use the hook, simply call it inside the component and pass the ref and current value of the <textarea> .

Example

Live example of the dynamic <textarea>

--

--

Owen Herterich

Front-end web developer with experience in creating flexible, innovative, and design-oriented websites.