基础决定一套界面耐不耐看。从像素与分辨率、字号与行高,到间距、色彩、层级和栅格,这些底层规则先讲清楚,上面的组件和页面才不会散。
18 个概念
内圆角 = 外圆角 − 间距,两道弧线保持平行。
把盒子四角做成圆弧,半径越大越柔和、越像卡片与气泡。圆角要和组件尺寸成套:按钮小、卡片中、大容器大,才像同一个家族;相邻圆角盒之间会留下难看的凹口,需要用同心圆角(外半径 = 内半径 + 间距)修正,或让它们干脆对齐。
160px + 2×1px border → 160px total
line
line-strong
accent
content-box 会在 160px 之外再加边框;border-box 让总宽保持不变。
用线条勾出元素的边界与状态:border 占据盒模型空间、outline 画在盒外不挤动布局、box-shadow 的 ring 用透明阴影描一圈。 普通态用低对比 border 静默分界,悬停加深、聚焦用 outline、报错换色;三者各司其职,边界才既清楚又不抖动。
@media (min-width: 280px)
base: grid-template-columns: 1fr
2 列 · 导航横排。断点来自内容哪里开始挤,而不是设备型号。
断点是布局发生切换的视口宽度临界值:窄于此用一套排版,宽于此换另一套。断点应由内容决定——把窗口慢慢拉宽,哪里开始拥挤、哪里变难看,那里就是断点,而不是照搬 iPhone、iPad 的型号宽度。移动优先用 min-width 从小到大叠加,断点越少越容易维护。
主色 Primary
辅助 Secondary
点缀 Accent
中性 Neutral
从一个基色出发生成有规律的色阶(50~900),再分配主色、辅助色、点缀色与中性色角色。色阶靠明度递进而非随手取色,保证 hover、disabled、边框都有对应深度可选;角色先于色值被命名,主题才换得动。
正文 16px 需要 4.5:1。
大号文字 3:1
WCAG 2.1 门槛。APCA 进一步按字重与字号细化。
前景与背景的亮度比值,衡量文字是否看得清。WCAG 2.1 给出硬性门槛:正文 AA 4.5:1、AAA 7:1,大号文字降到 3:1 与 4.5:1。APCA 按字重与字号给出更贴近感知的建议值。先算比值再选色,不要靠肉眼验收。
悬浮 · elev-2
可点卡片、工具条
umbra · 0 1px 2px rgba(0,0,0,.30)
penumbra · 0 2px 6px 2px rgba(0,0,0,.12)
ambient · spread +4px, blur ×2
box-shadow: 0 1px 2px rgba(0,0,0,.30), 0 2px 6px 2px rgba(0,0,0,.12)
深色界面阴影几乎不可见——改用描边或表面提亮。
用阴影的深浅表达元素离纸面的远近:0 贴平、1~2 浮起、3 以上成浮层。一套阴影由本影、半影、环境三层叠加而成,档位越高投影越大越淡。层级只用来表达叠放关系,不要拿它当装饰。
font-family: system-ui, -apple-system, 'Segoe UI', 'PingFang SC', sans-serif
零下载、零闪烁,随系统变化
按优先级排列的字体回退链:首选字体缺席时依次落到下一个,最后由通用族兜底。系统栈零下载、即时渲染,网络字体保品牌气质但要配 font-display 控制闪烁,本地优先则两者之间取平衡。栈的顺序就是渲染的决策顺序。
grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 12px
把容器缩到 380px 以内:cq 卡片从 3 列塌成 1 列——看容器,不看视口。
用列、槽间距与外边距把页面切成可复用的骨架。12 列最通用,因为它能被 2、3、4、6 整除,任意区块都能对齐到列线。 固定栅格稳但脆,repeat(auto-fit, minmax(240px, 1fr)) 让列数随可用宽度自动增减;容器查询进一步让组件按自身容器而非视口回流。
行高是文字的垂直节奏。标题收紧显得挺拔,正文放宽才耐读。用无单位倍数而不是写死像素,行高才会跟着字号一起缩放。拖动滑块,看段落的松紧如何改变阅读感受。行与行之间的空气,就是读者的呼吸。
无单位行高按比例继承,子元素按自身字号换算。
一行文字占的垂直空间,决定段落的松紧与呼吸。标题收紧(1.1~1.3)显得挺拔,正文放宽(1.5~1.8)利于逐行阅读,引文可以更松。优先用无单位倍数,让行高随字号缩放,而不是写死像素值。
中文舒适区约 28~40 字/行(≈56ch~80ch)。
一段文字每行容纳的字符数,决定眼睛回行是否省力。舒适区大约 45~75 个拉丁字符(中文 28~40 字),最常用 65ch 左右。行太窄回行太频繁,太宽则跟丢行;用 max-width 以 ch 为单位控制,比按像素猜更可靠。
cubic-bezier(0.2, 0, 0, 1) · 240ms
反馈要短,入场可长。开启减弱动效后,位移降级为淡入。
动效时长是动画从开始到结束的时间,按交互类型分档:微反馈 100–150ms、标准过渡 200–300ms、强调入场 300–500ms。缓动决定加速减速的节奏,入场用 ease-out、退场用 ease-in。始终尊重 prefers-reduced-motion,把位移降级为淡入。
放大的一个 CSS 像素,里面每一格是一个设备像素。
1 CSS px = 2 × 2 = 4 device px
一个 24px 图标占 48 device px
1x 图片显示在 2x 屏幕上
1 image px per CSS px
在这块屏上发虚
文字由字形轮廓按设备像素重新渲染,而不是像位图那样被拉伸,所以在任何 DPR 下都清晰(与用 px 还是 rem 无关)。
屏幕同时用两套像素计数:真实的设备像素与布局用的 CSS 像素,一个 CSS 像素里塞进几个设备像素就是设备像素比 DPR。手机像素密、CSS 像素少,位图被撑到 CSS 尺寸就发虚。位图按 2x/3x 提供并配 srcset 与矢量即可锐利;文字清晰度取决于字形渲染,与单位无关,rem 只用于相对根字号缩放。
拖动它,模拟用户把浏览器默认字号调大。
预览根字号 · 16px
px 纹丝不动,相对单位的卡片会随根字号放大,嵌套的 em 还会层层相乘。
1rem = 16px
width: 55vw
视口宽度——整屏区块
width: 70%
相对父容器的百分比
长度可以写死成 px,也可以相对别的量:rem 相对根元素字号,em 相对元素自身或父级的字号,% 相对容器,vw/vh 相对视口。用户把浏览器默认字号调大时,用 px 排的版面纹丝不动,用 rem 的会整体放大。字号、间距、圆角尽量用 rem,只有边框与发丝线才写死 px。
Surface 卡片
muted 辅助文字
--color-bg
#fafaf7
--color-surface
#ffffff
--color-raised
#f3f1ea
--color-text
#17150f
--color-muted
#8a857a
--color-line
#e5e2da
--color-accent
#b4441f
--color-danger
#b42318
同一套角色,四张取值表——组件从不接触具体色值。
按用途而非色相命名的颜色变量:bg、surface、text、muted、accent、danger。组件只认角色,主题切换时在映射层换指向即可,不必改组件。浅色、深色、高对比、品牌皮肤都是同一套角色的不同取值表。
间距档位
分组 A
组内元素共用同一档
↑ 16px 分组之间
分组 B
组内间距始终小于组间距,结构由留白自己说清楚。
用一组固定的间距档位(如 4、8、12、16、24、32、48px,通常按 4 或 8 的倍数生长)统一控制 padding、margin 与 gap。所有留白都从同一把尺子里取,而不是随手写数值,疏密节奏才稳定;间距同时承担分组,间距越大,元素之间的关系越疏远。
按下目标,看看命中反馈。
24px 图标本身不变,只有透明热区在变大。
触控目标是手指能点中的可交互范围,不等于图标看起来多大。苹果 HIG 建议至少 44×44 CSS 像素,Material 建议 48dp;相邻目标之间还要留约 8px 间距,避免误触。视觉小图标可以用透明内边距或伪元素把热区撑大,而不用改变外观。
每一档 = 基准 × 比例ⁿ。改基准字号,整条阶梯同步移动。
用一组按比例递增的字号定义标题与正文层级,让排版有稳定节奏。以正文基准字号乘以固定比例(如 1.25 大三度、1.333 纯四度)逐级放大,标题之间形成可预期的视觉落差,不必逐档拍脑袋定 px;也可用 sm/md/lg 尺码或 clamp() 流式档位落地。
A 是层叠上下文:z=9999 被锁在里面,C 照样在上。
用 z-index 决定已定位元素在纸面上的前后顺序,但真正说话的是层叠上下文:一旦祖先把 transform、opacity 或 isolation 变成上下文, 子元素的 9999 就只在这个盒子里有效,永远压不过外面的 z-index: 1。与其到处写魔法数字,不如定一套从小到大的命名档位。
当前分类和列表中没有匹配项,可以扩大搜索范围。