You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现支持垂直正向输入的textarea或表单输入框?

嘿,这个问题确实挺棘手的——原生textarea对竖排输入的支持确实拉胯,不过我们有两个靠谱的方案可以解决:

方案一:用contenteditable div实现原生竖排输入体验

这是最省心的方案,因为contenteditable元素的输入行为会完全跟随CSS的writing-mode设置,比textarea灵活得多。你只需要把已经用在<p>标签上的CSS搬过来,再调整样式让它看起来像输入框就行:

<!-- 模拟textarea的竖排输入框 -->
<div class="vertical-input" contenteditable="true" placeholder="请输入竖排文本"></div>
.vertical-input {
  /* 核心竖排样式,和你之前的p标签一致 */
  writing-mode: vertical-lr;
  text-orientation: upright;
  
  /* 让它看起来像原生textarea */
  width: 220px; /* 可根据需求调整,比如按列数+字符宽度计算 */
  height: 400px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  padding: 8px;
  font-size: 16px;
  line-height: 1.8;
  caret-color: #212529; /* 确保竖排光标可见 */
  overflow-y: auto;
  background-color: white;
}

/* 模拟placeholder提示文字 */
.vertical-input:empty:before {
  content: attr(placeholder);
  color: #adb5bd;
}

这个方案的优势几乎是碾压级的:

  • 不需要复杂JS,输入体验和原生输入框完全一致
  • 光标会自动跟随竖排方向,输入满一列后自动跳到右侧新列继续书写
  • 现代浏览器(Chrome、Firefox、Edge)都完美支持,兼容性拉满

如果需要把内容提交到后台,只要在表单提交时,把这个div的innerText赋值给一个隐藏的<input>即可。

方案二:改造textarea(如果必须用textarea的话)

原生textarea的输入逻辑是硬编码的水平流,即使加了writing-mode,输入的字符还是会横向排列,所以必须用JS实时转换文本结构:

<textarea id="vertical-textarea" rows="20" cols="10" placeholder="请输入竖排文本"></textarea>
#vertical-textarea {
  writing-mode: vertical-lr;
  text-orientation: upright;
  width: 220px;
  height: 400px;
  font-size: 16px;
  line-height: 1.8;
  border: 1px solid #ced4da;
  border-radius: 4px;
  padding: 8px;
}
const textarea = document.getElementById('vertical-textarea');
// 计算每列能容纳的字符数(根据textarea高度和行高自动计算)
const lineHeight = parseInt(getComputedStyle(textarea).lineHeight);
const charsPerColumn = Math.floor((textarea.clientHeight - 16) / lineHeight); // 减去上下padding

let lastProcessedText = '';

textarea.addEventListener('input', () => {
  // 避免循环触发事件
  if (textarea.value === lastProcessedText) return;
  
  // 去掉所有换行,只保留纯输入文本
  const rawText = textarea.value.replace(/\n/g, '');
  let formattedText = '';
  
  // 按竖排逻辑重新排列文本:每charsPerColumn个字符为一列,列间用换行分隔
  for (let i = 0; i < rawText.length; i++) {
    const rowIndex = i % charsPerColumn;
    const colIndex = Math.floor(i / charsPerColumn);
    
    // 每列的第一个字符前加换行(第一列除外)
    if (rowIndex === 0 && colIndex !== 0) {
      formattedText += '\n';
    }
    
    formattedText += rawText[i];
  }
  
  // 更新文本并锁定光标到末尾
  lastProcessedText = formattedText;
  textarea.value = formattedText;
  textarea.setSelectionRange(formattedText.length, formattedText.length);
});

这个方案需要JS处理文本转换,输入速度快时可能有轻微延迟,光标位置的处理也可能需要根据实际场景微调,所以优先推荐方案一。

额外提示
  • 如果需要中文传统竖排效果(比如横排字母旋转90度),可以把text-orientation: upright改成text-orientation: mixed
  • 测试时注意不同浏览器的光标显示差异,大部分现代浏览器都已经支持竖排光标

内容的提问来源于stack exchange,提问作者storval

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 20:22:50