HTMLText Areas (<textarea>)

Text Areas (<textarea>)

<textarea> is a multi-line text input — the right choice whenever users need to enter more than a single line, such as a comment, a message, or a bio. Unlike <input>, it's not a void element: its default text goes between the opening and closing tags, not in a value attribute.

basic-textarea.html

HTML
<label for="message">Your message</label>
<textarea id="message" name="message">
Feel free to include as much detail as helpful.
</textarea>
Default text goes between the tags, not in value
Unlike text inputs, <textarea> has no value attribute for setting its initial content. Whatever text sits between <textarea> and </textarea> becomes the starting value — including any accidental whitespace or line breaks from your indentation, so be careful with formatting.
rows and cols vs CSS Sizing

rows and cols set the textarea's initial visible size in terms of text rows and character-width columns. They're a rough, font-dependent way to size the box and were the only sizing option before CSS existed. Today, CSS width and height give far more precise, responsive control, and are generally preferred.

rows-cols.html

HTML
<textarea name="bio" rows="6" cols="40"></textarea>

css-sizing.css

CSS
textarea.bio {
  width: 100%;
  max-width: 480px;
  height: 160px;
}

Approach

Precision

Responsiveness

rows/cols attributes

Approximate — depends on the rendered font

Fixed size regardless of viewport

CSS width/height

Exact pixel or relative-unit control

Can adapt with percentages, min(), media queries, etc.

rows/cols still matter as a fallback
Even when you size with CSS, it's good practice to keep sensible rows/cols attributes as a baseline — they apply immediately, before any stylesheet loads, avoiding a layout flash on slow connections.
Controlling Resize with CSS

Most browsers let users drag a corner handle to resize a <textarea> by default. The resize CSS property controls whether that's allowed, and in which directions.

resize.css

CSS
/* Disable manual resizing entirely */
textarea.fixed-size {
  resize: none;
}

/* Only allow vertical resizing, not horizontal */
textarea.comment-box {
  resize: vertical;
}

Value

Effect

none

User cannot resize the textarea at all

both

Default in most browsers — user can drag both dimensions

vertical

User can only change height

horizontal

User can only change width

Limiting Length with maxlength

The maxlength attribute caps how many characters the user can type, enforced natively by the browser as they type (not just on submit).

maxlength.html

HTML
<label for="tweet">What's happening?</label>
<textarea id="tweet" name="tweet" maxlength="280" rows="4"></textarea>
Pair maxlength with a live character counter
maxlength silently stops accepting input once the limit is hit — that can confuse users who don't notice why typing stopped working. Pair it with a small JavaScript-driven counter (e.g. "42 / 280") so the limit is visible as they type.
placeholder for Hint Text

placeholder shows light, temporary hint text inside the box until the user types something — useful for showing an example format, but it disappears on input and isn't read by all assistive technology the same way a real label is, so it should never replace a <label>.

placeholder.html

HTML
<label for="feedback">Feedback</label>
<textarea
  id="feedback"
  name="feedback"
  placeholder="Tell us what worked well and what didn't..."
  rows="5"
></textarea>
  • Use <textarea> for any multi-line free-text input, such as comments or messages.

  • Its default content sits between the opening and closing tags — there is no value attribute.

  • Prefer CSS width/height for precise, responsive sizing over relying solely on rows/cols.

  • Use the resize CSS property to allow, restrict, or disable manual resizing.

  • maxlength enforces a character cap live as the user types — pair it with a visible counter.

  • placeholder is hint text, not a replacement for a real, persistent <label>.

Building a Live Character Counter

Combining maxlength with a small script that listens for the input event gives users real-time feedback on how much room they have left.

counter-markup.html

HTML
<label for="tweet">What's happening?</label>
<textarea id="tweet" name="tweet" maxlength="280" rows="4"></textarea>
<p><span id="count">0</span> / 280</p>

counter.js

JS
const textarea = document.getElementById('tweet');
const counter = document.getElementById('count');

textarea.addEventListener('input', () => {
  counter.textContent = textarea.value.length;
});
Auto-Growing a Textarea to Fit Content

A textarea's height doesn't grow automatically as the user types more lines — it just scrolls internally once content exceeds the visible area. A common enhancement resets the height on each keystroke and sets it to match the content's actual scroll height.

auto-grow.js

JS
const textarea = document.getElementById('message');

textarea.addEventListener('input', () => {
  textarea.style.height = 'auto';
  textarea.style.height = `${textarea.scrollHeight}px`;
});
A newer CSS-only option exists
Some modern browsers support field-sizing: content in CSS, which auto-grows a <textarea> without any JavaScript. Support is still uneven across browsers, so the JavaScript approach above remains the more broadly compatible fallback.
Read-Only and Disabled Textareas

Like other form controls, a <textarea> can be marked readonly (visible, submitted, but not editable) or disabled (not editable and not included in the form submission at all).

readonly-disabled.html

HTML
<label for="terms">Terms (read-only)</label>
<textarea id="terms" readonly>These terms cannot be edited but are still submitted.</textarea>

<label for="notes">Notes (disabled)</label>
<textarea id="notes" disabled>This value will not be submitted at all.</textarea>
Spellcheck and Wrap Attributes

Attribute

Purpose

spellcheck

Set to "false" to disable the browser's spellcheck squiggles, useful for code or username fields

wrap

"soft" (default) wraps visually but submits one long line; "hard" inserts real line breaks into the submitted value, matching the visual wrapping

spellcheck-wrap.html

HTML
<textarea name="snippet" spellcheck="false" wrap="hard" rows="6"></textarea>
wrap=hard is useful for content where line breaks matter
If you're collecting something like a mailing address or code snippet in a textarea and need the submitted value's line breaks to match what the user visually sees, set wrap="hard" — otherwise the server may receive one unbroken line of text.