✨ Get all templates and new upcoming releases for just $89. Limited time offer ✨

Auto-Growing Textarea with Tailwind CSS

A preview of the form that contains the auto-expandable textarea

I really enjoy building user interfaces with CSS, it lets me do almost anything I want. However, at times, it can be frustrating when common functionalities are not natively supported. For example, there’s currently no built-in feature in CSS that allows me to adjust the height of a textarea based on its content. There is ongoing discussion about introducing a field-sizing property in CSS, but it is still in the early stages.

So, if you want a textarea that gets taller as more text is added, you have to use JavaScript or a simple CSS trick like the one I’m about to show you.

The idea comes from Stephen Shaw, and it’s very simple: you nest the textarea within another element configured as a grid. Then, you add a pseudo-element inside it replicating the textarea content. This pseudo-element will expand to fit the content, which in turn makes the outer grid element (and therefore the textarea) expand to the same height. So, as you add more text, the textarea grows to fit it.

We’ve reproduced this trick with Tailwind CSS. To use it, take the outer div and wrap your textarea with it. Ensure that your textarea includes the onInput event – it’s responsible for updating the content of the pseudo-element. Lastly, check that the padding of the textarea and the pseudo-elements are the same, and you’re good to go!

Code

<div class="
    grid
    text-sm
    after:px-3.5
    after:py-2.5
    [&>textarea]:text-inherit
    after:text-inherit
    [&>textarea]:resize-none
    [&>textarea]:overflow-hidden
    [&>textarea]:[grid-area:1/1/2/2]
    after:[grid-area:1/1/2/2]
    after:whitespace-pre-wrap
    after:invisible
    after:content-[attr(data-cloned-val)_'_']
    after:border
">
    <textarea
        class="w-full text-slate-600 bg-slate-100 border border-transparent hover:border-slate-200 appearance-none rounded px-3.5 py-2.5 outline-none focus:bg-white focus:border-indigo-400 focus:ring-2 focus:ring-indigo-100"
        name="message"
        id="message"
        rows="2"
        onInput="this.parentNode.dataset.clonedVal = this.value"
        placeholder="Your request..." 
        required
    ></textarea>
</div>