Explain Codes LogoExplain Codes Logo

Is there a way to get a textarea to stretch to fit its content without using PHP or JavaScript?

html
responsive-design
css
javascript
Alex KataevbyAlex Kataev·Oct 25, 2024
TLDR

It's not possible to auto-expand a <textarea> to fit its content using CSS alone. Using a smidge of JavaScript with a mirrored <div> style technique does the trick, making the JavaScript fairly lightweight and non-invasive.

<div style="position:relative;"> <textarea class="auto-expand" style="min-height:40px; height:auto; overflow:hidden; resize:none;"></textarea> <!-- Our trusty mirror div, invisible but ever present --> <div class="mirror-text" style="white-space:pre-wrap; visibility:hidden; position:absolute; z-index:-1;"></div> </div>
// Mirrored div technique is just like a mirror in a dodge ball game, it's always helping you out document.querySelector('.auto-expand').addEventListener('input', function() { document.querySelector('.mirror-text').textContent = this.value; this.style.height = 'auto'; this.style.height = this.scrollHeight + 'px'; });

The .mirror-text div seamlessly mimics the textarea styling, ensuring accurate height dimensions.

CSS alone isn't enough, let's explore why

A purely CSS solution for dynamic textarea resizing based on content isn't feasible. That's because CSS alone lacks the properties to dynamically adjust to the content. Known workarounds using overflow:auto or resize:vertical fall short as they rely on user interaction or are statically set.

The 'contenteditable' attribute to the rescue…

If you are fine with using JavaScript, using the contenteditable attribute presents a fantastic alternative to <textarea>. It makes any element editable and expands along with the content. Do remember that it requires sanitization to prevent HTML injection

<div contenteditable="true" style="min-height:40px; max-height:200px; overflow:auto;"> Place Editable Content Here </div>

The above block expands with the content, but again, JavaScript is necessary to read the data from the div for form submission.

Enhancing user experience

Despite the limitations of pure CSS, adding resize:vertical allows users to manually adjust the height of the textarea

.auto-expand { min-height: 40px; max-height: 200px; resize: vertical; /* Everyone loves a resize option, it's like adjustable seats in a car */ }

The rows attribute is a neat trick to set a minimum height:

<textarea rows="3"></textarea>

While the maxLength attribute doesn't directly change the height, it indirectly affects content fitting by setting a character limit.

In the wild: Practical applications

While a purely CSS solution for dynamic resizing of a textarea remains impossible, the small amount of JavaScript required for the task is lightweight, non-invasive, and a fair trade-off for all practical purposes.

Efficient JavaScript

The JavaScript used is a one-time setup that prompts the textarea to adjust according to the user's input.

Handling form submissions

When using contenteditable, keep in mind that a hidden <input> element will be required to store the text for form submissions:

<form> <div contenteditable="true" id="editable"></div> <input type="hidden" name="textareaContent" id="hiddenInput"> </form>

You'd then need JavaScript to synchronize the editable div content with the hidden input's value upon form submission.

Styling with CSS

Using CSS variables simplifies and maintains synchronized styling between your textarea and mirror div:

:root { --textarea-font-size: 16px; --textarea-line-height: 1.5; --textarea-padding: 10px; } .auto-expand, .mirror-text { font-size: var(--textarea-font-size); line-height: var(--textarea-line-height); padding: var(--textarea-padding); /* "Copy-paste" styling? CSS variables beg to differ */ }