深浅模式设计

关于模式

这里所说的模式,可以理解我们肉眼看到的界面外观。点击上面的 demo 可以了解深浅两种模式在视觉上的感官区别。

它们有着相同的布局、相同的文字内容、相同的icon,还有其它相同的元素。仅仅除了颜色,它们所有的属性和操作其实都是一样的。

同样,在我们整个系统的设计中,深色模式与浅色模式实际上是一样的,在不改变任何布局、任何功能和内容的前提下,通过改变颜色(当然还会有其它的一些元素和属性)来设计不同的模式。

为什么做深色模式?

  • 对比度

    每个用户、每个商家显示器的显示质量不一样,在显示质量差的显示器上由于对浅灰度区域的颜色显示效果不好,浅灰色的背景肉眼所看到的是偏白色,缺少这部分的颜色的还原显示,界面上信息的可读性很差。

    恰巧这部分的颜色在整个设计中多用在背景、内容区块和分隔线等,用于设计信息之间的层级关系,影响了信息的展示和可阅读性。

    如果单纯把显示有问题的颜色加深加重,在显示质量好的显示器上,所改的颜色反而会显得过深,影响了整体的设计,这是一个很矛盾的问题。

  • A New Look For A New Experience

    在很多专业领域的产品里面,大多默认使用深色界面,因为在深色背景下信息可以处理得更突出,让人在使用的时候更专注,提升使用产品时的感官体验。

  • 在室内或暗光环境下,相对于浅色模式下的屏幕亮光,深色模式能够减少用户的视觉疲劳,也减少屏幕亮光对周围他人影响。

下图是系统设计的部分示例。

ModeCon

深浅模式示例

颜色

color

系统颜色

颜色,是最基础和也是最重要的部分,在设计时按照使用功能把颜色分成三部分:主色辅助色基本色

每种类型的颜色分为10个阶级,(除了基本色设了15级,因为这里深浅模式共用了同一套基本色),用在系统不同元素和交互状态上。

主色

主色: primary ,通常取决于品牌色,一般在UIKits上的重要按钮和点击元素。我们把主色分为10个层级,默认的是color-primary-600,向上的层级更浅,向下的层级更深,后缀的数值越小表示越浅,数值越大表示越深。

不同层级的颜色,可以适当使用在组件的hover、点击等状态,还有图标、背景等元素的颜色。

为了在深浅模式下有更好的对比度和显示效果,深浅两个模式下的主色是拥有不同的色值。在切换到深色模式时,系统会动态调整主色的色值(对应 color-primary-500)。

color-primary-100: #F0F8FF,
color-primary-200: #D1E8FF,
color-primary-300: #A7D1FF,
color-primary-400: #80B7FF,
color-primary-500: #589AFF, // 默认主色,深色模式
color-primary-600: #2C77F4, // 默认主色,浅色模式
color-primary-700: #1B57CF,
color-primary-800: #0D3CA8,
color-primary-900: #042682,
color-primary-1000: #02175C,

辅助色

有四种辅助色:分别是 success, warning, danger, info。每一个辅助色也同样是分成了10个层级,它们同样大多数是用在组件的状态,比如成功、警告、错误和普通提示。

下面以Success为例。

color-success-100: #E3FAEF,
color-success-200: #B2EDD2,
color-success-300: #84E0BC,
color-success-400: #5BD4A7,
color-success-500: #36C797, // 默认,深色模式
color-success-600: #15BA89, // 默认,浅色模式
color-success-700: #09946F,
color-success-800: #016E54,
color-success-900: #004739,
color-success-1000: #00211C,

基本色

基本色: basic color,即从黑到白的一系列中性灰(包括黑白),系统中使用最多的颜色,也是颜色中最复杂的部分。主要用于背景、描边、阴影、字体、图标等。

在设计深浅模式时,基本色可以共用同一套,也可以单独做两套(设计上会比较轻松),根据实际需要自行定制。我们的是共用同一套基本色。

basic_color

color-basic-100: #FFFFFF,
color-basic-200: #FAFAFA,
color-basic-300: #F4F4F6,
color-basic-400: #F0F0F0,
color-basic-500: #E8E8E8,
color-basic-600: #DBDBDB,
color-basic-700: #CCCCCC,
color-basic-800: #A6A6A6,
color-basic-900: #6C6C6C,
color-basic-1000: #8C8C8C,
color-basic-1100: #525252,
color-basic-1200: #404040,
color-basic-1300: #333333,
color-basic-1400: #262626,
color-basic-1500: #121212,

重新思考颜色的使用

有了上面这些颜色之后,如何使用它们将是一个关键问题,因为直接影响到我们如何设计深浅模式。

下面先分析我们以前使用颜色的方法,在进行多模式设计时会出现哪些问题,针对这些问题,重新思考了颜色在整个设计中的使用方法,这将让我们换一个角度重新看待颜色在界面设计中的使用。

BEFORE

以前是这样使用颜色的:

颜色 备注
#262626 正文文字 / 重要标题 / 组件文字 / 按钮颜色 / 背景颜色 /
#F4F4F6 背景颜色 / 分隔线 / hover颜色 /
…… ……
1. 定义有哪些颜色色值
2. 备注这些颜色分别是用在什么地方,在界面元素上直接指明用的是什么色值。

实例如下面两张图所示:

color_define

color_define_2

Yep!对于一个普通的APP或简单网页来说,这种方法是可行的。

但对于有着数百个页面和交互状态的系统来说,我们在实际应用的时候,设计上会有下面两个严重的问题:

  • 同一模式下,替换某一个颜色时容易把其它元素的也一起替换。

    曾经遇到过整体设计字体颜色太浅,需要更换字体颜色,但这时极有可能会把某个描边、某个背景颜色也一起替换掉。这种情况可以说是灾难性的,因为我们在使用颜色的时候,经常同一个色值会重复使用,可能既用在文字,又用在描边或背景,色值虽然相同,但作用范围不同。

  • 不同模式之间的颜色映射对应不上。

    浅色模式下的字体颜色 #262626 对应着深色模式的 #DBDBDB,但 #262626 同时也用在背景,那它的使用范围与#DBDBDB其实只有部分有交集。在模式切换时,总会有一些界面元素的颜色对应不上。这种要让每个颜色的映射关系时找到最优解是很困难的,在设计深浅模式或者其它多模式时会让人十分挠脑。

AND NOW

现在,对于颜色的使用,有不一样方法:

1. 每种模式下可以设置不同的颜色集,互不影响。
2. 拆解界面设计语言,划分不同类型的基础要素(如字体、背景等),主要用于区分颜色的使用范围。
3. 语义化颜色,根据拆解的基础要素来命名颜色,并且作为变量使用。

Scope

多模式下的颜色结构

颜色作用域

我们把每个模式下所拥有的颜色集称为作用域(Scope),每个模式都会有自己的颜色作用域,用于处理模式之间切换的颜色集管理。

模式之间颜色处理的方式有两种:

方式1(建议):设置一个默认模式(Default Mode -- 例如浅色模式),另外,其它模式相对默认模式**有差异的部分单独定义**,作为该模式独有的颜色作用域,在模式切换时,这部分颜色集会有更高的优先级。对于某些没有被定义的颜色,会获取和复用默认模式的颜色作用域里对应部分。

方式2:每种模式都单独设置颜色作用域,模式切换时,只读取自己的颜色作用域。

解构基础要素

在设计语言里面,除了颜色,我们发现能够影响UI外观的是一系列通用的基础要素,它们不是按钮、选择器这种级别的组件。当我们把这些界面组件继续往下解构时,它们可以拆分成下面几项(如上面所示):

  • 背景填充
  • 描边
  • 字体
  • 投影
  • 图标
  • 图片
  • 组件状态

PS:这些是我们设计不同模式时,界面上需要改变的基础要素。不同的设计语言会有不一样的拆解内容,比如iOS还有材质层 — 也就是我们常说的透明磨沙层。

这一步可以让我们理解到颜色在界面上的使用范围,为接下来 语义化颜色 做准备。

对于背景、描边、字体和投影,它们自身会有着不同的层级。我们常见的字体,这次设计了3 ~ 4种层级的深浅度,用在标题、正文、辅助等文字,因为做这种系统UI设计的大多数时候是在处理信息的层级关系(hierarchy)。拆解之后,我们可以单独定义每项基础要素及其不同层级的颜色,而且它们之间互不影响。

语义化颜色,动态改变色值

color_define_3

语义化颜色

所谓语义化,简单来说就是给对象起个与之意义相符合和容易理解的名字。

我们会给上面拆解的基础要素赋值颜色色值,并且给这个色值命名,每一个基础要素的颜色名称要唯一,并且作为 变量 使用。比如某个字体的颜色是#262626,我们不再是说这个字体的具体色 值,而是叫它primaryText

在不同模式下使用相同的命名,在切换模式时,相同命名的颜色的色值进行动态化改变。上图中的 primaryText 在浅色模式下是#262626,在深色模式下就变为了#FFFFFF;我们的主色在浅色模式下是#2C77F4,在深色模式下是#589AFF,都有共同且唯一的名称primaryColor

Yep!!! 这是语义化颜色带来的好处,可以轻松的改变颜色。如果有需要,在切换模式时,页面的元素甚至也可以动态使用其它命名的颜色,相当灵活。

再来看看已经调好的深色模式和浅色模式的一些组件,每项基础要素通过使用变量(颜色的命名)来赋值色值,模式切换的时候可以做到无缝对应。

Components

组件示例

定义颜色

为了确保深浅模式在切换时界面上的颜色能够对应得上,需要定义每个基础要素(也就是上面解构基础要素拆解出来的内容),以及它们不同层级的颜色。

背景

背景,有界面整体布局用到的背景,也有组件比如弹窗、下拉菜单所用到的背景,还有某些信息通过添加填充背景以与周围的信息区分隔离开。所以背景颜色不是单指某一个颜色色值,而且是一组颜色集。

界面整体的框架布局我们用到3个层级的背景,浅色模式下的白色是用到比较多的背景色,在它上面的还有稍微深一点的二级和三级的背景色,有了这些可以很轻松的构建系统页面的信息层级。

同样,深色模式的也一样。

background

Layout背景色

由于系统本身的复杂,除了整体框架布局用到的背景填充,还有一系列的组件也要用到背景填充,它们是作为上面3个层级背景色的补充。目的是将布局的背景填充与组件拆分处理,可以让组件灵活设计不受太多限制。

浅色模式下,这部分背景色有4个层级,虽然部分色值与上面的会有重复,但它们是不一样的变量,作用范围也不一样。同样对应到深色模式下也是有4个层级,与浅色模式形成一对一的映射关系。

深色模式下,fillBackground-1 ~ fillBackground-3 这三个的色值其实都是同一个,但它们也同样是不一样的变量。当然他们的色值可以不一样,视设计需要而定。

fill_color

辅助背景色

描边

我们把描边分为三个等级,每个等级的颜色都有使用的地方。primaryBorder大多数用在输入框、默认按钮的描边,sceondaryBorder用在表格分隔线、下拉菜单、弹窗的描边,tertiaryBorder用在内容块之间的分隔。

PS:这里对描边定义的颜色,实际上是包括了Divider分隔线,因为不想用太多颜色定义它们,描边的颜色一多使用起来会容易混乱。

Border

Border颜色

字体

界面中实际上出现最多的是文字,文字信息可以看作是人机交互最直接的交流媒介。

为了可以在设计上更好地处理信息展示的层级关系(hierarchy),我们在定义字体颜色的时候把它分成了4个等级,分别是primaryText secondaryText tertiaryText quaternaryText,应用的范围包括placeholder、组件默认文字、标题、正文、辅助和描述性文字等等,基本上揽括了我们整个设计中的字体用色。

Text

Text颜色

图标

作为视觉设计的一部分,图标和字体一样,在深浅模式下需要改变颜色,以达到更好的显示效果。使用有彩色的、使用渐变色的和使用组合颜色的图标需要特别注意。

icon_color

图标(不同颜色)

不过,通常有大量的图标实际上是可以不需要重新修改颜色的,只要通过调整图标的颜色在深色和浅色背景上能有明显的对比度。这种图标通常使用基本色,像下拉菜单上的图标、输入框、选择框中使用的图标。

下图这4组图标分别放在不同深浅的常用背景填充上,都能有不错对比度,而且图标的颜色都是同一个。

icon_basic

图标(相同颜色)

图片

大多数时候,对于需要配图的地方,在不同模式下我们会倾向选择使用同一张图片。

除非有以下两点的考虑:

一,为了更好的显示效果,有时候浅色模式下使用的图片在深色模式下不一定能搭配得上,反之亦然。

二,图片在不同模式下可能含有某些意义,可以使用与模式相匹配的图片,比如yahoo天气早上、中午、黄昏、和夜晚的图片,还有晴天、阴天、雨天的图片,都是根据当时的日照情况和天气情况而适配显示的。

pic

不同模式下的图片

投影

投影在我们的设计中是不可忽视的一部分,在设计信息层级(hierarchy)的时候用得比较多。它的使用可以让元素更突出,如浮层一样,与周围的信息形成更强的对比和区分。我们常用的Dropdown Menu、Dialog、Card就是典型的使用。

除此之处,投影也可以用在Button、Card等基础组件的hover、pressed的操作状态上,增强用户操作时的视觉反馈。

下图做了5个层级的投影,适用在上面所提到这些组件和操作。

Shadows

投影

状态

状态(States)的变化可以说是无处不在,只要有操作,界面上就会有状态的改变,这些状态是可以被感知到的,作为用户在操作时的一种反馈,通常是视觉上的感知(当然还有声音、振动,这里没有涉及到),这些都需要我们单独设计,

在界面设计中,有一些已经相当普适化的基本状态(参考下面的表格)。

Normal Disabled Hover Focus Selected Activated Pressed Dragged 这几个基本状态,一般应用在按钮、输入框、下拉菜单等组件上面,并不是所有组件都会有这些状态,对于不同组件的状态一般都可以单独设计。

关于状态远不止这些,还有很多涉及到业务流程上的状态变化,它们对应到界面设计上也会有状态变化,比如订单流程从下单到成功交易或取消交易,订单是有不同的状态流转,通常这部分是最容易被设计忽略。

基本类型 示例
Normal
Hover
Pressed
Focused
Disabled
Activated
Selected
Dragged

下图是定义了通用的Hover、Disabled的状态所关联到的描边和背景填充颜色。

States

部分通用状态

One More Thing

当上线后,如果需要调整设计,比如修改描边、字体、甚至背景颜色时,以前需要抓破头皮去想究竟还有哪些地方会受影响,现在只要把要改的部分直接改掉就可以。

以字体为例,如果要把字体颜色加亮或加深,只需要单独把这部分的颜色集修改就可以了。

因为它们都是单独的,而且可以看成是模块化,各基础要素在模式之间可以做到互不影响,在模式内也互不影响。

textMagic

替换字体颜色示例

📮 到底了