网格系统(Grid System)是本设计系统的基本规则,它是我用来 解决浏览器适配问题并使界面整体表现的规范 的非常有效的方法。另外需要指明,没有完美的方法,这就像前端中没有完美的可以解决所有问题并且都是最优解的框架一样。它仅是我们的一个思路,并围绕它去建立一套可以有效的解决规范及适配问题的 UI 设计系统,并应用到开发中。
Section 1
适配带来的问题
通常,我们都是基于 像素点(px)进行设计和开发的,每一个 UI 元素,都有一个相对固定的尺寸。
但是,现代的终端设备,无论是 PC 端,还是移动端,显示分辨率都是多种多样的。尤其在移动端各种不同的显示技术和分辨率下,使得 分辨率适配 成为一个让设计和开发都头疼的问题。
当 UI 元素尺寸固定时,保证其在各种分辨率下,无论大小都有一个非常良好的显示效果是一个不现实的问题。
如下图所示,一个大小固定为 100px * 40px 的 UI 元素,在四种不同的分辨率下展示效果是不稳定的。在较大的分辨率下,它将显得格外的小,而这显然不是我们所希望的看到的,因为它对于用户来说是非常不友好的。
这也同样会导致,在较大的分辨率下,单行(列)展示的内容(UI 元素)更多,而较小的分辨率下,展示的内容将较少。
我们通常通过 栅格 来解决此类问题(横向排版响应),或者通过纯粹的 响应式 设计,去改变不同分辨率下的排列及展示方式。
但这让设计们在考虑布局时花费了更多的时间和精力,也使前端开发们在页面还原时要格外的小心。
在时间充裕的时候,这些显然不是问题,但往往我们会面对时间紧任务量大的情况,所以也希望有一个更高效的方式,使设计和开发都能更快的完成各自的任务,并且减少因适配问题所带来的困扰。
面对此种情况,通常的解决方案是,针对不同的分辨率进行单独的设计。这种方案虽然照顾了多分辨率下的显示效果,但是却让设计及前端开发们操劳过度。
使用响应式 UI 框架(如 Bootstrap)也是一种方案,但是却无法解决个性化设计的全部要求(过分的模版化总是会降低操作的灵活性)。
既然涉及到适配时,我们总是纠结于在不同分辨率下的最佳展示效果和排版方式,那么,如果我们采用 矢量图形 的思路,使 UI 在我们需要时进行整体(通常不包含一些绝对稳定元素)的缩放,是不是可以解决这个问题呢?
Section 2
矢量图形的思考
矢量图形 是我们非常熟悉的一种图形,它没有固定的尺寸。
相较于位图拥有固定的大小及分辨率,在放大时会导致失真的情况,矢量图形能永远平滑的显示它的细节,而不需要去担心失真的问题(影响矢量图形显示效果的通常是显示设备,所以矢量图形依然会出现锯齿的情况)。
那么,如果我们将 UI 界面的元素也看作矢量图形,让他们在需要的时候进行等比例缩放,是不是就可以节约设计师大量的时间和精力,只需要确定一个变换的 断点(临界点) 和相应的比例就可以了呢?
显然,这可以解决我们绝大多数情况下遇到的适配问题,而我们也将针对这种广泛性的情况,探讨此方式的可行性。
首先,我们并不需要 UI 界面(元素)总是随着浏览器窗口的大小而改变尺寸,这点与矢量图形并不相同的。
所以,在未达到 响应断点(临界点) 时,我们依然采用传统方式来解决 自适应 的问题,这是因为在分辨率变化不大的情况下,UI 元素不存在相对于界面在视觉上的巨大落差导致的不协调问题。
接下来,就是 断点 的确定依据(主要针对 Web 端的界面,移动端可以直接去适配屏幕的宽度,相对而言没有 Web 端复杂)。
大多数时候,我们都不需要进行整体的缩放,而当我们照顾较小分辨率进行设计时(如针对 1,366px * 768px),UI 通常会采用较小的尺寸,如果适配在比较大的分辨率下(如 1,920px * 1,080px),会导致 UI 过小,这时我们就可以对 UI 进行整体的缩放,以保持显示的清晰性和整体的协调性。
为什么我们不让它在横向展示更多内容呢?
通常,宽度过大的界面不利于阅读,此类界面通常会提高 UI 的显示比例(UI 尺寸),或设置显示的 安全区,使内容更聚焦,保证阅读的流畅性(参考书籍文章,在文字相对较小的情况下,单行过长将导致阅读不便)。而很多时候,我们的 UI 元素,如 表格元素(Table),它本身是整体适应容器的,在它的左右没有其他的 UI 元素时,当整体比较宽却没有足够的内容(列数)时,会导致内部展示的信息松散,不利于阅读。
Section 3
网格系统及设计应用
网格 是将界面划分为由若干个 单元格 组成的网状结构。
我们将所有的 UI 元素及其关系,以 单元格 为基本单位进行设计,使其在达到需要进行缩放的断点时,通过调整单元格的尺寸大小,就可以使界面进行整体按比例进行缩放(绝大多数相对元素,少量绝对稳定元素则不参与缩放),以保持原有的显示比例。
通过这种方式,我们就实现了 UI 界面在较大的分辨率中显示时,保持稳定的比例,而不需要进行额外的设计。
之所以我们不用 像素 作为网格的基本单位,是由于我们的 浏览器 、显示器 乃至 Sketch 等设计软件的画布,其实都是基于像素点构成的网格。但是它的颗粒度太小了,我们除了描边和分割线,几乎不会出现 1 个像素的元素(移动端为了柔化边框及分割线,往往会采用 0.5 像素的线条),而像素 又是一个绝对值,它不会也不提供基础尺寸的改变。
所以,我们将 网格 设定为一个相对大一些的值。为了灵活性,我们采用 4px * 4px 的单元格作为网格的基础元素尺寸。这样,当我们在达到 断点 时,只需要将我们的单元格尺寸进行调整,即可达到想要的效果。
如果不考虑良好的兼容性(针对目前依然存在的分辨率及屏幕尺寸较小的设备,我们还需要考虑兼容性的问题,所以我们不得不采用保守的方案),我们甚至推荐使用 8px * 8px 的基础单元格尺寸。
当前的终端设备分辨率及屏幕尺寸越来越高,未来我们可能不需要再去顾及那些比较古老的显示设备,而宽阔的界面展示也往往给我们带来很好的呼吸感和信息展示的清晰度。
Section 4
网格系统的前端实践
前端开发其实和 UI 设计有高度的共通性。
针对网格的实践,前端也有一个非常合适的单位 - rem。
这是一个前端开发者都非常熟悉的单位,在移动端开发中经常会被用到。但是它拿到 Web 端也依然是一个非常符合我们需求的单位。它基于根元素(root)的基础值设定,由根元素的 Font-size 属性来定义它的尺寸。
在几年前,我们的构想还难以通过它来实现。早期的浏览器内核(Web 端),默认状态下会将根元素中,Font-size 小于 12px 的尺寸默认看作是 12px,这使得我们如果想要使用网格的方式去进行设计和实现,将不得不采用 12px 或更大的单元格,从而导致后续的关系设置中,出现大量带小数值的关系。
另外需要注意的是,栅格 是与 网格 并存的,网格 用来做整体的适配,而 栅格 用来做局部的横向适配。所以,对于 Flex 类型的元素,包括栅格元素在内,它们的宽度是不需要遵循网格系统的,真正在适配中影响到它们的,是走网格系统的间距 (Margin 及 Padding)。
同时,断点 的设置依然依赖 媒体查询(Media Query)。
我们将常见的尺寸划分为 3 个阶段,依据 浏览器视窗宽度(Screen Width)进行响应。在阶段切换时进行断点响应,而在阶段内依然采用 自适应 的方式去处理。
在 Web 端,我们支持的最低分辨率是 1,366px * 768px,目前不考虑更小的分辨率支撑(C/S 结构由于特殊性,目前不设置最低分辨率)。
第一个断点设置在 > 1,920px 处,此时,我们的单元格尺寸提高至 5px。
第二个断点设置在 > 2,560px 处,此时,我们的单元格尺寸提高至 6px。
至于 4K 以上的分辨率,目前的显示器通常会主动对分辨率进行降级(4K 以上目前都会将分辨率主动限制在 2,560px * 1,440px)。
我们之所以选用 rem 而不是其他的相对单位,是因为其它常见的如 vw、vh、vmin、vmax 等相对单位,它们的基准值并不是像素,而是浏览器的宽度或高度,这使得构成它们并不稳定。而且,在浏览器拖动缩放过程中,它们总是在变化,这会导致重新渲染等一系列的问题,这并不是我们希望看到的。
我们的响应缩放也不采用 zoom 这个属性,这个古老的属性目前已经在被淘汰的进程中,从开始就存在兼容性的问题,而且它并不关注你是否设定了稳定元素(不参与网格响应),更像是浏览器自身的缩放带来的效果,所以它显然也不是一个合适的解决方案。
Section 5
总结及说明
网格 不仅仅被用来解决我们关于设计及开发过程中的适配问题,它还是一个尺度,用来控制设计及开发的严谨性。
从开发角度而言,长久以来一直困扰着我们的页面还原问题,通过网格的方式也能得到有效的改善。毕竟当网格用起来的时候,所有的元素尺寸及间距都是一种关系,而不是一个“随便得来的固定数值”。