textarea, File Uploads and Hidden Fields
Three controls with their own rules: a textarea whose value is its content, a file input that needs the right enctype, and hidden fields that are not secret.
-
HTML Basics
- What is HTML: The Structure Layer of Every Web Page
- HTML Document Structure: DOCTYPE, html, head and body
- Elements, Tags and Attributes: The Vocabulary of HTML
- HTML Comments: Notes That Ship With Your Code
- Block Level and Inline Elements
- Writing and Running Your First HTML Page
- How a Browser Turns Markup Into a Page
- Text and Formatting
- Links and Navigation
- Images and Media
- Lists
- Tables
-
Forms
- Form Structure: form, action and method
- Input Types: Text, Email, Number, Date and the Rest
- Labels: The Most Important Element in a Form
- Checkboxes, Radio Buttons and Grouping
- select, option, optgroup and datalist
- textarea, File Uploads and Hidden Fields
- Buttons: submit, reset and button
- Built In Form Validation
- GET or POST: What Happens When a Form Is Submitted
- Semantic HTML
- HTML5 Features
- Head and Metadata
- HTML with CSS
- HTML with JavaScript
- Accessibility
-
HTML SEO
- How Google Works: Crawling, Indexing and Ranking
- SEO Friendly HTML Structure
- Titles and Descriptions That Earn Clicks
- Headings and Content Structure for Search
- Internal Linking and Anchor Text
- robots.txt and XML Sitemaps
- Canonical URLs and Duplicate Content
- Structured Data and JSON-LD
- Image SEO
- Core Web Vitals and Mobile Friendliness
- DevTools and Debugging
- Editor Productivity
- HTML Best Practices
- HTML Projects
- Advanced Projects
- Practice and Exams
textarea
A multi line text box. Unlike input, it is not a void element, and its value is the text between the tags rather than a value attribute.
<label for="message">Your message</label>
<textarea id="message" name="message" rows="6" cols="40"></textarea>This creates a real trap. Whitespace inside the tags is content, so writing it on separate lines gives the field a leading newline:
<!-- starts with a blank line -->
<textarea name="bio">
</textarea>
<!-- empty, as intended -->
<textarea name="bio"></textarea>
<!-- with a starting value -->
<textarea name="bio">Tell us about yourself</textarea>| Attribute | Effect |
|---|---|
rows | Visible lines of text |
cols | Visible width in characters |
maxlength / minlength | Character limits |
wrap | soft (default) or hard, which inserts real line breaks on submit |
placeholder, required, readonly | As on input |
Prefer CSS to cols for width, since a percentage width is responsive and a character count is not:
textarea {
width: 100%;
min-height: 8rem;
resize: vertical; /* let readers grow it, but not sideways */
font: inherit; /* browsers default to a monospace font */
}A visible character counter helps when there is a limit. Put it in a live region so it is announced without stealing focus:
<textarea id="bio" name="bio" maxlength="300" aria-describedby="bio-count"></textarea>
<p id="bio-count" aria-live="polite">300 characters remaining</p>File uploads
<form action="/upload" method="post" enctype="multipart/form-data">
<label for="photo">Passport photograph</label>
<input type="file" id="photo" name="photo"
accept="image/jpeg,image/png" required>
<button type="submit">Upload</button>
</form>Two things are mandatory and both are easy to forget:
method="post". A file cannot travel in a URL.enctype="multipart/form-data". Without it the browser sends only the file name, and the upload silently fails with no error anywhere.
accept
<input type="file" accept="image/*"> <!-- any image -->
<input type="file" accept=".pdf,.doc,.docx"> <!-- by extension -->
<input type="file" accept="image/jpeg,image/png"> <!-- by media type -->
<input type="file" accept="image/*" capture="environment"> <!-- open the camera -->accept filters the file chooser. It is a convenience, not a security control - the reader can select any file, and the file type must be verified on the server by inspecting the contents rather than trusting the extension or the declared type.
Multiple files
<input type="file" name="documents[]" multiple accept=".pdf">Styling
The file input cannot be styled. The usual approach is to hide it correctly - not with display: none - and style the label as a button:
<label for="photo" class="file-button">Choose a photograph</label>
<input type="file" id="photo" name="photo" class="visually-hidden">
<span id="file-name" aria-live="polite">No file chosen</span>The label already focuses and activates the input, so no script is needed to open the chooser. A script is needed only to display the chosen file name.
Server side limits
Nothing in HTML limits file size. That is enforced by the server, and on PHP it is governed by upload_max_filesize, post_max_size and max_file_uploads. A file exceeding the limit is rejected before your code runs, so handle that case explicitly rather than assuming an upload always arrives.
Hidden fields
<input type="hidden" name="form_id" value="enquiry-2026">
<input type="hidden" name="redirect_to" value="/thank-you">
<input type="hidden" name="csrf_token" value="a1b2c3d4e5f6">A hidden field is submitted like any other but is never displayed. It carries state the server needs and the reader does not set.
Hidden does not mean secret. The value is in the page source, visible in view source, in the Elements panel and in the Network tab, and it can be edited before submission with two clicks. Never put a price, a user id, a role, a discount amount or anything else security relevant in one and trust it on the way back.
<!-- dangerous: the reader can edit this to 1 -->
<input type="hidden" name="price" value="4999">
<!-- safe: an identifier the server resolves to a price it owns -->
<input type="hidden" name="product_id" value="kettle-2l">The one legitimate security use is a CSRF token: a value the server generated, sent to this reader, and verifies on the way back. Its safety comes from the server knowing what it issued, not from the field being hidden.
Important rules
- A textarea value is its content; whitespace inside the tags is part of the value.
- File uploads need
postandmultipart/form-data. acceptis a filter, not a validator.- A hidden field is fully visible and fully editable by the reader.
- Hidden fields need no label, since there is nothing to interact with.
- A disabled hidden field is not submitted.
Common mistakes
- Writing a textarea across two lines and shipping a leading newline in every value.
- Forgetting
enctypeand getting an upload that silently does nothing. - Trusting
acceptas a security measure. - Putting a price or a user id in a hidden field and using it on the server.
- Hiding a file input with
display: none, removing it from the tab order. - Using
colsfor width instead of CSS. - Assuming a file always arrives, and crashing when the server limit rejects it.
Best practices
- Write
<textarea></textarea>on one line when it should start empty. - Set textarea width in CSS and allow vertical resizing only.
- Show a live character counter when there is a limit.
- Always set
acceptto narrow the chooser, and always validate on the server. - State the accepted formats and the maximum size in visible text next to the field.
- Send identifiers in hidden fields, never values the server can look up itself.
- Include a CSRF token in every state changing form.
Practice
- Write a textarea over two lines, submit it, and inspect the value the server receives.
- Build an upload form without
enctypeand observe what arrives, then add it. - Open DevTools, change a hidden field value and submit. Explain what a server must do to be safe.
- Build a styled file chooser using a label, and confirm it is reachable by keyboard.