20 · 文案长度、排版容量与共享策略

适用:标题溢出、按钮换行、卡片高度不齐、翻译变长、用户输入被截断,或多个页面各自判断字符串长度。问题不应一律交给“缩小字号”。

TEXT-01 · 分开管理四种约束

约束决定什么所有者
业务长度是否允许保存、采用何种单位领域规则与服务端协议
编辑预算作者希望多简洁、何时需要改写内容规范,可按语境调整
排版尺度字号、字重、行高与文字层级设计系统与组件语义
布局容量可用宽度、换行、折叠、完整查看页面模式与容器

按钮文案预算是编辑建议,不应通过截断按钮文字隐藏动作。文章标题的存储限制不能变成卡片上“每个汉字占 16px”的宽度算法。

TEXT-02 · 先约定“一个字符”怎么算

JavaScript 的 string.length 和 HTML maxlength 使用 UTF-16 码元数量。码点数量、UTF-8 字节数、用户感知字符数并不相同,emoji 与组合附加符号尤其明显。参见 MDN maxlength。

需要按可见字符计数时,可使用 Intl.Segmenter 的 grapheme 分段。它不能替代字体测宽,旧环境应采用验证过的兼容实现或明确限制支持范围。参见 MDN Intl.Segmenter。

const segmenter = new Intl.Segmenter('zh-CN', { granularity: 'grapheme' });
const count = value => [...segmenter.segment(value)].length;
// 👨‍👩‍👧‍👦 与 e + 组合重音分别可构成一个扩展字素簇。

规则采用 grapheme 时,不能再用同一个数字设置原生 maxlength,否则会提前拒绝 emoji。前后端必须对齐算法与 Unicode 版本;若服务端按字节限制,就按实际协议设计输入体验。

TEXT-03 · 封装规则,分别输出业务结果与文案

字段策略:maxGraphemes、是否 trim、是否允许空值、规范化策略。
纯函数:计数与验证,返回稳定原因代码和实际数量。
领域文案:把原因代码映射成用户可理解的提示。
字段组件:显示标签、帮助、计数与错误,连接输入与焦点。
页面:决定保存时机与操作流程。

这样修改上限时,提示、计数和校验一起变化;翻译提示时不用修改校验逻辑;另一个领域的字段也不会被误改。不要把字符串长度判断分散在页面、按钮和请求拦截器中。

组合输入期间不要裁切、自动改写或重置光标。提交时仍需校验;对已经出现的错误,可以在完成组合输入后更新。粘贴超长内容应保留可修正的输入并明确提示,不能悄悄丢弃后半段。

TEXT-04 · 按信息重要性决定溢出策略

内容默认策略需要保留的能力
主要按钮与危险动作容器扩展或合理换行动作完整可读,不靠悬停补含义
金额、时间、对象标识结构调整、专门格式化核心值和单位准确可取
列表标题换行;确有需要再限定行数触控和键盘可获取完整内容
正文与错误原因自然换行、可展开无硬裁切,修复步骤完整
连续 URL 或长标识局部允许断行,必要时复制保存原值,展示不改变数据
辅助摘要允许缩略或改写详情有完整版本

CSS ellipsis 只改变展示,JS slice 会改变得到的字符串。不要用 slice(0, 20) 当跨语言的通用摘要,更不能拿处理后的值提交保存。

title 属性或只在 hover 时出现的 tooltip,不足以作为手机与键盘用户查看完整文本的唯一入口。截图里整齐,不等于信息可用。

TEXT-05 · 字号由语义决定,不由字符数决定

正文、帮助文字、标签和标题通过共享 typography token 管理。容器宽度变化时优先换行、重排和渐进披露;不能按 length > 20 把标题变成极小字号。

标题可以使用有上下界的响应式字号,但仍要检查缩放和大字号。数字与单位可组成可控区域;不应给所有内容统一 white-space: nowrap,也不能靠固定行高裁掉翻译后的文字。

TEXT-06 · 翻译、动态插值与富文本一起设计

使用语义完整的消息,支持复数和参数;不要用“成功”+数量+“个”拼成无法翻译的句子。用户名称、项目名等插值按不可信文本处理,禁止直接拼 HTML。

金额、数量、日期的格式化可以共享;法律或业务准确性要求不能为了卡片宽度简写。不同语境允许不同消息键,禁止把所有“取消”强行绑定同一个翻译。

TEXT-07 · 用边界内容验证,而不是同长占位字

至少检查:空值、仅空白、临界长度、超限、中文、连续英文、URL、emoji、组合字符、RTL、超长翻译、极大数与大字号。输入法还要检查组词、回车确认、删除、粘贴和选择替换。

演示的名称编辑采用共享长度策略、原因代码和文案函数;可在实验室粘贴组合 emoji 体验。可下载文本策略模块。该模块只负责计量和长度校验,不负责过滤 HTML、服务端授权或字体测宽。