最稳方式是display: flex + flex-direction: column,需确保父容器设display: flex且子元素为独立;writing-mode: vertical-rl更语义化,适合东亚文字原生竖排。

用 display: flex + flex-direction: column 最稳
直接给文字容器设为 flex 并竖排,是现代浏览器里最可靠、最可控的方式。它不依赖行高或伪元素,也不受字体渲染差异干扰。
常见错误是只写 flex-direction: column 却忘了设 display: flex,结果样式完全不生效;或者把 flex 应用在 <p></p> 上却期望内部文字逐字换行——其实它默认按子元素(比如多个 <span></span>)排列。
- 把每个要垂直排列的字符或词包进独立
<span></span>,再让父容器启用 flex 竖排 - 如果是一整段文字想“字字换行”,得先用 JS 拆成字符数组再拼回带
<span></span>的 HTML,纯 CSS 做不到自动逐字拆分 - 注意
align-items控制水平对齐(如center),justify-content控制垂直方向间距分布(如flex-start或space-between)
<div class="vertical-text">
<span>文</span>
<span>字</span>
<span>垂</span>
<span>直</span>
</div>
<p><style>
.vertical-text {
display: flex;
flex-direction: column;
align-items: center;
}
</style></p>
用 writing-mode: vertical-rl 实现真正的竖排文本流
这是专为东亚文字设计的原生方案,文字自动从上到下、从右到左排列,标点、数字、英文也能按规范正确旋转和对齐,比手动拆 <span></span> 更语义化。
容易踩的坑:Chrome/Firefox 支持良好,但 Safari 对 writing-mode 在某些内联场景(比如套在 <a></a> 里)有渲染延迟或错位;另外它不会自动把一串汉字拆成单字堆叠——整块文字仍是一个行框,只是书写方向变了。
- 适用于标题、侧边栏标签、传统排版场景,比如「章节名」「印章文字」
- 配合
text-orientation: mixed可让英文/数字保持正立(不旋转90°),避免阅读障碍 - 若需居中显示,别用
text-align: center,而要用margin: auto或 flex 包一层再居中
<div class="vertical-title">文字垂直排列</div>
<p><style>
.vertical-title {
writing-mode: vertical-rl;
text-orientation: mixed;
width: 2em; /<em> 必须设宽度,否则可能撑满整行 /
}
</style></p>
避开 line-height + height 这种“伪垂直”陷阱
有人用超大 line-height 配合固定 height 强制每行只显一个字,看似有效,实则问题一堆:文字实际并未垂直排列,只是被行高“撑开”;换字体、缩放页面、读屏器解析都会出错;移动端 pinch-zoom 后布局极易崩。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
这种写法在调试时看起来像垂直,但本质是视觉欺骗,不是真实布局逻辑。一旦内容动态变化(比如后端返回字数不定的标题),就必须同步改 CSS,维护成本高。
- 绝对不要用
line-height: 2em模拟单字一行,除非你明确只要临时 demo 且不考虑可访问性 -
white-space: pre-line或pre-wrap也无法解决逐字换行需求,它们只响应换行符 \n - 若必须兼容 IE11,
writing-mode: tb-rl是旧语法替代项,但已废弃,且不支持mixed方向
JS 辅助拆字时注意 DOM 性能和空格处理
当设计要求严格“每个汉字、字母、数字都独占一行”,又不想手写一堆 <span></span>,就得靠 JS 拆解。但直接对长字符串用 .split('') 会把全角空格、换行符、零宽字符也拆进去,导致多余空行。
更麻烦的是,频繁操作 innerHTML 可能触发重排,尤其在列表项多或滚动中更新时。别在 for 循环里反复设 innerHTML += <span>...</span>。
- 用正则
/[\u4e00-\u9fa5a-zA-Z0-9]/g提取有效字符,忽略空白和符号(按需调整) - 批量生成字符串后一次性赋值给
innerHTML,或用document.createElement+append批量插入 - 如果文字来自用户输入或 API,记得做防 XSS 处理,别直接插 raw string
const text = "Hello世界123";
const chars = text.match(/[\u4e00-\u9fa5a-zA-Z0-9]/g) || [];
const html = chars.map(c => <span>${c}</span>).join('');
el.innerHTML = html;
实际用哪种方式,取决于你是否需要语义正确、是否要适配读屏器、有没有动态内容,以及设计师交付稿里那个“垂直”到底指视觉错觉还是真实排版逻辑。多数情况下,writing-mode 是首选,flex 是兜底,其他都是权衡后的妥协。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










