ant-design Switch 组件 size 尺寸指南:读懂小号开关演示、尺寸 API 与 Design Token 实现原理
本文以 ant-design 仓库中 Switch 组件的“两种大小(Two sizes)”官方演示(size.md 与 size.tsx)为切入点,逐层讲解 size="small" 的用法、size 属性的取值约定、尺寸如何从 Props 传导为 CSS 类,以及小号开关的几何尺寸如何由 Design Token 推导而来。读完本文,你将掌握 Switch 组件尺寸体系的完整使用与定制方法,并能独立用 ConfigProvider.componentSize 实现整页级尺寸统一。
一段演示背后的主题
在 Switch 组件的官方文档页面(components/switch/index.zh-CN.md)中,代码演示区将 ./demo/size.tsx 登记为标题为“两种大小”的示例,其配套说明文档 size.md 全文只有一句话,却是理解该演示的核心:
zh-CN:
size="small"表示小号开关。en-US:
size="small"represents a small sized switch.
这句话揭示的事实是:Switch 组件内置两档外观尺寸——默认的 medium(中号)与 small(小号),而“两种大小”演示的用途正是把这两种规格放在一起,让使用者在同一视图中直观对比它们的视觉差异。
演示源码逐行解读
演示的实际渲染代码位于 size.tsx,完整代码如下:
import React from 'react';
import { Switch } from 'antd';
const App: React.FC = () => (
<>
<Switch defaultChecked />
<br />
<Switch size="small" defaultChecked />
</>
);
export default App;
逐行要点:
- 第一个
<Switch defaultChecked />未传size,走组件默认值medium,即标准尺寸开关; <br />负责让两个开关上下排布(该页面演示区按两列布局渲染,demo.cols = 2);- 第二个
<Switch size="small" defaultChecked />显式指定size="small",渲染为小号开关; - 两者都设置了
defaultChecked,保证初次进入页面即为“开”状态,便于对比两种尺寸下“开”态的视觉纵深与手柄(handle)位置。
size 属性:取值、默认值与兼容约定
官方 API 文档(index.zh-CN.md API 一节)对 size 的定义如下:
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| size | 开关大小,可选值:medium small |
'medium' | 'small' |
medium |
在实际源码中,尺寸类型的定义更为精细,见 components/switch/index.tsx:
export type SwitchSize = Exclude<SizeType, 'large'> | 'default';
这里引用了全局的 SizeType(定义于 components/config-provider/SizeContext.tsx):
export type SizeType = 'small' | 'medium' | 'middle' | 'large' | undefined;
由此可以梳理出两条需要特别注意的兼容约定:
default已被弃用:历史版本中 Switch 的“标准尺寸”写作size="default",现已更名为medium。源码注释明确说明“defaultis deprecated and will be removed in v7, please usemediuminstead.”,并且在开发环境下会通过devUseWarning输出size="default"应改为size="medium"的弃用告警(index.tsx)。由于 Switch 不支持large,SwitchSize通过Exclude<SizeType, 'large'>将其剔除。size只取两个有效值:medium(默认)与small。如果传入的是小写字符串,useSize逻辑会原样采用;因此真正意义上的“小号开关”写法就是演示中的size="small"。
尺寸如何生效:从 Props 到 CSS 类的调用链
size="small" 并不是由 @rc-component/switch 直接消费的,antd 内部做了一层合并与映射。梳理 components/switch/index.tsx 的实现,整条链路是:
useSize(customizeSize)读取 ConfigProvider 注入的SizeContext,把“组件显式传入的 size”与“全局上下文 size”合并(实现见 components/config-provider/hooks/useSize.ts):组件没传size时沿用全局 context,传了字符串则以组件为准;- 合并结果写入
mergedProps.size; - 在拼装 className 时,若
mergedSize === 'small'则追加${prefixCls}-small(即ant-switch-small)类名:
const classes = clsx(
contextClassName,
{
[`${prefixCls}-small`]: mergedSize === 'small',
[`${prefixCls}-loading`]: loading,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
...
);
- 带上述类名的开关本体渲染为
@rc-component/switch的<RcSwitch>,外层再包裹<Wave>以提供点击波纹动效。
也就是说,所有尺寸相关的视觉差异完全由 CSS 层基于 ant-switch-small 类实现,这与快照测试中观测到的结果一致:例如 index.test.tsx 里渲染 size="small" 的开关后,其 DOM 类名即为 ant-switch ant-switch-small ... ant-switch-checked(可对照 snapshots/demo.test.ts.snap 中的小号开关快照)。
小号开关的几何模型:Design Token 驱动的尺寸推导
ant-design 6 代起全面使用 CSS-in-JS + Design Token 生成样式。Switch 组件所有尺寸相关的 Token 都登记在 components/switch/style/index.ts 的 ComponentToken 接口中,其中与小号尺寸直接相关的有:
| Token | 语义 |
|---|---|
trackHeightSM |
小号开关轨道高度 |
trackMinWidthSM |
小号开关最小宽度 |
handleSizeSM |
小号开关手柄(圆形把手)直径 |
innerMinMarginSM / innerMaxMarginSM |
小号开关内部文字/内容区的边距 |
trackPadding |
轨道内边距(大小号共用,固定值 2) |
这些 Token 的默认值不是写死的数字,而是从全局基础 Token 推导而来,推导逻辑位于同文件的 prepareComponentToken:
const height = fontSize * lineHeight; // 中号轨道高度
const heightSM = controlHeight / 2; // 小号轨道高度 = 控件高度的一半
const padding = 2; // 固定内边距
const handleSize = height - padding * 2;
const handleSizeSM = heightSM - padding * 2;
trackHeightSM: heightSM,
trackMinWidthSM: handleSizeSM * 2 + padding * 2,
handleSizeSM,
innerMinMarginSM: handleSizeSM / 2,
innerMaxMarginSM: handleSizeSM + padding + padding * 2,
如果采用默认主题(seed token 中 controlHeight: 32,见 components/theme/themes/seed.ts),代入公式可得到一组直观的参考数值:
- 小号轨道高度
trackHeightSM = 32 / 2 = 16px; - 小号手柄直径
handleSizeSM = 16 - 4 = 12px; - 小号最小宽度
trackMinWidthSM = 12 × 2 + 2 × 2 = 28px。
可见小号开关在设计上遵循“控件高度减半”的思路,视觉上比中号更紧凑,适合表格行内、设置面板、紧凑工具栏等空间受限场景。需要强调的是,这些数值都会随你通过 ConfigProvider 或 theme.token 修改的全局 Token(如 controlHeight、fontSize、lineHeight)同步变化,因此请勿把它当作一成不变的像素值。
对应的小号样式规则集中在 genSwitchSmallStyle(style/index.ts),它在 ant-switch-small 作用域内覆盖最小宽度、高度、行高、内容区左右 padding 切换动画、手柄尺寸、加载图标垂直居中偏移以及按下态位移,使小号开关在“开/关切换”“内容平移”“按下反馈”等交互上与中号保持同一套动画模型。
全局统一:用 ConfigProvider 让整页开关变小
在实际产品中,更常见的诉求是“整页/整块区域的开关统一缩小”,而不是逐个写 size="small"。ant-design 为此提供了全局尺寸能力:ConfigProvider 的 componentSize 属性支持 SizeType('small' | 'medium' | 'middle' | 'large'),配置后会通过 SizeContextProvider 把尺寸注入子组件树(见 components/config-provider/index.tsx)。
import { ConfigProvider, Switch } from 'antd';
const App: React.FC = () => (
<ConfigProvider componentSize="small">
{/* 无需再写 size="small",内部所有支持尺寸的组件都会变小 */}
<Switch defaultChecked />
<Switch defaultChecked />
</ConfigProvider>
);
export default App;
这正是前文 useSize 合并逻辑的意义所在:当 Switch 自身未传 size 时,会从 SizeContext 继承到 small,最终同样命中 ant-switch-small。而显式传 size="small" 的优先级高于全局配置,适合“整体小号、个别中号”的混排需求。
组合使用的注意事项
掌握 size 之后,把它与其它属性组合使用时还需注意几点,均可对照官方文档与源码验证:
- 文字/图标内容:
checkedChildren/unCheckedChildren在小号开关中同样支持,但内容区域基于innerMinMarginSM/innerMaxMarginSM计算边距,fontSizeSM级别的小字号内容观感最佳(样式定义见 style/index.ts 中ant-switch-small对ant-switch-inner的处理)。快照测试中也有unCheckedChildren="0"配合size="small"的用例可参考; - 加载中:
loading状态下展示的LoadingOutlined图标在小号开关中会按handleSizeSM与加载图标尺寸差计算top偏移,以保持手柄内居中,不必手动微调; - 与 Form 的配合:Switch 的值绑定属性是
checked而非value,如需在 Form.Item 下绑定数据,应使用valuePropName="checked"(FAQ 部分有官方示例),这与尺寸无关但容易在组合使用时踩坑; - 语义化样式:从 6.0.0 起,
classNames/styles支持root、content、indicator三个语义结构(见 components/switch/demo/_semantic.tsx),如需对“小号开关单独定制”,可结合函数式classNames={({ props }) => ...}判断props.size === 'small'来差异化返回类名,相关用法在 semantic.test.tsx 中有完整的断言示例。
小结
回到那则只有一句话的演示文档:size="small" 代表小号开关。在 ant-design 中,这短短一行背后是完整的尺寸体系——medium/small 两档取值与 default 的弃用约定、useSize 合并组件与全局两层尺寸、ant-switch-small 类名的挂载、以及由 controlHeight 等 Token 公式化推导出的 16px 轨道 / 12px 手柄几何模型。理解这条从“演示 → Props → 类名 → Token → CSS”的链路后,无论是要写一个局部小开关,还是要通过 ConfigProvider 统一收紧整个表单的密度,都能在源码层面做到心中有数。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00