Web 设计模式
面向生产级界面的 CSS 实现模式。如需了解设计基础与决策方法,请参阅 ui-design。本技能聚焦代码实现。
另见:
ui-design(排版/色彩/间距理论)、frontend-design(创意美学)
安装
OpenClaw / Moltbot / Clawbot
npx clawhub@latest install web-design
布局原则
二维布局使用 CSS Grid,一维流式布局使用 Flexbox。根据上下文选择合适的工具。
| 布局需求 | 工具 | 原因 |
|---|---|---|
| 页面级结构 | CSS Grid(grid-template-areas) | 命名区域、显式行/列控制 |
| 导航栏 | Flexbox | 单轴对齐,通过 gap 控制间距 |
| 卡片网格 | Grid(auto-fill / auto-fit) | 无需媒体查询即可实现响应式 |
| 居中 | Grid(place-items: center) | 最简短、最可靠的居中方式 |
| 侧边栏 + 内容 | Grid(grid-template-columns: 250px 1fr) | 固定侧边栏的比例尺寸 |
| 堆叠重叠 | Grid + grid-area: 1/1 | 无需 position: absolute 即可层叠元素 |
空间构成
跳出可预测的布局。有意的非对称、重叠元素和打破网格的强调装饰能够创造视觉趣味。使用 Grid 堆叠(grid-area: 1/1)而非 position: absolute 来实现元素重叠。为奢侈/编辑类美学选择宽松的负空间,为数据密集型界面选择受控的密度——选择必须是有意的。
排版
排版承载了设计个性的 90%。选择与界面用途匹配的字体。
| 上下文 | 展示字体方向 | 正文字体方向 | 示例搭配 |
|---|---|---|---|
| 编辑 / 杂志 | 高对比度衬线体 | 中性人文主义无衬线体 | Playfair Display + Source Sans 3 |
| SaaS 仪表盘 | 几何无衬线体 | 匹配粗细的无衬线体 | DM Sans + DM Mono(数据) |
| 创意作品集 | 表现性展示字体 | 清晰易读的无衬线体 | Syne + Outfit |
| 电商奢侈品 | 细体现代衬线体 | 优雅无衬线体 | Cormorant Garamond + Jost |
| 开发者工具 | 等宽展示字体 | 等宽正文字体 | JetBrains Mono + IBM Plex Mono |
字体尺度
使用一致的比率。1.25(大三度)尺度适用于大多数界面:text-xs 0.64rem、text-sm 0.8rem、text-base 1rem、text-lg 1.25rem、text-xl 1.563rem、text-2xl 1.953rem、text-3xl 2.441rem、text-4xl 3.052rem。正文字体设为 1rem(最小 16px),正文行高 1.5,标题行高 1.1–1.2。行宽限制在 60–75ch。
色彩
构建调色板
每个调色板需要五个功能角色:
| 角色 | 目的 | 示例用途 |
|---|---|---|
| 主色 | 品牌标识、主要操作 | 按钮、链接、激活状态 |
| 中性色 | 文本、边框、背景 | 正文、卡片、分隔线 |
| 强调色 | 次要操作、高亮 | 标签、徽章、次要按钮 |
| 成功 / 警告 / 错误 | 语义反馈 | 提示框、表单验证、状态 |
| 表面色 | 分层背景 | 卡片、模态框上的覆盖层 |
对比与深度
通过表面分层而非仅靠阴影来创造深度:
:root {
--surface-0: hsl(220 15% 8%); /* 页面背景 */
--surface-1: hsl(220 15% 12%); /* 卡片 */
--surface-2: hsl(220 15% 16%); /* 凸起元素 */
--surface-3: hsl(220 15% 20%); /* 弹出框 / 模态框 */
}
使用 HSL 或 OKLCH 进行感知均匀的色彩操作。主导色加上鲜明强调色比均匀分布的调色板效果更好。始终验证 WCAG 对比度:普通文本 4.5:1,大文本 3:1。
间距
一致的间距创造节奏感。使用 8px 基础单位(密集 UI 可用 4px):
| 令牌 | 值 | 用途 |
|---|---|---|
--space-1 | 0.25rem (4px) | 内联图标间距、紧凑内边距 |
--space-2 | 0.5rem (8px) | 输入框内边距、紧凑列表 |
--space-3 | 0.75rem (12px) | 按钮内边距、卡片内部间距 |
--space-4 | 1rem (16px) | 默认元素间距 |
--space-6 | 1.5rem (24px) | 区块内边距、卡片间隔 |
--space-8 | 2rem (32px) | 区块分隔 |
--space-12 | 3rem (48px) | 主要区块分隔 |
--space-16 | 4rem (64px) | 页面级垂直节奏 |
一致地应用间距:在 Grid/Flexbox 容器上使用 gap,而不是在子元素上使用外边距。这样可以消除外边距塌陷错误,并简化响应式调整。
视觉层次
通过大小、粗细、色彩和空间的刻意对比来引导视线。
层次技术
| 技术 | 方法 | 影响 |
|---|---|---|
| 大小对比 | 主标题是正文的 3–4 倍 | 立即形成视觉焦点 |
| 粗细对比 | 粗体标题 + 常规正文 | 可扫描性 |
| 色彩对比 | 主色文本 vs 柔和次要文本 | 信息分层 |
| 空间分组 | 组内紧密间距,组间宽距 | 格式塔邻近性 |
| 抬升 | 阴影 / 表面层 | 交互暗示 |
| 空白隔离 | 关键元素周围的空白空间 | 通过缺失实现强调 |
实用模式——卡片层次
在卡片内部构建层次:眉标(xs,大写,柔和)→ 标题(xl,半粗)→ 正文(base,次要颜色,1.6 行高)→ 操作(用 margin-top 隔开)。使用表面色进行分隔,并使用间距令牌保持一致的内边距。
响应式设计
断点策略
| 断点 | 目标 | 方法 |
|---|---|---|
< 640px | 移动端 | 单列、堆叠导航、触摸目标 ≥ 44px |
640–1024px | 平板 | 两列选项、可折叠侧边栏 |
1024–1440px | 桌面 | 完整布局、启用悬停交互 |
> 1440px | 宽屏 | 最大宽度容器(1280px),防止超宽行长 |
流体技术
尽可能优先使用流体尺寸而非固定断点:
/* 流体排版——在 640px 和 1440px 视口之间缩放 */
h1 { font-size: clamp(2rem, 1.5rem + 2.5vw, 3.5rem); }
/* 流体间距 */
section { padding-block: clamp(2rem, 1rem + 4vw, 6rem); }
/* 内在网格——无需媒体查询 */
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); gap: var(--space-6); }
当组件的布局应响应其容器而非视口时,使用容器查询(@container)实现组件级响应。
无障碍
无障碍并非可选。从一开始就构建它。
| 要求 | 实现 | 标准 |
|---|---|---|
| 色彩对比度 | 普通文本 4.5:1,大文本/UI 元素 3:1 | WCAG 2.1 AA |
| 键盘导航 | 所有交互元素可聚焦且可操作 | WCAG 2.1.1 |
| 焦点指示器 | 可见的 :focus-visible 环,2px+ 偏移 | WCAG 2.4.7 |
| 语义化 HTML | 使用 <button>、<nav>、<main>、<article> 等 | WCAG 1.3.1 |
| 替代文本 | 信息性图片用描述性文本,装饰性图片用 alt="" | WCAG 1.1.1 |
| 动效安全 | 尊重 prefers-reduced-motion | WCAG 2.3.3 |
| 触摸目标 | 交互区域最小 44×44px | WCAG 2.5.8 |
| 必要时使用 ARIA | 仅当原生语义不足时使用 aria-label、aria-live、role | WCAG 4.1.2 |
/* 健壮的焦点指示器 */
:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
/* 尊重动效偏好 */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
组件设计
设计良好的组件结构
每个 UI 组件都应具有清晰的状态、一致的间距和可预测的行为:
| 状态 | 视觉处理 | 示例 |
|---|---|---|
| 默认 | 基础样式 | 按钮静止状态 |
| 悬停 | 细微变化——背景、阴影或缩放 | background 变亮 5-10% |
| 激活 / 按下 | 压缩感——阴影减少、轻微内陷 | transform: scale(0.98) |
| 聚焦 | 高可见度环,不移除轮廓 | :focus-visible 环 |
| 禁用 | 降低透明度,cursor: not-allowed | opacity: 0.5 |
| 加载中 | 旋转动画或骨架屏,禁止交互 | 内联旋转动画替换标签 |
设计令牌架构
将令牌分为三层以便维护:
/* 第1层:原始值 */
--blue-500: oklch(0.55 0.2 250);
--gray-100: oklch(0.95 0.005 250);
--radius-md: 0.5rem;
/* 第2层:语义别名 */
--color-primary: var(--blue-500);
--color-surface: var(--gray-100);
--radius-button: var(--radius-md);
/* 第3层:组件专用 */
--btn-bg: var(--color-primary);
--btn-radius: var(--radius-button);
--btn-padding: var(--space-2) var(--space-4);
这种三层方法允许通过重新映射第2层来实现主题切换,而无需触及组件。
交互模式
动效与动画
使用动效来传达状态变化,而非装饰。聚焦于高影响力的时刻:
| 交互 | 持续时间 | 缓动函数 | 目的 |
|---|---|---|---|
| 按钮悬停 | 150ms | ease-out | 确认交互 |
| 模态框打开 | 250ms | ease-out | 吸引注意力 |
| 模态框关闭 | 200ms | ease-in | 快速关闭 |
| 页面过渡 | 300ms | ease-in-out | 保持空间上下文 |
| 交错显示 | 每个项目延迟 50–80ms | ease-out | 顺序内容加载 |
| 微反馈 | 100ms | ease-out | 切换、复选框、开关 |
/* 交错入场动画 */
.stagger-item {
opacity: 0;
translate: 0 1rem;
animation: reveal 0.5s ease-out forwards;
}
.stagger-item:nth-child(1) { animation-delay: 0ms; }
.stagger-item:nth-child(2) { animation-delay: 60ms; }
.stagger-item:nth-child(3) { animation-delay: 120ms; }
@keyframes reveal {
to { opacity: 1; translate: 0 0; }
}
滚动驱动效果
使用原生 animation-timeline: scroll()(放在 @supports 后面)实现视差和显示效果,无需 JavaScript。用特性检测包裹以优雅降级。
设计质量检查清单
在发布前,对照以下标准进行验证:
- 排版:有意的字体搭配、一致的尺度、可读的行宽
- 色彩:协调的调色板、满足 WCAG 对比度、定义了语义反馈颜色
- 间距:使用间距令牌实现一致的节奏,没有临时的像素值
- 层次:清晰的视觉流程——视线路径遵循预期的阅读顺序
- 响应性:在移动端、平板、桌面端测试,无水平溢出
- 无障碍:键盘可导航、焦点可见、屏幕阅读器测试、动效安全
- 状态:所有交互元素都有悬停、激活、聚焦、禁用和加载状态
- 个性:设计有清晰的观点——不像是通用模板的审美
- 性能:图片已优化、字体已子集化、动画使用 GPU 加速(
transform、opacity) - 暗黑模式:如果支持,表面使用分层亮度,而非反转颜色