htmltextarea 怎么用:从基础写法到常见属性

htmltextarea 怎么用:从基础写法到常见属性

htmltextarea 怎么用:从基础写法到常见属性

<textarea> 是 HTML 中用于输入多行文本的表单控件。留言、备注、反馈、文章内容等需要换行的文本,通常都适合用它。它看起来像一个可拖动的文本框,但它的初始值、换行规则和表单行为与单行的 <input> 并不完全相同。

本文从最基本的写法开始,逐步说明常用属性、表单提交、JavaScript 操作和安全边界。示例中的 HTML 标签已转义,复制代码时请将示例里的 &lt;、&gt;、&amp; 分别还原为 <、>、&。

一、textarea 适合什么场景

当用户需要输入一段可能包含换行的纯文本时,<textarea> 通常是合适的选择,例如:

  • 联系表单中的留言、问题描述或反馈;
  • 订单备注、地址补充说明;
  • 文章编辑器中的纯文本内容;
  • 让用户粘贴较长代码、日志或配置文本。

如果只需要输入一行内容,例如姓名、邮箱或搜索词,应优先考虑对应类型的 <input>。如果需要富文本编辑、格式工具栏或复杂的内容结构,则需要专门的编辑器,不能仅靠 <textarea> 实现。它接收的是文本,不会把用户输入自动解析成可视化格式。

二、最基本的写法

<textarea> 是成对标签,初始文本写在开始标签和结束标签之间,而不是写在 value 属性中:

<label for="message">留言</label>
<textarea id="message" name="message"></textarea>

这里的 id 用于让 label 关联控件,点击标签文字时可以聚焦文本框;name 则是表单提交时使用的字段名。没有 name 的控件通常不会作为字段提交。

初始内容放在元素内部:

<label for="note">备注</label>
<textarea id="note" name="note">请填写需要补充的信息。</textarea>

需要留意缩进和换行。标签之间的空白也属于初始文本的一部分,所以这种写法可能让文本框一开始就多出换行或空格:

<textarea>
  这段文字前后可能包含换行和空格。
</textarea>

如果要求初始值精确,尽量把内容紧贴开始标签和结束标签,或在脚本中明确设置 value。与单行输入框不同,<textarea> 没有用于设置初始文本的 value HTML 属性。

三、大小与显示方式:rows、cols、wrap

rows 和 cols

rows 设置文本框可见的行数,cols 设置大致的可见字符宽度。它们影响控件的初始尺寸,不限制用户最终能输入多少内容。

<textarea name="message" rows="5" cols="40"></textarea>

rows 和 cols 都应是正整数。未指定时,浏览器会使用默认尺寸;常见默认值分别为 2 行和 20 列,但实际显示大小还可能受到字体、样式和浏览器影响。它们不是精确的像素值,也不是内容长度限制。

页面布局通常更适合用 CSS 控制,例如设置宽度、高度或最大宽度。不要一边用 cols 控宽,一边用 CSS 设置相冲突的尺寸。

<textarea class="message" name="message" rows="5"></textarea>

<style>
.message {
  box-sizing: border-box;
  width: 100%;
  max-width: 42rem;
  min-height: 8rem;
}
</style>

wrap 换行行为

wrap 控制换行如何影响提交的文本,常用值是 soft 和 hard:

  • soft:文本框内会按宽度视觉换行,但这些自动换行一般不会作为新增换行字符加入提交值。它是默认行为。
  • hard:提交时会把因宽度产生的换行纳入文本。使用 hard 时应设置 cols,换行结果还会受到浏览器实现影响。
<textarea name="description" rows="4" cols="40" wrap="soft"></textarea>
<textarea name="plainText" rows="4" cols="40" wrap="hard"></textarea>

两者都不会替代服务端的换行处理。若应用对文本行数、格式或换行符有要求,应在服务端按实际收到的值验证和处理,而不是假定所有浏览器提交的结果完全相同。

四、常用属性与限制

placeholder:提示,不是默认值

placeholder 用于在文本框为空时显示简短提示:

<textarea name="question" placeholder="请描述遇到的问题"></textarea>

提示文字不会作为用户输入提交,也不应代替 label。控件一旦有内容,提示就会消失。说明字段用途、格式或限制时,应使用可见的标签或帮助文字,而不是只依赖占位提示。

maxlength 和 minlength:约束字符长度

maxlength 指定用户输入的最大长度,minlength 指定非空值允许的最小长度。属性值应为非负整数,例如:

<label for="feedback">反馈(最多 500 个字符)</label>
<textarea id="feedback" name="feedback" maxlength="500"></textarea>

浏览器通常会限制用户输入超过 maxlength 的内容,并在约束校验中使用长度规则。长度按 UTF-16 代码单元计数,并不总等同于用户感知的“字符”:某些表情符号会占用多个代码单元。因此,如果产品要求按字素簇、字节数或其他口径计数,需要明确实现相应规则,不能把 maxlength 当成任意计数方式。

minlength 不表示文本框一开始就自动填满,也不会代替业务校验;空值是否可接受还要看 required 等规则。浏览器端限制可以被绕过,服务端必须独立验证长度和内容。浏览器对极大长度的实际处理能力也受实现限制,不应据此承诺任意大的输入都能稳定工作。

required、readonly 和 disabled

required 表示表单提交前必须提供非空值。它会触发表单约束校验,但不会验证内容是否符合业务语义:

<label for="reason">请说明原因</label>
<textarea id="reason" name="reason" required></textarea>

readonly 表示用户不能编辑内容,但控件仍可聚焦,且通常会随表单提交;只读控件不参与约束校验,因此不要将 required 用在只读文本框上。disabled 会禁用控件,无法正常聚焦和编辑,且该字段不会随表单提交。

<textarea name="generated" readonly>系统生成的内容</textarea>
<textarea name="optional" disabled>暂不可编辑</textarea>

需要“显示但不允许改、同时提交”的场景可以考虑 readonly;需要“暂时不可用且不提交”的场景才适合 disabled。无论哪一种,都不能把客户端字段状态当作权限控制:服务端仍需检查提交数据和用户权限。

其他常见属性

  • autocomplete:提示浏览器是否可以自动补全,例如 on 或 off。浏览器是否遵从还可能受自身策略影响。
  • autofocus:页面加载后请求自动聚焦。多个自动聚焦控件会造成体验和可访问性问题,通常应谨慎使用。
  • form:通过表单的 id 指定关联表单,适用于控件不在表单标签内部的情况。
  • spellcheck:提示浏览器是否检查拼写;其具体表现取决于浏览器和语言环境。
  • dirname:可让浏览器在提交时附带文本方向信息字段,适用于需要获知输入方向的场景,字段名由该属性值指定。

五、放进表单并获取提交值

表单提交使用 name 作为字段名,文本框内容作为字段值。下面是一个可直接运行的示例:

<form action="/feedback" method="post">
  <label for="feedback-text">你的反馈</label>
  <textarea
    id="feedback-text"
    name="feedback"
    rows="5"
    maxlength="1000"
    required></textarea>
  <button type="submit">提交</button>
</form>

当表单通过常规方式提交时,浏览器会发送类似 feedback=填写的文本 的字段。换行和特殊字符会按表单编码规则处理。使用 method="get" 时,字段会进入 URL 查询参数;长文本或可能包含敏感内容的数据通常不适合放在 URL 中。对敏感数据应使用 HTTPS,并在服务端进行访问控制和校验。

也可以用 JavaScript 读取表单数据:

<form id="feedback-form">
  <label for="feedback-text">反馈</label>
  <textarea id="feedback-text" name="feedback"></textarea>
  <button>提交</button>
</form>

<script>
const form = document.querySelector("#feedback-form");

form.addEventListener("submit", (event) => {
  event.preventDefault();

  const data = new FormData(form);
  const feedback = data.get("feedback");

  console.log(feedback);
});
</script>

脚本中也可以直接读写 textarea.value。这是当前控件的文本值:

<textarea id="memo"></textarea>

<script>
const memo = document.querySelector("#memo");
memo.value = "第一行\n第二行";

console.log(memo.value);
</script>

设置 value 不等同于设置 HTML 属性,也不会自动改变元素内部的初始文本。通常读取和更新用户当前输入时使用 value,不要把 innerHTML 当成文本值接口。

六、动态字符计数示例

下面的示例实时显示已输入长度和最大长度。JavaScript 的字符串 length 同样按 UTF-16 代码单元计数,与浏览器长度约束的计数口径相符;它不代表用户看到的字符个数。

<label for="bio">个人介绍(最多 200 个字符)</label>
<textarea id="bio" name="bio" maxlength="200" rows="4"></textarea>
<p id="bio-count" aria-live="polite">已输入 0 / 200</p>

<script>
const bio = document.querySelector("#bio");
const count = document.querySelector("#bio-count");
const max = bio.maxLength;

function updateCount() {
  count.textContent = `已输入 ${bio.value.length} / ${max}`;
}

bio.addEventListener("input", updateCount);
updateCount();
</script>

input 事件会在用户编辑时触发。若界面还会通过脚本修改 value,脚本赋值通常不会自动触发 input 事件,因此应在赋值后主动调用更新函数,或按应用状态管理方式同步更新。

七、安全处理:textarea 不是安全过滤器

<textarea> 只是文本输入控件,不会自动过滤 HTML、脚本或危险内容。安全的关键在于数据最终被放进什么上下文,以及服务端如何处理数据。

在页面上展示用户输入时,应使用文本接口,例如设置 textContent,而不要把未经处理的输入拼接进 innerHTML:

<div id="preview"></div>
<script>
const userText = '<img src=x onerror=alert(1)>';
document.querySelector("#preview").textContent = userText;
</script>

这里写入的是普通文本,不会创建图片元素。相反,若将不可信字符串赋给 innerHTML,浏览器可能把它解析为 HTML,造成跨站脚本风险。

把动态数据直接拼到 HTML 中的 <textarea> 内容也有风险。例如,用户内容如果包含结束标签文本 </textarea>,可能提前结束文本框并改变后续页面结构。仅在 JavaScript 中把小于号替换成某种实体,并不一定适用于所有输出上下文。应使用框架提供的安全模板转义,或采用与具体上下文匹配的可靠编码方式;不要把用户输入当作 HTML 片段直接输出。

服务端还应进行业务所需的长度、权限和数据校验。输入校验有助于保证数据符合预期,但不能代替输出编码;输出编码也不能代替服务端授权检查。存储用户文本时,应按业务需要保存文本本身,并在展示到 HTML、属性、URL 或脚本等不同上下文时分别采用正确的安全处理方式。

八、常见错误与排查

1. 把初始值写成 value 属性

<textarea value="hello"> 不是设置初始文本的正确方式。把文本放在标签之间,或在脚本中设置 element.value。

2. 忘记设置 name

控件能显示、也能编辑,不代表表单会提交它。检查是否设置了 name,以及控件是否被禁用、是否关联到预期的表单。

3. 把 rows、cols 当成字符限制

它们主要影响可见尺寸,不限制输入长度。限制长度应使用 maxlength,并在服务端再次校验。

4. 用 placeholder 代替标签

提示文字会在用户输入后消失,也不总能替代可访问名称。为控件提供明确的 label,必要时补充说明文字。

5. 误以为 readonly 和 disabled 一样

只读字段通常仍会提交,禁用字段则不会。需要什么提交行为,应结合表单实际验证;服务器不能信任客户端状态。

6. 误解换行符和字符数

视觉换行不一定会成为提交文本中的换行;wrap="hard" 会影响提交值。长度属性按 UTF-16 代码单元计数,也不等于字节数或所有语言下的可见字符数。

7. 直接把用户输入作为 HTML 输出

文本框不会替你完成安全过滤。输出到页面时优先使用安全的文本接口;确需输出富文本时,应采用经过审查的净化方案,并在服务端和客户端明确处理信任边界。

九、可访问性与样式建议

每个文本框都应有清晰的可访问名称,最简单的做法是使用 <label for> 与控件 id 对应。较长的填写要求可以用说明文字,并通过 aria-describedby 关联:

<label for="details">问题详情</label>
<p id="details-help">请勿填写密码或其他敏感信息。</p>
<textarea
  id="details"
  name="details"
  aria-describedby="details-help"
  rows="6"></textarea>

样式上应保证文本和背景有足够对比度,焦点状态清晰可见,并避免把文本框缩小到难以输入的尺寸。是否允许用户拖动改变大小,可以通过 CSS 的 resize 属性控制;如果禁用拖动,应确认响应式布局仍能容纳较长内容。

总结

<textarea> 用于多行纯文本输入:初始内容写在标签之间,name 决定表单字段名,rows 和 cols 主要控制尺寸,maxlength 等属性提供浏览器端约束。实际开发中还要区分只读与禁用、理解换行和长度的计数边界,并在服务端验证数据、在输出时采用适合当前上下文的安全处理方式。

© 版权声明

相关文章