如何实现支持垂直正向输入的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
相关产品推荐
相关产品推荐

