D01 组件样式按钮与卡片

2026-10-31 17:010 阅读约 12 分钟CSS

D01 组件样式按钮与卡片

摘要:按钮与卡片是复用率最高的两个组件。按钮的难点在状态完整——默认、悬停、按下、禁用、加载五种状态都要可辨且可键盘触发;卡片的难点在内容自适应——标题长短、有无图片、有无摘要都不能破坏排版。本文给出两组完整样式与六项验收。
关键词:组件样式,状态,禁用,卡片,自适应

所属:frontend/css / D-实战 | 上一篇:D00-总结 | 下一篇:D02-响应式文章列表

1 引言

组件的维护成本取决于状态数量与容错程度。状态漏一个,用户就少一条操作线索;宽度写死一处,组件就少一个使用场景。

本文给出两组组件的完整写法。范围见表 1-1。

项 本文覆盖 本文不覆盖
按钮 五种状态、三种变体、尺寸档 图标按钮与按钮组
卡片 有图/无图、横排/竖排、摘要截断 拖拽与交互
令牌 颜色、圆角、间距变量 完整设计系统

2 预备知识

项 要求 核对方式
环境 本地服务器可用 浏览器能打开 localhost
文件 css-practice/components.html 编码 UTF-8
前置 B04、B05 伪类与过渡
前置 B06 变量体系已建立

3 原理与实现

3.1 状态与变体的正交关系

状态由交互决定,变体由用途决定,两者相乘但样式规则不重叠,如图 3-1 所示。

flowchart LR
    A["基础按钮 .btn"] --> B["状态<br/>hover / active / disabled / loading"]
    A --> C["变体<br/>primary / ghost / danger"]
    B --> D["组合后各自生效"]
    C --> D

图 3-1 按钮的状态与变体

图上可见:变体只改颜色与边框,状态只改位移、透明度与光标;两者分开写才不会互相覆盖。

3.2 完整样式

/* 运行环境:Chrome 130+;css-practice/components.css */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.5rem 1rem;
  border: 1px solid transparent;
  border-radius: var(--radius, 0.5rem);
  font: inherit;
  line-height: 1.2;
  cursor: pointer;
  transition: transform 120ms ease, background-color 120ms ease, opacity 120ms ease;
}

.btn--primary { background: var(--brand, #1d4ed8); color: #fff; }
.btn--ghost { background: transparent; border-color: currentColor; color: var(--brand, #1d4ed8); }

.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn:disabled,
.btn[aria-busy="true"] { opacity: 0.55; cursor: not-allowed; transform: none; }

.card {
  display: grid;
  gap: 0.75rem;
  padding: 1.25rem;
  background: var(--surface-alt, #f8fafc);
  border-radius: var(--radius, 0.75rem);
}

.card__title { font-size: 1.125rem; margin: 0; }
.card__body { color: var(--text-muted, #475569); margin: 0; }
.card__meta { font-size: 0.8125rem; color: var(--text-muted, #475569); }

.card--media {
  grid-template-rows: auto 1fr;
  overflow: hidden;
  padding: 0;
}

.card__media { aspect-ratio: 16 / 9; background: #e2e8f0; }
.card__inner { padding: 1rem 1.25rem 1.25rem; display: grid; gap: 0.5rem; }

/* 内容自适应:摘要最多两行 */
.card__body {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

按钮状态与判定标准见表 3-1。

状态 触发 视觉变化 验收标准
默认 — 基础色 可聚焦
悬停 指针移入 上移 1 像素 触摸设备不依赖此状态
按下 指针按下 回位 有即时反馈
禁用 disabled 透明度降低、光标禁止 不可点击、不可聚焦
加载 aria-busy="true" 半透明、无位移 保留尺寸,不跳动

卡片结构要点见表 3-2。

要素 写法 目的
布局 display: grid + gap 内部间距统一
图片区 aspect-ratio 高度随宽度确定
摘要 -webkit-line-clamp 限制行数,避免高度失控
内边距 带图卡片用内层容器 图片贴边、文字留白
宽度 不写固定宽度 由父容器决定

实施清单(按顺序执行):

步骤 动作 产出
1 定义颜色、圆角、间距变量 令牌就绪
2 写 .btn 基础样式 单按钮可见
3 补 primary 与 ghost 两个变体 两种用途可区分
4 补五种状态 键盘与禁用可用
5 写 .card 基础与带图变体 两种卡片可用
6 补摘要行数限制 长文本不撑高
7 按 4 节清单验收 六项通过

4 验证与讨论

  1. 用 Tab 聚焦按钮,确认轮廓可见;用 Enter 触发,确认按下态有反馈。
  2. 给按钮加 disabled,确认不可点击且光标为禁止。
  3. 给按钮加 aria-busy="true",确认尺寸不变、无位移。
  4. 把卡片放进 240 像素与 640 像素宽的容器,确认排版正常且摘要最多两行。
序号 验收项 判定标准 依据
1 状态完整 五种状态均可复现 表 3-1
2 键盘可用 无鼠标也能触发 表 3-1
3 变体独立 变体与状态组合无冲突 图 3-1
4 卡片自适应 两种宽度下均无溢出 表 3-2
5 摘要截断 超长文本最多两行 表 3-2
6 令牌复用 颜色只来自变量 3.2 节

五项取舍见表 4-1。

决策点 采用方案 备选方案 不选的理由
变体命名 --primary 修饰符 独立类名 修饰符能表达同族关系
加载态 aria-busy 属性选择器 .is-loading 类名 属性同时可用于无障碍提示
卡片布局 Grid 单列 Flex 纵排 Grid 的 gap 与行控制更直接
摘要截断 行数限制 字符数截断 行数不受字体影响
宽度 完全自适应 三档固定宽度 容器查询与网格已能覆盖

讨论与局限。 行数截断在部分旧浏览器需前缀,且被截断的内容对朗读软件仍完整,属于视觉处理。另按钮的加载态若需要转圈动画,应放进伪元素并响应减少动效偏好。

5 常见问题

现象 原因 处理
按钮文字尺寸与页面不一致 未继承字体 font: inherit
禁用按钮仍可点击 只加了透明度,未加 disabled 使用禁用属性
卡片高度随摘要变化 未限制行数 行数限制
带图卡片图片不贴边 外层有内边距 图片放内层之外,或分层容器
变体颜色被状态覆盖 状态选择器权重更高 状态只改位移与透明度

6 结论

序号 结论 依据
1 状态与变体正交,规则不重叠 图 3-1
2 禁用必须用属性,不能只改颜色 表 3-1
3 卡片宽度由容器决定 表 3-2
4 摘要截断按行数,不按字符数 表 4-1

参考文献

[1] MDN Web Docs · line-clamp,https://developer.mozilla.org/en-US/docs/Web/CSS/line-clamp(访问于 2026-10-31)
[2] W3C · ARIA 按钮模式,https://www.w3.org/WAI/ARIA/apg/patterns/button/(访问于 2026-10-31)

返回文章列表

评论 0

0/2000

还没有评论,快来抢沙发吧~