Details That Make Interfaces Feel Better
Layout
1. 分组
目标: 用户一眼能看出哪些内容属于一起。
- 同一组内容之间的距离要小,不同组之间的距离要明显更大。
- 不同组之间的间距,建议至少是组内间距的 2 倍。
- 优先用留白区分内容;留白不够清楚时再使用背景;最后才使用分割线。
- 如果仅靠间距已经能看出分组,就不要再加分割线。
2. 对齐
目标: 页面看起来有稳定的结构,不杂乱。
- 同一级内容尽量沿同一条左边线或右边线排列。
- 相同类型的内容使用相同的对齐方式。
- 子内容需要缩进时,同一级子内容使用相同的缩进距离。
- 不要为了“看起来差不多”随意把某个元素单独向左或向右移动几像素。
3. 内容顺序
目标: 重要内容先被看到,次要内容后被看到。
- 页面默认按照从上到下、从左到右的顺序安排信息。
- 最重要的信息放在更靠前的位置。
- 一行信息中,名称、标题等主要信息放前面;时间、状态、辅助操作等次要信息放后面。
- 不要让次要信息比主要信息更抢眼。
4. 可点击内容和普通内容要能区分
目标: 用户能看出哪些东西可以点击。
- 按钮、链接、可操作区域不能看起来和普通文字完全一样。
- 可以通过背景、边框、下划线、固定按钮区域等方式表示“这里可以操作”。
- 同一种操作在不同页面中应保持相同的表现方式。
5. 被隐藏的内容必须有提示
目标: 用户知道还有更多内容可以展开、滑动或查看。
- 如果内容被折叠,必须显示“展开”、箭头等提示。
- 如果内容可以横向滑动,可以露出下一项的一小部分,让用户知道右边还有内容。
- 不要把内容完全藏起来,又不给任何提示。
6. 操作按钮之间要留足距离
目标: 多个按钮不会挤在一起,也不容易点错。
- 有边框或背景的相邻按钮,间距可以从约
12px开始。 - 只有文字或图标的操作,周围需要更大的留白,可以从约
24px开始。 - 两组不同操作之间的距离,要明显大于同一组按钮之间的距离。
7. 页面边缘的使用
目标: 背景可以铺满屏幕,但文字和操作不要贴边。
- 背景、图片、视频可以延伸到屏幕边缘。
- 正文、按钮等主要内容要和屏幕边缘保持稳定距离。
- 移动端没有现成规范时,左右可以先使用约
16px的边距。 - 除非有明确设计目的,否则按钮和文字不要直接贴到屏幕边缘。
8. 视觉对齐优先于数学对齐
目标: 元素看起来是对齐的,而不是只看坐标是否相等。
- 播放按钮、箭头、尖角图标等形状不对称,即使数学上居中,看起来也可能偏。
- 这种情况下允许轻微移动
1–2px,让它视觉上更居中。 - 如果图标本身画歪了,优先修改图标本身,不要长期靠外边距补偿。
Responsive
1. 布局何时切换
目标: 只有当前布局真的放不下时,才切换结构。
- 不要因为屏幕到了
768px、1024px就固定切换布局。 - 当内容开始拥挤、重叠或被压缩到不可用时,再设置断点。
- 只要原布局仍能正常使用,就尽量保持原结构。
- 例如:侧边栏开始把正文压得过窄,或卡片已经无法保持合理宽度时,再切换布局。
2. 页面和组件分别适配
目标: 元素根据自己真正拥有的空间变化,而不是只看整个屏幕有多宽。
- 页面整体布局可以根据浏览器宽度变化。
- 独立组件应优先根据组件所在容器的宽度变化。
- 例如一个 Card 即使处于宽屏,如果被放进很窄的侧边栏,也应该切换成窄版布局。
- 这种组件级适配优先使用 Container Query,而不是只使用全局屏幕断点。
3. 内容变长时布局不能坏
目标: 文本长度变化后,组件仍然能够正常显示。
- 不要按照当前文案长度给文字容器设置固定宽度。
- 文字容器不要设置固定高度,需要最低高度时使用
min-height。 - 文本应该允许换行。
- Button 宽度应由
文字 + 左右 Padding决定,不要为文案写死固定宽度。 - 不同语言可能让文字明显变长,因此布局不能依赖某一种语言的长度。
4. 重要操作不能被裁掉
目标: 屏幕变小、内容变长或键盘弹出时,主要操作仍然可见。
- Primary Action 不应放在容易被裁掉的位置。
- 不要把主要按钮固定在一个可能溢出的固定高度区域底部。
- 如果内容区域需要滚动,主要操作可以放在独立且稳定的底部操作栏中。
- 固定在屏幕边缘的操作需要避开手机刘海、圆角和底部手势区域。
Typography
1. 字体数量与搭配
目标: 字体体系简单、明确。
- 整个界面通常不超过 3 种字体。
- 字体搭配应有明显差异,例如
Serif Heading + Sans Body。 - 不要同时使用两种看起来非常接近的字体。
2. 字号层级
目标: 通过稳定的字号层级表达信息重要性。
- 只使用少量固定字号,不为单个页面随意创建新字号。
- Heading 层级越低,视觉尺寸不得反而越大。
- 相邻层级可以字号相同,但必须通过字重或间距区分。
3. 字号与字重
目标: 保证文字清晰,同时维持合理层级。
- 长正文默认从约
16px开始。 - Input、Menu 等 UI 文字可从约
14px开始。 - Caption 可使用约
13px。 - 除特殊情况外,不使用低于
12px的文字。 18px以下文字使用400+字重。300以下的轻字重只用于约28px+的大字号展示文字。
4. 行高与字距
目标: 不同类型文字保持合适的阅读密度。
- Heading 行高约
1.1。 - 正文行高约
1.5–1.6。 - 三行及以上文字,行高至少约
1.4。 - 大标题可以使用轻微负字距。
- 小号全大写文字可以使用轻微正字距。
- 普通正文默认不额外调整字距。
5. 正文宽度
目标: 避免一行文字过长导致阅读困难。
- 长正文每行控制在约 60–75 个字符。
- 不让文章、说明文字随着容器无限变宽。
6. 换行
目标: 标题和正文产生自然、稳定的换行。
- 标题使用
text-wrap: balance,让多行标题长度更均衡。 - 短描述使用
text-wrap: pretty,避免最后一行只剩一个短词。 - URL、ID、长单词使用
overflow-wrap: break-word。 - Badge、短 Label 等不应换行的内容使用
white-space: nowrap。 balance和pretty不用于长篇正文。
7. 动态数字
目标: 数字变化时,文字位置保持稳定。
- Timer、Counter、Price、Metric 等会变化的数字使用等宽数字。
- 使用
font-variant-numeric: tabular-nums。 - 避免数字位宽变化导致界面左右跳动。
8. 文本截断
目标: 空间不足时控制文字长度,但不永久丢失重要内容。
- 单行文字使用省略号。
- 多行文字使用
line-clamp。 - 如果被截断的信息很重要,必须提供查看完整内容的方式。
- 不重要的信息才可以直接截断。
9. 字体渲染
目标: 避免 macOS 上文字显得过粗。
- Web 界面可以在全局使用字体抗锯齿:
-webkit-font-smoothing: antialiased。 - 应全局设置一次,不在单个组件重复设置。
Color
1. 颜色数量
目标: 控制颜色数量,让界面保持统一。
- 使用一套中性色,用于背景、文字、边框。
- 使用一个强调色,用于主要交互和品牌强调。
- 成功、警告、错误等状态色只在产品确实需要时添加。
- 不要为了“颜色体系完整”创建实际不会使用的颜色。
2. 同一颜色建立深浅层级
目标: 同一种颜色在不同场景下有稳定的深浅变化。
- 每个主要颜色建立从浅到深的一组颜色。
- 每一级必须有明确用途,例如背景、悬停、边框、按钮背景、文字。
- 不要创建没有实际用途的颜色等级。
- 同一组颜色应保持基本相同的色相,不要在深浅变化过程中明显变成另一种颜色。
3. 按用途使用颜色
目标: 组件颜色能够统一管理,并随主题一起变化。
- 不要在组件里直接使用
blue-500、gray-300这类具体颜色。 - 先定义颜色用途,例如:
- 主要文字
- 次要文字
- 页面背景
- 卡片背景
- 边框
- 强调色
- 错误色
- 组件只使用这些用途颜色。
- 不要因为两个颜色当前看起来一样,就混用不同用途的颜色。
4. 一种颜色只表达一种含义
目标: 用户看到颜色后能够预测它代表什么。
- 如果强调色表示“可以点击”,不要同时用于普通静态文字。
- 如果红色表示错误或危险,不要同时用于普通装饰。
- 相同含义在不同页面中使用相同颜色。
- 不同含义不要使用容易混淆的相近颜色。
5. 主要操作的颜色
目标: 用户一眼能找到当前最重要的操作。
- 实色强调色主要用于最高优先级操作。
- 一个界面区域通常只保留一个最明显的主要操作。
- 其他并列操作降低颜色强度,避免多个按钮同时争夺注意力。
6. 深色模式
目标: 深色模式保持与浅色模式一致的信息层级和颜色含义。
- 不要简单把浅色模式颜色反转。
- 深色模式需要单独调整亮度、对比度和颜色鲜艳程度。
- 同一颜色用途在浅色和深色模式下保持相同含义。
- 整个项目使用统一的主题切换机制。
7. 渐变
目标: 渐变过程自然,不出现脏灰或意外颜色。
- 普通渐变优先使用
OKLab插值。 - 需要保持较高颜色鲜艳度时使用
OKLCH。 - 避免仅依靠肉眼不断调整中间色来修复不自然的渐变。
Surface
1. 圆角
目标: 不同容器保持统一、自然的圆角关系。
- 同类组件使用相同圆角。
- 不要为不同组件随意创建大量圆角值。
- 小组件使用较小圆角,大容器可以使用更大圆角。
- 胶囊形按钮、标签等使用完全圆角。
2. 嵌套圆角
目标: 内外两层容器的圆角看起来保持同心。
- 外层圆角应根据内层圆角和两者之间的间距决定。
- 可使用:
外层圆角 ≈ 内层圆角 + 内边距。 - 内外圆角不要随意设置成互不相关的数值。
例如:
内层圆角 8px + 间距 8px → 外层圆角约 16px
3. 边框
目标: 只在需要明确边界时使用边框。
- 边框用于表示结构、分隔、选中、输入区域等明确边界。
- 如果通过背景或间距已经能区分区域,不再增加边框。
- 不要默认给所有 Card 和容器加边框。
- 同一级容器的边框粗细和样式保持一致。
4. 阴影
目标: 用阴影表达元素位于其他内容之上。
- Dropdown、Popover、Modal、浮动面板等悬浮元素可以使用阴影。
- 普通静态容器不要仅为了“更精致”而添加明显阴影。
- 如果只是希望容器从背景中轻微分离,可以使用非常浅的阴影代替明显边框。
- 避免同时使用强边框和强阴影。
5. 表面层级
目标: 用户能看出哪些内容位于同一层,哪些内容浮在上方。
- 页面背景、普通容器、浮动容器应形成清晰但克制的层级。
- 层级越高,不代表颜色或阴影必须越强。
- 不要通过大量不同背景色制造不必要的层级。
- 没有明确层级关系的内容应尽量使用相同表面样式。
6. 图片边缘
目标: 无论图片本身是深色还是浅色,都能和背景保持清晰边界。
- 图片容易与背景融在一起时,增加约
1px的低透明度内侧描边。 - 浅色背景使用低透明度深色描边。
- 深色背景使用低透明度浅色描边。
- 描边应足够弱,不应成为图片本身的视觉元素。
Icon
1. 图标风格
目标: 所有图标看起来属于同一套系统。
- 同一产品统一使用 Outline 或 Filled 为主的图标风格。
- 图标的线宽、圆角、视觉重量保持一致。
- 不要混用明显不同风格的图标库。
- 图标颜色默认跟随文字颜色。
2. 图标尺寸
目标: 图标尺寸稳定,不因页面不同随意变化。
- 使用少量固定尺寸,例如
16px / 20px / 24px。 - 相同用途的图标保持相同尺寸。
- 不要出现大量
17px / 19px / 21px等独立尺寸。
3. 图标与文字
目标: Icon + Text 看起来属于同一个整体。
- 图标与文字之间保持固定间距。
- 图标大小应与文字视觉重量匹配。
- 图标和文字使用视觉对齐,不只依赖数学居中。
- 非对称图标允许轻微偏移。
4. 图标状态变化
目标: 图标切换时能表达状态之间的关系。
Copy → Check、Play → Pause等状态切换不要默认瞬间替换。- 可使用
opacity + scale + blur做短暂过渡。 - 动画只用于表达状态变化,不用于纯装饰。
Buttons & Actions
1. 按钮层级
目标: 用户能快速判断哪个操作最重要。
- 按钮分为
Primary / Secondary / Ghost / Destructive。 - 一个区域通常只保留一个最明显的 Primary Action。
- 次要操作不得和主要操作拥有相同视觉权重。
- 危险操作应和普通操作明确区分。
2. 按钮尺寸
目标: 相同按钮在不同页面保持一致。
- 使用固定尺寸体系,例如
Small / Medium / Large。 - 同一尺寸按钮保持相同高度和左右内边距。
- 按钮宽度默认由内容决定。
- 不要因为文案不同随意改变按钮高度。
3. 按钮文案
目标: 用户不用猜就知道点击后会发生什么。
- 优先使用
动词 + 对象。 - 推荐:
Save changes、Create project、Delete account。 - 避免含义不明确的
OK、Yes、Confirm。 - 危险操作必须直接说明结果。
4. 图标按钮
目标: 只有图标的按钮仍然容易理解。
- 只在图标含义足够常见时使用 Icon-only Button。
- 不明显的图标应提供 Tooltip 或文字说明。
- 图标按钮保持固定点击区域。
- 不要因为图标本身很小就缩小整个操作区域。
Form Controls
1. 输入控件一致性
目标: 表单中的不同控件看起来属于同一系统。
- Input、Select、Textarea 等保持统一高度、圆角、边框和内边距。
- 同一表单不要混用明显不同的控件风格。
- 相同尺寸的控件应共享相同高度。
2. Label
目标: 用户始终知道字段要求填写什么。
- 每个输入项都应有明确 Label。
- Placeholder 不能代替 Label。
- Placeholder 只用于示例、格式提示或补充信息。
3. Placeholder
目标: Placeholder 只提供辅助信息。
- Placeholder 视觉权重低于真实输入内容。
- 不要在 Placeholder 中放必须记住的信息。
- 不要只靠 Placeholder 表达字段名称。
4. 错误状态
目标: 用户能快速发现并理解输入错误。
- 错误状态同时使用颜色和文字提示。
- 不要只把边框变红。
- 错误信息放在对应字段附近。
- 错误文案应说明哪里错了,必要时说明如何修复。
5. Checkbox / Radio / Switch
目标: 不同选择控件表达不同交互含义。
- Checkbox 用于多选。
- Radio 用于一组选一。
- Switch 用于立即生效的开关状态。
- 不要把这三种控件互相替代。
Navigation
1. 当前页面状态
目标: 用户始终知道自己当前在哪里。
- 当前页面或当前 Tab 必须有明确状态。
- Active State 不应只依赖非常轻微的颜色变化。
- 同一种导航组件使用统一的 Active 表现方式。
2. 导航层级
目标: 用户能理解不同导航项之间的层级关系。
- 一级和二级导航应通过缩进、字号或间距明确区分。
- 同一级导航项保持一致布局。
- 不要创建过多层嵌套导航。
3. Tabs
目标: Tabs 用于同一上下文中的并列内容切换。
- Tabs 之间应是同一级内容。
- 当前 Tab 必须明显可见。
- 不要用 Tabs 表达有上下级关系的页面。
- Tab 数量过多时不要强行挤在一行。
4. Sidebar
目标: Sidebar 提供稳定的主导航结构。
- 主导航位置保持稳定。
- 一级项目和子项目有明确缩进关系。
- 不要同时使用过多视觉强调。
- 当前项比 Hover 状态更明显。
5. Breadcrumb
目标: 在层级较深时帮助用户理解当前位置。
- Breadcrumb 表示真实的页面层级。
- 当前页面通常不需要可点击。
- 不要把 Breadcrumb 当作普通标签列表。
Interaction States
1. 必须存在的状态
目标: 用户每次操作都能获得明确反馈。
交互组件按需要提供:
- Default
- Hover
- Focus
- Pressed
- Selected
- Disabled
2. Hover
目标: 鼠标经过时明确提示元素可以操作。
- Hover 状态应能被看见,但不要过度突出。
- Hover 不得导致组件尺寸变化。
- 不要通过增加边框宽度造成 Layout Shift。
3. Focus
目标: 键盘用户能明确看到当前焦点位置。
- Focus 必须清晰可见。
- 推荐使用明显的 Focus Ring。
- Focus 与 Hover、Selected 状态应能区分。
- 不要直接移除默认 Focus 而不给替代样式。
4. Pressed
目标: 用户点击时获得即时反馈。
- Pressed 状态应比 Hover 更明确。
- 可以通过轻微颜色变化或轻微缩放表达。
- 不要使用夸张位移或缩放。
5. Selected
目标: 用户能明确看出哪些内容已被选择。
- Selected 状态必须持续可见。
- 不要只依赖 Hover 表示选中。
- Selected 和 Disabled 不得使用过于相似的表现方式。
6. Disabled
目标: 用户能看出当前操作不可用。
- Disabled 元素降低视觉权重。
- Disabled 不应看起来仍然可以点击。
- 不要让 Disabled 文本低对比度到难以阅读。
Motion
1. 动画目的
目标: 动画帮助用户理解变化,而不是单纯增加视觉效果。
动画只用于表达:
- 状态变化
- 层级变化
- 空间关系
- 操作反馈
- 内容进入或离开
2. 动画时长
目标: 动画足够快,不拖慢操作。
- 快速反馈约
100–150ms。 - 普通状态变化约
150–250ms。 - 较明显的进入动画约
250–400ms。 - 不要为不同组件随意创建大量动画时长。
3. 可中断动画
目标: 用户改变操作时,动画能够立即响应。
- Hover、Dropdown、Accordion、Toggle 等交互动画应可中断。
- 交互状态变化优先使用 Transition。
- 不要强迫用户等待一个固定动画播放完。
4. 内容进入
目标: 内容出现时能强化阅读顺序。
- 不要默认让整个大容器一起进入。
- Heading、Description、Actions 等可以分组进入。
- 多组内容可以使用轻微 Stagger。
- Stagger 可从约
100ms开始。
5. 内容退出
目标: 退出动画快速且不抢注意力。
- Exit 通常比 Entrance 更短、更轻。
- 优先使用小幅位移和透明度变化。
- 避免大距离飞出屏幕。
6. 减少动画
目标: 用户不希望看到动画时仍能正常使用界面。
- 非必要动画支持
prefers-reduced-motion。 - 减少动画后不能影响功能理解。
UI Copy
1. 文案清晰
目标: 用户无需解释就能理解界面文字。
- 优先使用短、直接、具体的表达。
- 避免为了“有趣”而牺牲清晰度。
- 不要使用内部术语或用户不了解的缩写。
2. 术语一致
目标: 同一个概念始终使用同一个名称。
- 如果叫
Workspace,不要在其他地方又叫Project或Space。 - 同一个操作在不同页面中使用相同文案。
- 不要为了避免重复而随意换同义词。
3. 操作文案
目标: 用户能预测操作结果。
- 按钮优先使用动词。
- 需要时使用
动词 + 对象。 - 不使用模糊的
OK、Yes、Continue代替明确操作。
4. 危险操作
目标: 用户明确知道操作会造成什么结果。
- 使用
Delete project、Remove member、Discard changes。 - 不使用
Confirm或Yes作为最终危险操作按钮。 - 危险操作的文案直接描述后果。
5. 错误提示
目标: 用户知道发生了什么,以及下一步怎么办。
- 错误信息说明具体问题。
- 能修复时,说明如何修复。
- 避免只显示
Something went wrong。
6. 链接文案
目标: 用户不用依赖上下文也能理解链接目的。
- 优先使用
View deployment logs、Read billing documentation。 - 避免单独使用
Click here、Read more、Learn more。