skip to content

In HTML, how do you give a <textarea> an initial value, and what do its rows and cols attributes actually control?

level: middleimportance: should knowfreq 42%

answer

  1. no value attribute anywhere on it
  2. the children are the default value
  3. raw text: tags inside are literal
  4. first newline after the tag disappears
  5. lines visible, characters wide — nothing more

basics

~20 s

A textarea has no value attribute: its initial text is whatever sits between the opening and closing tags, and a newline right after the opening tag is dropped by the parser. The rows and cols attributes set the visible line count and average character width.

solid answer

~40 s

Unlike `<input>`, `<textarea>` has no `value` attribute — its default value is its element content, so you write `<textarea name="bio">Hello</textarea>`. The content is parsed as raw text, so tags inside it are literal characters and you must escape anything that looks like a closing textarea tag; a single newline immediately after the opening tag is swallowed by the parser, which is why people indent the closing tag and get mystery leading whitespace. `rows` is the number of visible text lines (default 2) and `cols` is the visible width in average character widths (default 20); both are just the initial box size and CSS overrides them. Because it is a default value, a form reset restores that content, not whatever the user typed.

code

html · 4 lines
html
<!-- The first newline after the tag is dropped; later whitespace is not -->
<label for="note">Note</label>
<textarea id="note" name="note" rows="4">
Starts with S, no leading blank line.</textarea>

go deeper

for a junior

Know that a textarea's starting text goes between the tags rather than in a value attribute, and that rows sets how many lines are visible. Say plainly that neither rows nor cols caps the amount of text.

for a middle

Explain that the content is the default value in the same sense as an input's value attribute, describe the raw-text parsing rules, and be ready to name the stripped-first-newline behaviour when asked why a field starts with blank space.

for a senior

Show that you think about the value crossing boundaries: escaping when templating user content into the element, CRLF normalisation on submission versus a single newline in the DOM, and why serialising the DOM does not capture what the user typed.

for a principal

Be ready to set the house rule for multi-line input across a product — where a plain textarea suffices versus where a rich editor is justified, and what the richer control costs in accessibility, paste handling, and sanitisation on the way to storage.

## Content is the value `<input>` carries its default in a `value` attribute. `<textarea>` cannot: its value is multi-line text, and attribute values are a poor place for line breaks. So the element's *children* are the value: ```html <label for="bio">Short bio</label> <textarea id="bio" name="bio" rows="6" cols="40">Frontend engineer.</textarea> ``` This is the element's **default value** — the same role `value` plays on an input. It is what the control shows on load and what a form reset restores. Once the user types, the current value lives only in the DOM; the markup does not change. Serialising the DOM back to a string therefore does not capture what the user typed, which is a classic surprise when someone tries to "save the HTML". ## The parser rules that bite `<textarea>` is a *raw text* element (along with `<title>`). Two consequences: 1. **Markup inside is not markup.** A `<b>` tag written inside a textarea shows up as the literal characters `<b>`, not as bold text. Only character references such as `&amp;` are decoded. 2. **The closing tag cannot appear in the content.** The first closing textarea tag ends the element. If your server templates user content into a textarea, that same string appearing in the content would terminate it early and let the rest be parsed as markup — so escape at least `<` and `&` when interpolating. And the rule everyone hits once: **a newline immediately after the opening tag is stripped** by the parser. That is why this is safe — ```html <textarea> Hello</textarea> ``` — it yields exactly `Hello`. But this is not: ```html <textarea> Hello </textarea> ``` Only the *first* newline is dropped; the two indent spaces, the trailing newline and any further whitespace are all part of the value. Pretty-printed templates are the usual source of a textarea that mysteriously starts with blank space. Put the content flush against the tags, or emit it from a template expression. ## rows and cols `rows` is the number of text lines visible without scrolling; the default is 2. `cols` is the visible width measured in average character widths; the default is 20. Both are *initial sizing* only — they impose no limit whatsoever on how much the user may type, and CSS `width`/`height` override them. So why set them? Because they render before any stylesheet applies, they give a sensible box if CSS fails, and `rows` is the honest way to express "this field expects about six lines" — a size hint the user reads as an expectation of how much to write. Setting `cols` on a fluid layout is usually pointless since a width rule will win. Limiting the *amount* of text is a separate concern handled by `maxlength`/`minlength`, not by `rows`/`cols`. ## wrap, and what actually gets submitted `wrap` has two values. The default, `wrap="soft"`, means the text wraps visually but is submitted exactly as typed — no line breaks are inserted. `wrap="hard"` inserts a real line break at each wrap point in the submitted value, and requires `cols` to be specified so the browser knows where the wraps fall. `hard` is rare and only makes sense for fixed-width output such as plain-text email bodies. One more normalisation to know: line breaks in the value read from the DOM are `\n`, but on submission the value is normalised to CRLF (`\r\n`) pairs. Code that counts characters client-side and server-side can disagree by one byte per line break because of this. ## Resizing and the other attributes Browsers make textareas user-resizable by default; that behaviour is controlled by CSS, not markup. The genuinely useful markup attributes beyond the above are `placeholder` (a hint, never a substitute for a label), `readonly` (submitted but not editable), `disabled` (not editable and *not* submitted), and `spellcheck`. Auto-growing a textarea as the user types has no markup solution and requires script.

  • What is the difference between wrap="soft" and wrap="hard" on a textarea?
    `soft` is the default: the text wraps visually but is submitted exactly as the user typed it, with no inserted line breaks. `hard` makes the browser insert real line breaks at every visual wrap point in the submitted value, and it requires `cols` so the wrap column is defined. You would only want `hard` when the consumer expects fixed-width plain text, such as a plain-text email body.
  • You render user-supplied text into a textarea from a server template. What must you escape, and why?
    At minimum `<` and `&`. A textarea is a raw text element, so the first closing textarea tag in the content ends the element — unescaped content containing that string would close the field early and let the remainder be parsed as markup. Escaping `<` prevents that, and escaping `&` stops character references in the user's text from being decoded into something else.
  • A user's 500-character text is rejected by the server as 512 characters. What in the textarea's behaviour could explain the discrepancy?
    Line-break normalisation. The value you read in the DOM uses a single `\n` per line break, but the value the browser submits normalises breaks to CRLF, adding one byte per line. A twelve-line message therefore arrives twelve characters longer than a client-side count suggested. Count on the same normalisation on both sides, or set the limit with `maxlength`, which the browser enforces consistently against what the user sees.

saying these in an interview costs you the question

  • Setting an initial value with a value attribute on textarea
  • Thinking rows and cols limit how much can be typed
  • Putting HTML tags inside a textarea and expecting them to render
  • Blaming CSS for a leading blank line from template indentation
  • Assuming the markup updates as the user types

context