textarea

Multi-line text input for longer content like messages, comments, or descriptions. Unlike input type='text', textarea allows line breaks and resizing.

When to Use

  • Comments and messages
  • Descriptions and bios
  • Address fields (multi-line)
  • Code or text snippets
  • Any free-form text longer than a single line

Basic Usage

A simple textarea with label and placeholder.

Code

<label for="message">Message</label> <textarea id="message" name="message" placeholder="Enter your message..."></textarea>

Attributes

Attribute Purpose Example
rows Initial visible lines rows="5"
cols Visible character width cols="40"
minlength Minimum character count minlength="10"
maxlength Maximum character count maxlength="500"
required Field must have a value required
disabled Prevents editing disabled
readonly Can select but not edit readonly
placeholder Hint text when empty placeholder="..."
wrap Text wrapping behavior wrap="soft"
spellcheck Enable/disable spell check spellcheck="true"

Setting Size

Using rows Attribute

Control the initial height with rows.

Code

<textarea rows="3"></textarea> <!-- 3 lines --> <textarea rows="5"></textarea> <!-- 5 lines --> <textarea rows="10"></textarea> <!-- 10 lines -->

Character Limits

Use minlength and maxlength for validation.

Minimum 50 characters, maximum 200

Code

<textarea minlength="50" maxlength="200"></textarea>

Textarea States

Disabled

Cannot be edited or focused.

Read-only

Can be selected and copied but not edited.

Invalid

Shows validation error state.

Please enter at least 50 characters

Code

<textarea disabled>Cannot edit</textarea> <textarea readonly>Can select but not edit</textarea> <textarea aria-invalid="true">Invalid content</textarea>

With form-field

Use the form-field custom element for CSS-only validation.

Please enter at least 10 characters

Code

<form-field> <label for="message">Message</label> <textarea id="message" name="message" required minlength="10" rows="5" aria-describedby="message-msg"></textarea> <output id="message-msg" for="message" aria-live="polite"> Please enter at least 10 characters </output> </form-field>

Real-World Examples

Contact Form Message

Be as specific as possible so we can assist you better.

Code/Snippet Input

Address Input

Comment with Character Counter

0/500 characters

Resizing Behavior

By default, textareas can be resized vertically. CSS controls this behavior.

CSS Property Behavior
resize: vertical Can resize height only (default)
resize: horizontal Can resize width only
resize: both Can resize in both directions
resize: none Cannot be resized

Character / Word Count (data-count)

Add data-count to any textarea to show a live character or word count. Works with native maxlength for character mode and data-maxwords for word mode. Color shifts at 80% (warning) and 100% (error).

Character Count

The default mode counts characters. Pair with maxlength to show “42 / 500” format.

<form-field> <label for="bio">Bio</label> <textarea id="bio" maxlength="500" data-count></textarea> </form-field>

Word Count

Set data-count="words" and data-maxwords for word-based counting.

<textarea data-count="words" data-maxwords="200" placeholder="Write your essay..."></textarea>
Attribute Values Description
data-count "", "words" Enable counter. Empty for characters, "words" for word mode.
data-maxwords number Max word count (word mode only).

Auto-Expand (data-grow)

Add data-grow to a textarea to make it automatically expand as the user types. Uses CSS field-sizing: content where supported, with a JS scrollHeight fallback. Set data-max-rows to cap the height.

<textarea data-grow rows="2" placeholder="Type to see it grow..."></textarea>

Max Rows

Set data-max-rows to limit growth. Once the limit is reached, the textarea scrolls normally.

<textarea data-grow rows="2" data-max-rows="10" placeholder="Grows up to 10 rows, then scrolls..."></textarea>

Combined with Count

data-grow and data-count work together seamlessly.

<form-field> <label for="msg">Message</label> <textarea id="msg" data-grow data-count maxlength="500" rows="2" placeholder="Auto-grows with character count..."></textarea> </form-field>
Attribute Values Description
data-grow Enable auto-expanding behavior.
data-max-rows number Maximum rows before scrolling.

Accessibility Notes

  • Always use a label: Every textarea needs an associated label
  • Don't disable resize: Allow users to resize for their needs when possible
  • Provide character limits: If using maxlength, show remaining characters
  • Use aria-describedby: Link to help text or validation messages
  • Placeholder is not a label: Placeholders disappear when typing
  • Spell checking: Keep spellcheck enabled for prose, disable for code

CSS Reference

textarea { display: block; inline-size: 100%; padding-block: var(--size-s); padding-inline: var(--size-s); min-block-size: 8rem; border: var(--border-width-thin) solid var(--color-border); border-radius: var(--radius-m); background: var(--color-surface); font: inherit; resize: vertical; transition: border-color var(--duration-fast); } textarea:focus { outline: none; border-color: var(--color-interactive); box-shadow: 0 0 0 3px oklch(from var(--color-interactive) l c h / 0.15); } textarea::placeholder { color: var(--color-text-muted); } textarea:disabled { background: var(--color-surface-raised); cursor: not-allowed; } textarea[aria-invalid="true"] { border-color: oklch(55% 0.25 25); }

Related Elements

  • input - Single-line text input
  • label - Required for accessibility
  • form - Container for textareas
  • form-field - Enhanced textarea with validation