> ## 文章索引
> 在这里获取全部文章的索引：https://lrd.im/blog/llms.txt
> 这是 lrd.im 的个人博客，记录设计、技术与思考。

# 一个特殊字符，打开 Sketch 组件新世界的大门

![封面图](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/01.png)

公司内 B 端项目的表单比较多，经常有各种编辑页、功能配置页等。所以最近在做到一个编辑页调整的需求时，也和前端老哥沟通了一波，把公司项目里常用到的表单做成了组件。后续我打算做成 Sketch Symbol，同步到 B 端到组件库内。这时出现了一些耐人寻味的问题。

![课程编辑页界面截图，由两列表单组件构成，包含课程封面上传、课程介绍编辑、课程名称、开始/结束时间、分享文案配图等字段，右列还展示了防文字复制等功能配置开关。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/02.png)

## 一、耐人寻味的问题

拿其中一个最基础的表单来做例子。标题旁边，可能会出现「示例」入口；而表单的右侧扩展区域，根据业务需要会出现四种情况，一是占位符文本，二是已填写的内容，三是两种文本同时出现，四是没有文本。

![表单组件的四种右侧扩展区状态示意：1. 纯占位符文本（灰色 "请输入"）；2. 已填写内容（红色 "示例" 标签+实际值）；3. 占位符与已填写并存（"请输入 元"）；4. 无文本仅保留箭头图标。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/03.png)

把所有情况抽象出来，实际上我们要用 Sketch 组件来控制不同字段是否展示。而且字段不同，其文本颜色也不同。

![示意图展示 Sketch 组件需解决的三个控制问题：文章标题旁 "示例" 入口的显隐、占位符文本的显隐与颜色、右侧扩展区箭头图标的显隐，三者相互独立。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/04.png)

17年我在 [Pablo Stanley](https://www.youtube.com/channel/UCZHkx_OyRXHb1D3XTqOidRw "Pablo Stanley 的 YouTube 频道") 的油管频道里学习 Sketch 时，处理上述情况的方式是再多做一个组件。因为那时 Sketch 不支持在组件外给文本设置颜色。

所以以往常规的做法是：

1. 做多个表单组件，需要展示哪种情况就直接切换；
2. 做一个表单组件，多个文本组件，利用 Sketch 组件的 Overrides 功能来控制不同文本类型是否出现，以及各文本字段的值。

![两种处理表单组件状态的常规做法对比：方式一通过切换多个大组件（仅占位符、仅已填写、占位符+已填写、无文本）实现；方式二在单个组件内嵌套文字子组件，通过 Overrides 面板控制文本类型切换。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/05.png)

以往我也一直用这两种方法来做，深知他们的利弊。

这两种方法均能达到目的，但是会创建多个组件，造成组件库冗余。且文案需要来回修改时要在组件下拉框内切换选择，操作繁琐。其他同事上手时学习成本较高。

> 2021年了，用 Sketch 组件来控制文本显示 & 文本颜色有没有另一种方式？

答案是有的，最后我还会放上源文件，有兴趣的伙伴可以下载来试试实际效果，是否会比以往的组件方便。

## 二、独特的做组件方式

### 1. 基础实现

最开始我也是想用上面描述的第二种方法来实现。但就会有多个冗余组件。工具线的设计是我负责的，不太乐意见到这种情况的发生。如果组件需要后续迭代，冗余组件只会越来越多。

所以我这次想试试不走寻常路。不在内部额外嵌套组件，仅靠一个表单组件来控制不同文本类型是否出现，以及修改文本字段的值。做到如下图一般的效果：

![示意图：一个表单根组件可派生出四种样式变体——带占位符文本的课程名称、带已填写文本的课程名称、仅含箭头的课程排序、带建议价格说明的课程价格，实现一个组件控制多种显示状态。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/06.png)

首先，组件内的文字图层，是不能直接修改颜色的。所以基于业务，这次的表单组件内需要有三个不同颜色的文本图层，以确保在组件外可自由改写各字段的值。

1. 示例 #F73657 （产品的品牌色）
2. 占位符文本 #999
3. 已填写文本 #333

而因为占位符文本会被已填写的内容替换，所以组件内可以将两个字段重叠，确保位置一致。

![Sketch 表单组件示例：左侧图层面板显示「扩展区域/已填写」和「扩展区域/占位符」两个文本图层重叠放置，右侧预览显示标题行中品牌红色「示例」文字与「已填写文本」字段并排呈现。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/07.png)

另一个问题是需要控制字段是否显示。如果用旧方法，只要将文本做成组件，在右侧 Overrides 面板控制是否展示即可。但我们不做新组件，只能靠文本图层唯一一个可以 Override 的内容：字段的值来做文章了。

> 字段的值是什么，才能让我们看不见文本？

**字段的值是空格的时候，我们就看不见文本了。** 所以，在 Overrides 面板中，给占位符字段输入一个空格，给已填写的字段输入对应内容，我们已经能够做到「控制字段是否显示」了。

![Sketch 组件制作示意图：展示三种列表行状态——隐藏所有文字、仅显示标题和示例、显示标题和占位符；右侧 Overrides 面板中，将不需要展示的字段值设为空格即可隐藏该字段。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/08.png)

### 2. 更进一步

上述步骤已经可以达到我们的目的，但每次拖一个组件出来都要给不需要展示的内容输入一个空格，操作仍然繁琐。

我突发奇想，要不干脆直接将源组件内的字段内容，填入一个空格。组件就会默认不展示任何文本（因为是一个空格，我们看不见），只有在右侧 Overrides 一栏内给某个类型填入相应的文案，才会显示出来。

然而事情并没有这么简单。Sketch 里我们如果给文本图层只输入一个空格键，回车之后图层会被自动删除。估计 Sketch 是为了减少冗余图层的出现，认为纯空格的图层没有作用，直接将图层清理了。

![Sketch 表单组件截图：左侧图层面板显示「标题组」和「扩展区域」等图层结构，右侧预览区展示组件效果——「标题」为黑色文字，「示例」为红色文字，说明组件的文本图层内容可见。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/09.gif)

然而我也没那么容易放弃，就是要跟 Sketch 硬刚到底。

因为前段时间了解了一些前端、网页开发相关的知识，了解到网页内有多种空格，而且这几种空格所占的宽度，对应的 Unicode 都不一样。说不定能在这次的研究中派上用场。列举一部分：

`&nbsp;` 不换行空格，全称 No-Break Space。是按下 space 键产生的空格，最常见。

`&emsp;` 全角空格，全称是 Em Space。其占据的宽度正好是 1 个中文宽度。

`&zwnj;` 零宽不连字，全称是 Zero Width Non Joiner。是一个不打印字符，放在电子文本的两个字符之间，抑制本来会发生的连字。

`&zwj;` 零宽连字，全称是 Zero Width Joiner。是一个控制字符，放在某些需要复杂排版语言（如印地语）的两个字符之间，使得这两个本不会发生连字的字符产生连字效果。

参考资料：[HTML的多种空格！—简书](https://www.jianshu.com/p/af9c7ed2eb24)、[零宽连字 - 维基百科，自由的百科全书](https://en.wikipedia.org/wiki/Word_joiner)

所以我在 Sketch 内逐个试，看看其中没有一个空格能在 Sketch 文本图层内单独存活下来。

捣鼓一轮之后，真被我找到了。在普通的空格前面或后面，加一个 Joiner，外观没有变化，但他已经不是普通的空格了，不会被 Sketch 当成无用图层清理。比如上表中的「零宽连字」，就不会被清理掉。

因为做连字空格的步骤略繁琐，所以我直接在文章内打了一个，方便大家复制使用。（连字空格的制作方法和实例放在文章结尾处）

接下来将带有连字符的空格「 ‌‍」（在两个引号中间）粘贴到咱们表单根组件内，作为文本图层的默认文本。然‍‍后修改图层名称为对应的类型，方便在组件外找到。

![Sketch 表单组件的图层结构与预览效果截图：左侧图层面板显示「表单组件」包含标题组、扩展区域（含扩展信息、箭头、Divider、Bg）等图层；右侧预览仅显示「标题」文本，其余扩展区域因连字空格隐藏而不可见。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/10.gif)

把连字空格粘贴在其他文本图层之后，已经 100% 达到我想要的效果了。用取巧的方式，仅靠一个组件，实现控制不同文本类型是否出现，以及修改文本字段的值。组件无嵌套关系，拖入即用，有手就行。

![Sketch 表单根组件的三种状态展示及其 Overrides 面板：仅标题、标题加示例占位符、标题加已填写文本，右侧面板说明各字段默认为空时自动隐藏，填写后才显示。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/11.png)

PS：因为表单总是会有一个标题，所以在根组件内，标题字段就没有用空白来做。

### 3. 其他实例

至此，组件已满足业务设计需要。因为无嵌套关系，所以扩展性也极强。

遇到特殊的情况：占位符文本和已填写文本同时出现的情况，也可以通过两组占位符/已填写类型来轻松做到。只要确保图层命名足够清晰，就能在外部组件右侧 Overrides 面板内一眼看懂。

![Sketch 组件 Overrides 面板示例：课程价格表单行包含标题、占位符「建议 0~50」和单位「元」三组独立文本图层，演示占位符与已填写文本同时出现时用两组文本图层分别控制的实现方案。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/12.png)

上面用连字空格来做 Sketch 组件的几个示例，我也做成了 Demo 。源文件已传到网盘上面，感兴趣的小伙伴可以下载来体验一下。看看这种新思路能否对工作上各方面有帮助。如有其他想法或建议，也欢迎到评论区交流。

源文件已上传到 Google Drive，[点击此处下载](https://drive.google.com/file/d/1hlP7Hu6CfjvB6f6Aj1u7HY8nTdfPb37e/view?usp=sharing "在 Google Drive 中下载")

## 三、优势与局限

取巧地通过连字空格来控制文本图层是否展示，优势很明显。

1. 无嵌套。拖入即用，使用者的学习成本低；
2. 操作简便。字段默认隐藏，只要在 Overrides 面板填入对应内容即可恢复显示。也无需像组件一样点开下拉菜单一个个找；
3. 无冗余组件。组件库清爽干净，适合有设计洁癖的人。

当然也有其局限性的，这种的做法不适宜文字颜色过多的情况。

![Sketch Overrides 面板截图：组件列出了 6 种颜色变体的提示文案字段（正常-黑、链接-蓝、失效-灰、成功-绿、警告-橙、报错-红），加上标题字段共 7 行，说明颜色越多面板越臃肿](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/13.png)

因为我们只是通过连字空格来将选择颜色的步骤前置展示，没有收在下拉框内。所以每多一种颜色，根组件内就多一个文本图层，外部组件的 Overrides 面板就多一行。

这次我的组件是基于业务，所以颜色数量有限。但如果是做像 AntD 那种最通用系统级组件库，需要允许更改任何颜色，我这种方法确实是行不通的。但可以参考我另一篇文章：[在 Sketch 组件外更改文字颜色最简单的方法](http://lrd.im/blog/2021-05-30)

## 四、Figma 的表现？

Figma 是支持在组件外调整文本颜色的。所以实现同样的效果，在 Figma里简直不要太简单…

![Figma 操作示意图：在组件外选中 "右侧文本" 图层（步骤 1），直接在右侧调色板修改颜色（步骤 2，当前色值为 #999999），无需进入根组件，操作比 Sketch 更简便直接。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/14.png)

直接在组件外选中需要调整的字体，右侧调色板即可自由调色。同时在根组件内也能填入普通的空格而不被清理。或者也可以用可变组件来做，各方面都领先 Sketch 不少。

## 五、macOS 制作连字空格

连字空格不会被 Sketch 当成普通空格那样被自动清理，因为它的构成是「空格 + 连字符」。下面公开制作方法。

1. 在 Sketch 文本图层内，输入一个空格
2. 按 Control + Cmd + Space 呼出字符检视器，在右上角的搜索栏内输入「joiner」，搜索连字符
3. 双击「Unicode 名称」下前四个的其中一个，将他输入到空格后面
4. Cmd + 回车，完成编辑

![macOS 字符检视器截图，搜索「joiner」后显示 Zero Width Non-Joiner 字符，Unicode 为 U+200C，UTF-8 为 E2 80 8C。背景为 Sketch 画布，展示含连字空格的「示例」文字组件。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/15.gif)

字符检视器内有多种连字符，将 Combining Grapheme Joiner / Zero Width Non-Joiner / Zero Width Joiner / Word Joiner 的其中一个放在空格前后，都能起到作用。

下面看看普通空格和连字空格的 Unicode 编码差异，能更清楚其中的原理。

![ChinaZ Unicode 编码转换工具截图，展示普通空格编码为 \&#32;，连字空格编码为 \&#32;\&#8205;（空格+零宽连字符），直观说明两者的 Unicode 构成差异](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/16.png)

实际上就是因为 Sketch 会自动清理 Unicode 编码为`&#32;`的空格，而零宽连字（Joiner 的一种）的 Unicode 编码为`&#8205;`，所以他跟我们平常汉字，标点符号类似，在 Sketch 看来都是正常文本。

之所以我们需要「空格 + Joiner」或者「Joiner + 空格」，是因为单独的「Joiner」在 Sketch 里宽高均为 0.1px，编辑组件时不好选择，所以才加一个空格符号在前面或者后面，方便编辑，也不影响最终效果。

## 六、总结

上面写了这次通过用连字空格，取巧地做 Sketch 组件的完整思考、实践过程。在最后浓缩一遍，尝试用最精炼的语言描述清楚：

我们可以用「连字空格」这个外观看上去是空格的符号，作为根组件内的文本，可以确保在组件的 Overrides 面板也能复写该字段。默认为空白，即不展示。需要展示文本时填上具体内容即可，起到显示 / 隐藏字段的效果。

用连字空格来做 Sketch 组件的方式，网上没有相似的经验分享，是我独家的设计经验。

## 一些补充

对于标题以及文章内提到的「Joiner」，我在因特网上搜了一大圈都没找到对应的中文翻译。有多种类型的「Joiner」，其原本的作用都是放在词语之间，控制符号前后的文字作出某种变化，到底它的中文译名是什么呢？

零宽连字，全称是 Zero Width Joiner。可以把「Joiner」称为「连字符」吗？但已经有广为人知的「Hyphen」了。

[维基百科](https://zh.wikipedia.org/wiki/%E9%9B%B6%E5%AE%BD%E7%A9%BA%E6%A0%BC)里倒是有一个条目跟「Joiner」有关，把他叫作「词连接符」。在网络上搜索词连接符，也是找不到相应内容的，真是让人头疼~

![中文维基百科 "零宽空格" 条目的参见章节截图，列出软连字符、分字符、词连接符等相关条目，其中 "词连接符" 显示红色（条目尚未创建），悬浮提示建议参考英文维基的 "Word joiner" 页面。](https://lrdim.oss-cn-shenzhen.aliyuncs.com/blogimg/2021-05-03-8264a8e896aa/17.png)

## 扩展阅读

近期也写了一篇博客，能用一种更简单的方法实现 Sketch 组件外改文字颜色的效果：[Sketch 组件外更改文字颜色最简便的方法](/blog/2021-05-30)