首页

实战:如何利用栅格系统做响应式设计- 后台设计经验总结(2)

分享达人


左右布局响应策略动态演示。考虑到gif被压缩后效果不理想,所以做了一小段视频来帮助大家更好的理解响应策略。视频如果看着不清晰,选择清晰度为1080p蓝光观看即可

Image title

Image title

一、什么是响应式?

按照本人自己的理解,响应式就是通过合理的设计方案配合规范的技术实现策略,使同一个Web页面在各个终端(设备)不同分辨率屏幕上都能有最佳的用户体验。

Image title

这里说是用户体验而不是视觉效果是因为用户体验包含了性能、交互、效率等多方面内容,也就是说,对于一个线上的响应式页面,我们不仅要关注视觉上看到的,也要关注我们操作、使用时的感受,这些综合因素最终影响着用户使用后台系统时的效率与体验。而这里我提到的“合理的设计方案”就是本篇文章跟大家分享的重点:如何利用栅格系统完成后台页面的响应式设计。对于交互与性能方面内容,本篇文章不做介绍,因为两者涉及到我不太了解的技术相关知识。我提出这个观点主要希望大家在执行设计时,能有更全局的考虑,多跟交互与开发沟通,协力打造更好的用户体验



三、响应式的目的是什么?


后台系统做响应式设计的目的:提高屏幕利用率,最大化操作效率


1、提高屏幕利用率最简单的理解就是在大屏幕上显示更多内容,在小屏幕上通过数据筛选展示关键信息。一直以来大家普遍认为移动端碎片化严重,但实际上桌面端设备的分辨率也是有着不太均匀的分布,而随着新设备的更新,更多高分辨率屏幕不断加入,这种碎片化的趋势会更加明显,因而要想利用好每一块屏幕,让不同分辨率的用户都有好的体验,显然传统固定的布局是做不到了。

Image title


2、后台系统的应用特性,决定了响应式在后台设计中具有很高的实用价值。后台系统有两大主要功能:查看与操作。查看主要是各种数据,是系统自动生成的内容;操作是需人工干预、人工决策的任务,查看的数据为操作提供了依据,而操作支撑了公司或部门业务的正常运行。所以后台系统设计最基础的目标之一是如何通过良好的数据展示帮助用户提高操作、决策效率,而充足的展示空间显然是实现这一目标的基础,响应式设计通过为每个分辨率设定合理的版式布局,使数据在每块屏幕上都尽可能展示的最佳。优化后的数据展示,帮助用户更获取信息,从而提高了用户使用后台系统的效率与体验。

Image title



四、为何要利用栅格系统来进行响应式设计


响应式可以响应的前提有两点:1、页面布局具有规律性、2、元素宽高可用百分比代替固定数值,而这两点正是栅格系统本身就具有的典型特点,所以利用栅格系统进行响应式的设计是顺理成章的,也比较快捷,所以响应式与栅格化天生一对好搭档


栅格系统页面布局具有规律性、元素宽高可用百分比表示

Image title



五、利用栅格系统完成后台页面响应式设计的步骤


1、确立设计稿基准尺寸


设计稿基准尺寸是指我们从哪一个分辨率开始设计,也就是我们新建画板时画板的尺寸应该是多大。而这个尺寸确定的主要依据是我们后台系统所面向的主要用户的屏幕分辨率;我们分两大类情况来讨论这个问题。


(1)、如果我们的系统是给公司内部员工使用,由于公司批量采购设备的原因,公司内部员工的屏幕分辨率往往会比较统一,这种情况下我们需要拿到这个数据,然后以它作为基准尺寸开始设计。因为虽然响应式设计的目标是让页面在每个分辨率下都有最佳的体验,但实际开发中毕竟存在损坏,设计还原很难100%,因而大多数情况下还是基于基准尺寸的设计与开发,在用户端显示效果最佳、体验最好

(2)、如果我们的系统是平台级面向全网用户,或者虽然是公司内部使用,但是并不能统计到内部员工屏幕分辨率情况,就可以以1440*900作为基准尺寸开始设计。从统计数据来看,目前国内PC端用户屏幕分辨率排名前三的分别是1920*1080、1366*768、1400*900;1440的尺寸实际上是处于中间位置,如果以它为基准设计,最终向上向下响应适配后,相对误差最小,从而达成用户体验的最大公约数。

Image title



2、确定页面布局结构


页面的布局结构,是页面基本框架,后续的设计都是在这个大的框架下完成的,所以确定页面基准设计尺寸后,需要跟交互设计师或产品经理配合,根据实际业务情况讨论确定页面布局结构。一般来讲,后台系统有两种最典型的页面布局结构:左右布局与上下布局(这两种布局是最典型也是最基础的布局形式,其余布局,下期内容讲)


上下布局

Image title

上下布局的结构在传统网页中非常常见,而在后台系统中并不常用。这种布局的优点是符合用户认知,遵循用户从上而下浏览页面获取信息的习惯;贯穿全屏的导航栏设计也使页面显得正式稳重,除却导航栏之后相对较大的空间也为内容展示提供了比较充足的空间。缺点是顶部一级导航受页面宽度限制,数量会比较局限,同时导航层级较深时,交互效率也不够理想。所以该布局适合那些导航层级较少,内容展示充分的后台系统设计


左右布局

Image title

拥有侧边导航的左右布局页面结构,是在后台系统中更常见的页面布局形式。侧边导航栏可以固定也可以收起,相对比较灵活,同时文字横向排列的形式可以在竖向上展示更多内容,因此侧边导航比顶部导航能容纳更多一级内容,而层叠式的内容展示也使得一、二、三级导航内容关联更为顺畅,可扩展性也得到加强;由于侧边栏可以常驻在页面左侧,所以对于右侧内容的指示性也优于顶部导航,切换起来也更加方便。但同时,因为侧边栏的常驻,导致右侧内容区域空间被挤掉部分,所以相对上下布局的结构,左右布局的结构,内容区域空间会比较小;一般为了与页面其它区域做区分,导航部分会用更深的颜色、安排更多的图标和文字,这也导致了在视觉上左右布局的页面不够平衡,会有左边重右边轻的感觉。


3、对内容区域建立栅格系统


根据不同的布局类型,对页面内容区域建立栅格系统。对于一个利用栅格系统做响应式设计的页面来讲,主要有三大数值需要规范:Column、Gutter、Margin;对于Column、Gutter我们在上一期内容中已经有很详细的介绍,不再赘述,而Margin是页边距,主要确定了内容区域距离页面边缘的距离,它分布在内容区域的两侧,主要作用是通过留白把内容区域与周围环境隔离出来,从而突出内容区域的显示,此外还可通过Margin值来调整内容区域显示比例,使页面在视觉上有更好的呈现效果。所以一个用于响应式的栅格系统事实上由Columns、Gutters、Margins三部分组成。


上下布局结构与其对应的栅格系统

Image title


左右布局结构与其对应的栅格系统

Image title


4、根据实际业务内容确定盒子(Box)比例


上下布局结构的盒子

Image title


左右布局结构的盒子

Image title


5、确定响应策略


响应策略就是当视窗(Viewport)发生变化时,内容区域的元素如何去响应,具体到我们当前的栅格系统,就是Columns、Gutters、Margins以及由Columns跟Gutter组成的盒子(BOX)四者的值(主要是宽度)如何变化,以及在这种变化之下我们页面的布局如何调整。


为了方便直观的向开发工程师与团队里的其它小伙伴沟通,我们可以把这个响应策略制作成如下的表格,并在页面中标注说明相关元素的变化规律,供自己与开发参考。


由于带左侧导航的响应式规则相对复杂,所以我先以它为例跟大家交流下响应策略如何制定


左右布局响应策略表

Image title


如图,响应式是以视窗的最小宽度作为基本依据来制定每种宽度下Columns、Gutters、与Margins的响应策略,也就是说Viewport Min-width是做出响应的触发条件,视窗每达到一个最小宽度,就会触发该宽度下预设的页面布局方式,而每种布局都是在该宽度下的最佳布局,也是因此,响应式才会在各种复杂分辨率条件下都能给用户比较好的体验。


每个视窗宽度的最小值是触发响应的关键值,因此我们给这些用于触发的关键值起了个名字叫“Breakpoint”,每个Breakpoint触发一种响应策略,而每个策略持续(保持)的宽度范围就是图中绿色矩形的范围。以图中第二行矩形为例,该矩形代表的响应策略是:栏目数是8、水槽宽度16(SM)、页边距32、侧边栏收起且仅展示图标,当点击侧边栏展开图标时侧边栏以Push的方式展开,该策略触发的Breakpoint是768,保持范围是577~768。也就是当视窗宽度缩放至768时,栏目数量由上一级的12变为8,水槽宽度由24变为16,侧边导航由完全展开状态自动收起文字部分,仅保留图标,然后保持这些关键数值不变,直到视窗宽度达到另一个Breakpoint。需要特殊说明的是,第一行矩形中0~576(Min&Fixed)这个范围的视窗宽度是固定的,也就是在该套响应策略中,页面最小响应到576的页面宽度,当视窗到达这个宽度时,浏览器会限制视窗进一步缩小,因为当页面宽度比它还小时已经无法有效展示数据了,所以进一步的缩放是毫无意义的。


左右布局响应策略动态演示

考虑到gif被压缩后显示效果不理想,所以我做了一小段视频来帮助大家更好的理解上述响应策略在实际页面中如何发挥作用。视频如果看着不清晰,选择清晰度为1080p蓝光观看即可


左右布局响应策略标注

Image title


对于上下布局的后台系统我们根据内容区域(Container)宽度定义的不同方式,可以把它们分为两类:


1、内容区域定宽的后台系统( Fixed-width Container )


内容区域定宽是指内容区域在每一组视窗宽度区间内,都会设定一个最大值(Max-with),当内容区域宽度小于最大值时,区域内元素会响应视窗的变化;达到最大值后,内容区域不再响应视窗的变化,而是宽度保持该最大宽度值不变,此时我们通过增加页面两侧的margin值来响应视窗的变化。Flex Margin就是应对此情况的动态页边距。

Image title


 上下布局响应策略表(内容区域定宽( Fixed-width Container ))

Image title


2、内容区域宽度流式 (fluid-width Container) 


内容区域宽度流式 (fluid-width Container) 的后台系统,它的内容区域 (Container) 距离页面两侧的页边距Margin是定值,因此视窗有多大内容区域就展示多大。




Q&A


1、后台系统必须做成响应式么?


并不是必须的,是否要做响应式主要是根据后台产品面向的用户来定的。如果是公司内部使用的系统,且员工配备的桌面设备都是有统一的分辨率,就可以不做响应式;如果是面向全网用户的后台产品(比如淘宝商家的后台管理系统,阿里云的控制台)或公司(部门)内部的桌面设备并没有统一的分辨率规格,那么就需要做成响应式。当然了,更实际的环境中是否做响应式还有技术实现、时间、人员成本等各方面因素的考虑,有时为了尽快的让业务运营起来,后台系统会做的比较“简陋”



2、为什么栅格系统没有适配到移动端的分享?


因为后台管理系统的使用场景主要是工作时间在桌面设备上使用,由于庞杂的数据内容在移动设备上展示困难、操作不便,因而很少有公司会把后台系统响应到移动端使用,所以我们今天说的后台响应式仅针对桌面设备屏幕。



3、对于iMac4k、5K这类超高分辨率的屏幕如何做响应式设计?


对于左右布局的后台系统,实际上它是全屏展示的,也就是屏幕有多大就展示多大,因而iMac的响应策略也是按照左右布局响应策略表里的策略来响应对于上下布局,内容区域定宽的后台系统,iMac的响应策略使用上下布局响应策略表里的策略来响应即可;


对于内容区域宽度流式的后台系统,iMac的响应策略可以参考左右布局的响应策略表来处理栏目、水槽的变化,页边距保持定值即可。



4、在以8为原子单位的栅格中,Margin需要按8n的规律变化么?


能以8n的规律变化是最好的,如果无法做到也可以使用其它数值。Margin是页边距,主要作用是通过留白的方式将页面内容区域与周围环境隔离区分出来,从而突出内容;一般我们会优先考虑内容区域匹配8n的变化规律,安排完内容区域后剩余的空间自然成为页边距(margin)



5、响应策略制定的时机是什么?如何去制定?文中示例的策略表我可以借鉴套用么?


响应策略表一般是在主要页面设计完成,要交付开发实现的时候来跟开发一起商定。这块需要注意两点:


1、如果开始设计时就已确定页面是要具备响应式的能力,那么最好开始设计时就去跟开发沟通,看他们现有技术是如何来做响应式的,因为他们很有可能是在用Bootstrap、Foundation这类组件库来做开发,而这些组件库一般都有自己现成的响应规则,这种情况下我们需要了解开发他们的规则,让自己的设计匹配已有的策略。当然了,如果他们的规则并不能很好满足我们的业务需要,一般也是可以在这些组件的基础上让开发去修改调整的。


2、响应策略表只是对响应方式的结果的呈现,而这个策略的制定事实上是从设计开始执行时就要去考虑的,从我个人经验来讲,我一般会挑两类页面来做响应策略的研究与适配,一个是控制台(Dashboard)页面,另一个是表单(Form)页面。优先规划这两个页面的设计,考虑他们在各个Viewport下如何布局如何展示如何缩放变化,并且跟开发沟通想法,听取意见,制定初步的响应计划,当这两个页面设计完成,就可以更大范围的执行设计。


3、文中示例的策略表是基于我自己项目经验总结而来,具有实际应用价值,可以借鉴。但我更想做的是通过那个表希望跟大家分享一种与开发交流、沟通的方法和技巧。实际工作中我们并非一定要做出那么一个经过精心设计细致考虑的表,我们可能会找张纸画一画给开发看就可以了,这块的重点是如何把我们设计师的想法更可视化更直观准确的传达给开发工程师。所以那张表是启发而非标准。


控制台(Dashboard)页面示例(素材图片作者:Coderthemes)

Image title


表单(Form)页面示例

Image title

转自UI中国-BYMD



栅格系统及其在后台设计中的应用—后台设计经验总结01

分享达人

关于栅格系统文章不少,但鲜有专门针对栅格系统在后台设计中相关应用的介绍。本文抛砖引玉,希望引起更多同行的交流与讨论

Image title

Image title


栅格系统的目的


栅格系统在页面排版布局、尺寸设定方面给了设计者直观的参考,它让页面设计变得有规律,从而减少了设计决策成本;栅格化提高了页面布局的一致性跟复用性;避免了设计师与开发者在细节上的反复沟通确认,从而提升了整个设计开发流程的效率、并能帮助开发者实现较为理想的设计还原。

但实际应用中,由于对栅格系统理解的不充分,很多设计师在应用栅格系统的实践中产生了各种问题,本来帮助设计的工具现在反而成了设计中需要解决的问题。结合我自己后台设计的经验,本篇文章跟大家聊聊栅格系统在后台设计中如何应用。



建立栅格系统的方法与规则


1、第一步:确立栅格系统的原子单位(网格)


如图,一个比较完整的栅格系统是由许多规格一致的小网格组成,这些网格辅助我们更规范的排版、布局。

Image title

后台系统设计中,由于后台页面主要以Web形式呈现,而对于web,用户已习惯通过鼠标滚轮或滚动条(scrollbar)来纵向浏览页面内容,因此,在不考虑内容优先级的情况下,Web可以实现竖直方向的“无限”加载,即竖直方向可以无限延伸,因此基于Web的后台页面,它的栅格系统在水平方向的栅格可以不体现出来,我们在执行设计时只要在竖直方向保持规律的变化就可以了。标准的栅格系统简化为适用于Web后台的设计如下图所示

Image title

如上图,对于后台设计来讲,栅格系统是由栏目(Column)跟水槽(Gutter)交替分布形成的,栏目(Column)是接纳网页内容的容器,水槽(Gutter)用来调节相邻两个栏目间距,把控页面留白;由于栏目跟水槽的宽度是以网格作为基本单位来增加或者减小,所以栅格化的第一步需要先定义好栅格的原子单位“网格”的大小。根据本人的设计实践以及其它已有规范经验,目前后台栅格系统网格大小定义为8是最普适易用的。具体原因有以下几点:


(1)目前主流桌面设备的屏幕分辨率在竖直与水平方向基本都可以被8整除,使用8作为最小原子足够普适.


我们选取4、6、8、10、12为栅格的候选原子单位,然后用目前主流屏幕分辨率与其相除,判断各个分辨率在竖直(Y)与水平 (X)方向能否被候选原子整除,统计结果如图。

Image title

显然,对于目前市场桌面设备屏幕而言,4是整除率最高的一个原子,接下来依次是8、10、6、12。但4作为基本原子实在过于小了,太小的步进单位将导致我们决策成本的增加,因为我们将元素间间距增加4px或者减小4px视觉感受到的差异并不明显,这种情况下我们为了找到那个“合适、满意”的间距,就需要反复调试,这就造成了时间上的浪费,尤其对于没有经验的新人,这点会更为突出。但这种调整并不合适,原因是后台管理系统设计重点在于面向用户使用的效率与逻辑,其次才是视觉呈现,使用栅格系统的目的之一也是想减少设计师在“细节”上的纠结,希望设计师站在更全局的角度看待设计,合理安排时间,因此我们舍弃4。在剩下的6、8、10、12四个单位中,8的整除率最高(80%),以8像素作为一个步进单位的变化,我们视觉上也是能感受到较为明显的差异,因此选取整除率最高的8做为栅格系统的原子单位。



(2)以8为单位符合“偶数原则”。偶数原则可以在页面缩放中的避免类似于0.5、0.75、1.25等次像素的出现,从而使页面各类元素在大多数场景下都能有比较精致的细节表现


虽然对于后台设计而言,通常设计师是直接在目标尺寸下进行设计,并在此基础上标注、切图给开发实现,并不存在像移动端那样需要对各种尺寸、各种像素密度的设备进行适配的情况,但对于Web页面来讲,仍存在向上向下适配的可能,因而从页面的兼容性、可扩展性及可维护性层面来讲,我们设计师还是有必要考虑的更加长远,遵循“偶数原则”可以上避免各种潜在的问题。

Image title


(3)开发工程师使用的前端开源组件库比如Metronic、Antdesign等也是基于8的原子单位来设计,因此如果设计师也使用以8为基本单位的栅格系统,开发与设计师相互对接就会更加方便,开发实现页面时也能更高品质的去还原我们设计师的稿件



2、第二步:建立基于原子单位的栅格系统


经过第一步讨论,我们现已确定后台设计的原子单位为8,而我们也知道栅格系统是由栏目(Column)跟水槽(Gutter)交替分布形成的,所以接下来我们要利用原子单位确定栏目跟水槽在具体的页面中如何分布以及它们各自的宽度。


通常,在一套后台设计系统中,水槽宽度会是几个比较固定的数值(因为后台系统的页面相对于其它类型的Web页面,表现的更加整齐、规律,所以留白的方式比较固定,加之后台往往有大量的数据、内容需要呈现,所以要尽可能提高页面利用率,可以留白的空间也比较有限);而栏目宽度更加灵活,它可以根据页面水平方向尺寸的改变而增大或减小以响应页面的变化(遵循8n的变化规律,此处变化规律在下期文章《栅格化与响应式》里会详细介绍)。


当我们做后台设计的时候首先需要确定在什么样的分辨率下做设计,也就是首先需要确定设计稿的尺寸,当设计稿尺寸确定后,便可建立基于该尺寸的栅格系统。假设页面内容区域宽度为W,栏目个数为A,水槽个数为B,栏目(Column)宽度为C,水槽(Gutter)宽度为G,则W=A*C+B*G。栅格系统建立初期,由于我们并不确定之后会有什么样的内容呈现我们的页面上,所以为了让栅格更加灵活、普适,我们先假定单个栏目与水槽的宽度是相同的,即C=8n(n=1、2、3、4...)=G,然后以此将页面内容区域等分,形成初步的栅格,之后再按实际内容需要,按比例调整两者宽度或者按比例对两者进行组合,形成承载业务内容的盒子。目前有两种比较主流的等分方式:12等分与24等分。


12等分的栅格系统在流行的前端开发开源工具库Bootstrap与Foundation中广泛使用,适用于业务信息分组较少,单个盒子内信息体积较大的中后台页面设计;

Image title


24等分的栅格系统适用于业务信息量大、信息分组较多、单个盒子内信息体积较小的中后台页面设计;相对12栅格系统,24栅格系统变化更加灵活,更适合内容比较多样复杂的场景。

Image title



栅格系统的应用


1、页面布局与版式设计


(1)、了解承载业务内容的盒子模型(Box Model)


建立好栅格系统后,就可以根据自己的实际业务,在栅格系统上安排内容了。页面上最终承载内容的其实是一个个“盒子(Box)”,这个盒子的高度由盒子要容纳的内容与页面版式设计决定,按8n规律变化;宽度则由栏目与水槽按比例组合得到。


在栅格系统上容纳业务内容的容器我们把它称之为盒子(Box),栅格系统上的盒子其实跟前端工程师写页面时用到的盒子是一致的。如图所示,当我们浏览任何一个网页时,右键>检查元素(审查元素),然后在style菜单下就可以看到这个盒子结构了。其中Padding就是主体内容(Element)距离盒子外侧的距离,我把它称之为内边距,(Element可以是一个按钮,一段文本、一张图片或者一个表格等;)而Margin就是相邻两个盒子间的距离,对应在后台栅格系统中其实就是水槽的大小。了解完栅格系统的盒子模型之后,下一步我们需要根据具体业务内容来确定盒子的宽度,也就是如何利用栅格系统做实际内容的布局与版式设计

Image title


(2)、根据业务内容分配页面比例,确定盒子宽度


以24栅格系统为例,一个24栅格系统可以根据业务需要被2等分、3等分、4等分、6等分、8等分、12等分,还可以被1:1:1、1:2:1、1:3:2、2:3:3、1:2、1:3、1:5、3:5等不对称分割,具体采用哪种比例的组合需要我们根据自己业务需求来定,我们此处所说的比例实际上就是盒子的宽度。

Image title

上图展示了盒子在24栅格系统上的分布情况,图中只列举了部分比例,实际业务中,同一个页面上使用一到两组比例值的组合来布局是比较合适的(如下图),组合形式过多页面就会显得琐碎、杂乱,不利于阅读和使用。因为盒子的高度根据内容来定,故下图中没有体现高度这一维度的变化规律。

Image title

当我们完成上图规划后,需要做的便是根据实际内容往每个盒子里安排内容,做视觉与交互的落地了。



2、元素对齐与间距设定


栅格系统大的层面可以帮助设计者更好的进行版式设计与内容布局,而小的方面可以辅助设计师规范页面内各种元素的对齐与间距的设定。从用户体验角度来讲,这两者同等重要,从执行层面来讲,我们一般先做版式设计与布局,然后再填充内容、调整细节。


栅格系统辅助对齐的作用类似于各种设计软件中的参考线,它能让我们更直观的安排、调整内容的位置及对齐方式,可以使内容变得规律、有序,方便用户浏览阅读,帮助用户提高获取信息的效率。


栅格系统对于元素间间距设定的帮助是直观的,当我们定义了栅格原子单位为8时,这意味页面上各元素间距的变化也应遵循8n的规律,一致的变化规律让页面富有节奏感跟韵律感,在提高页面一致性的同时也减少了设计决策成本。我们知道,栅格系统中水槽与栏目的变化也遵循8n的变化规律,此处n为大于0的正整数,即n=1、2、3...;但是用于规范元素间距的8n,n可以是0.5、1.5这类包含二分之一8的情况,原因是实际工作中,我们面临的情况是复杂的,这样处理可以让间距的设定适应一些特殊的场景,从而使其更灵活普适。

Image title



注意事项


1、水槽宽度的设定


确定好内容模块比例后,我们会发现由于之前等分的缘故,此时水槽较宽,我们需要调整水槽宽度到一个合适的值。


水槽的宽度是8n,也就是水槽可以以8为基本单位去增加或减小。为了减少设计决策成本,我们会事先设定好一系列水槽宽度,并定义好每个宽度对应的使用场景,然后设计中根据每个场景使用对应数值就可以了。我定义了一组水槽的值是8、16、 24、32 、40,为了区分它们的使用场景我们依次为其命名为XS、SM、MD、LG、XL。根据实践经验,正常情况下,两个盒子间距(水槽)的值为24(MD)时,视觉上是最为舒适。

Image title


栅格化工具推荐(插件请在附件中下载)


Ps栅格系统工具


1、PS自带栅格系统设定:新建参考线版面(重点推荐)


Ps有个功能叫做“新建参考线版面”,打开这个面板后,在预设这里可以看到Ps已经预设了8列、12列、16列、24列的栅格系统,选择对应列数就可以看到页面上参考线的变化。预设中“装订线”的宽度即栅格系统中水槽的宽度。默认均为20px,我们可以根据之前讨论的8的倍数原则,将其手动更改为24;


如果预设的栅格系统无法满足我们工作需要,我们也可以自定义栅格系统,并能将栅格参数保存为预设,这样就可以重复利用自定义的栅格系统了;栅格系统还可以选择将其应用在当前画板或者所有画板,十分方便易用。由于是Ps自带的参考线,所以它可以通过快捷键灵活的控制显示或隐藏

Image title

Image title



2、利用Ps标注工具Assistor Ps 进行栅格系统的建立


Assistor Ps在之前主要是一款页面标注工具,但是随着蓝湖等自动标注工具的流行,这个小软件基本没人用了,但我发现它设置参考线的功能还是很强大的,可以媲美大名鼎鼎的guideguid(这款插件目前对Ps cc 2017及以上版本貌似已经不支持,软件本身安装也挺麻烦),所以就介绍给大家。(安装包在文末下载,Win&Mac,解压后跟常规装软件一样,正常安装就行)。但是这个插件由于很多数值都要自己算,实际上没有Ps自带的新建参考线面板的功能好用。算是一个工具的补充吧

Image title



Sketch栅格系统工具


1、Sketch自带栅格系统设定:Layout Settings

Image title

Sketch端利用sketch自带的栅格工具Layout Settings即可完成栅格系统的设置,由于sketch的栅格工具是自带的,与Ps类似,它也可以通过快捷键快速显示或隐藏,点击左下角“Make Default”还可以将自定义的栅格系统设置为默认的栅格系统,方便以后重复调用,但sketch貌似只能储存一组栅格系统的数值,而Ps可以储存多组。



2、Sketch栅格系统插件:BootstrapGrid-maste


BootstrapGrid是一个专门用于建立栅格系统的插件(插件在文末附件中下载),插件可以对栅格系统的基本数据做个性化的设定,可以对多个形状同时建立栅格系统,还可以通过快捷键快速调用。具体用法:先选中要建立栅格的画板或者画板里的形状(可以多选),然后:插件>Bootstrap Grid(Plugins -> Bootstrap Grid)


栅格系统参数设计

Image title



单个形状(画板)建立栅格系统动图演示

Image title



多个形状(画板)建立栅格系统动图演示

Image title



跨平台的web端栅格工具 http://grid.guide/


GridGuide 最大优点是可以针对一种栅格系统生成4组不同水槽宽度的栅格化方案,能比较直观的比较不同水槽宽度下各个栅格系统的视觉感受。使用方法:在右上角设置好页面宽度以及栏目数量,页面内就会自动生成可以下载为png图片的栅格。


Image title


QAQ(常见问题解答)


(1)当栅格系统中奇数不可避免的出现时,如何处理?


理想状态下,我们应该调整内容区域的大小,使其尽可能成为可以被8整除的尺寸,但实际应用中,有时会出现无法整除的情况。基于对盒子模型的理解,此时我们保持padding、margin的值不变,改变盒子的大小去适应奇数的页面(元素)即可,因为一致性跟效率才是栅格化要达成的首要目的,偶尔有一些不“完美”的尺寸是完全允许的,因为用户在实际使用页面时,并不能看到我们使用的栅格系统,也很难注意到那几像素的变化,他们能感受到的是页面整体呈现出来的节奏与韵律感,以及持续、一致的视觉语言带给他们的严谨、可靠的心里感受。



(2)栅格系统必须以8作为原子单位?使用其它数值是否可以


首先需要指出的是使用其它数值当然也可以,栅格系统只是手段,提升设计效率、减少沟通成本、提高页面一致性才是最终目的,所以如果你所在团队有其它栅格化习惯,且一直以来效果良好,那么继续使用它也是没问题的。但是对于设计新人来讲,如果能理解前人的经验,并能较好的运用,对于他们来讲,是会少一些弯路,更好的完成设计工作。



(3)栅格系统建立初期是否必须使栏目宽度与水槽宽相等,并等分内容区域?


建立栅格系统时并不是必须使栏目宽度与水槽宽相等,并等分内容区域。本篇文章介绍栅格系统时采用这种处理方式是为了让大家更好的理解栅格系统建立的原理与过程,事实上,栏目的宽度在实际应用中往往大于水槽宽度,我们通常会先计划好水槽的宽度、内容区域总宽度与栏目的数量,这时候栏目的宽度通过计算可得到,对于响应式页面,栏目的宽度可以是百分比而不是具体的数值(关于响应式的内容下期文章跟大家分享)。

转自UI中国-BYMD


九宫格方式上传图片(预览并删除)

前端达人

<view class="gallery">

    <view class="item" wx:for="{{images}}" wx:key="">

        <image src="{{item}}" data-src="{{item}}" bindtap="previewImage" mode="aspectFill" />



        <!-- 删除按钮 -->

        <view class="delete" bindtap="delete" data-index="{{index}}">X</view>

    </view>

    <view class="item" bindtap="chooseImage">

        <view class='addIcon'>+</view>

    </view>

</view>

<button type="primary" bindtap="submit">提交</button>

————————————————



/* pages/index/index.wxss */
/*画廊*/
.gallery {    
  width:630rpx;
  margin: 0 auto;
  display: flex;    
  justify-content: flex-start;    
  flex-wrap: wrap;
}
/*每张图片所占容器*/
.item {    
  position: relative;    
  margin:10rpx 5rpx;
  width: 200rpx;
  height: 200rpx;
}
.item image{
  width: 100%;
  height: 100%;
}
/*add按钮*/
.item .addIcon{
  position:relative;
  width:200rpx;
  height:200rpx;
  text-align:center;
  line-height:200rpx;
  font-size:80rpx;
  background: #f2f2f2;
  color: #555;
}
/*删除按钮*/
.delete {    
  position:absolute;
  right:0;
  top:0;
  /* background:#ccc; */
  opacity:1;
  height: 36rpx;
  font-size:22rpx;
  font-weight:700;
  padding:0 8rpx 0 10rpx;
}
————————————————


var that;
Page({
  data: {
    images: [],
    uploadedImages: [],
    //imageWidth: getApp().screenWidth / 4 - 10
  },
  onLoad: function (options) {
    that = this; var objectId = options.objectId; console.log(objectId);
  },
  chooseImage: function () {
    // 选择图片
    wx.chooseImage({
      count: 3, // 默认9
      sizeType: ['compressed'],
      sourceType: ['album', 'camera'],
      // 可以指定来源是相册还是相机,默认二者都有
      success: function (res) {
        // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
        var tempFilePaths = res.tempFilePaths;
        console.log(tempFilePaths);
        that.setData({
          images: that.data.images.concat(tempFilePaths)
        });
      }
    })
  },
  // 图片预览
  previewImage: function (e) {
    //console.log(this.data.images);
    var current = e.target.dataset.src
    wx.previewImage({
      current: current,
      urls: this.data.images
    })
  },
  // submit: function () {        
  //   // 提交图片,事先遍历图集数组
  //   that.data.images.forEach(function (tempFilePath) {
  //     new AV.File('file-name', {
  //       blob: {
  //         uri: tempFilePath,
  //       },
  //     }).save().then(                
  //       // file => console.log(file.url())
  //     function (file) {                    
  //       // 先读取
  //       var uploadedImages = that.data.uploadedImages;
  //       uploadedImages.push(file.url());                    
  //       // 再写入
  //       that.setData({
  //         uploadedImages: uploadedImages
  //       }); console.log(uploadedImages);
  //     }
  //     ).catch(console.error);
  //   });
  //   wx.showToast({
  //     title: '评价成功', success: function () {
  //       wx.navigateBack();
  //     }
  //   });
  // }, 
  delete: function (e) {
    var index = e.currentTarget.dataset.index; var images = that.data.images;
    images.splice(index, 1);
    that.setData({
      images: images
    });
  }
})
————————————————


微信小程序转发/分享功能 小卡片设置

前端达人

<button data-name="shareBtn" open-type="share" plain="true">转发</button>

添加plain=”true”后button的边框样式可自定义 ↓ ↓


button[plain]{ border:0


 //转发
  onShareAppMessage: function (options) {
      var that = this;
      // 设置菜单中的转发按钮触发转发事件时的转发内容
      var shareObj = {
          title: "这是一个标题!",        // 默认是小程序的名称(可以写slogan等)
          //path: '/page/index/index/user?id=123',        // 默认是当前页面,必须是以‘/’开头的完整路径
          imageUrl: '../../img/xiaochengxu-share.jpg',     //自定义图片路径,可以是本地文件路径、代码包文件路径或者网络图片路径,支持PNG及JPG,不传入 imageUrl 则使用默认截图。显示图片长宽比是 5:4
          success: function (res) {
              // 转发成功之后的回调
              if (res.errMsg == 'shareAppMessage:ok') {
              }
          },
          fail: function (res) {
              // 转发失败之后的回调
              if (res.errMsg == 'shareAppMessage:fail cancel') {
                  // 用户取消转发
                       console.log("用户取消转发");
              } else if (res.errMsg == 'shareAppMessage:fail') {
                  // 转发失败,其中 detail message 为详细失败信息
              }
          },
            complete: function(){
              // 转发结束之后的回调(转发成不成功都会执行)
          },
    };
    // 来自页面内的按钮的转发
    if(options.from == 'button') {
        var eData = options.target.dataset;
        console.log(eData.name);     // shareBtn
        // 此处可以修改 shareObj 中的内容
        //shareObj.path = '/pages/btnname/btnname?btn_name=' + eData.name;
    }
// 返回shareObj
return shareObj;
————————————————



微信小程序轮播功能

前端达人

<swiper indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" circular="{{duration}}" current="{{swiperCurrent}}" bindchange="swiperChange" class="swiper">

  <block wx:for="{{imgUrls}}" wx:key="unique">

    <swiper-item>

      <image src="{{item}}" class="img" bindtap="swipclick" />

    </swiper-item>

  </block>

</swiper>

————————————————


/* swiper {
    height: 421.5rpx;
} */
swiper-item image {
    width: 100%;
    height: 100%;
}
.swiper-container{
  width: 100%;
  position: relative;
}
.swiper-container .swiper{
  height: 300rpx;
}
.swiper-container .swiper .img{
  width: 100%;
  height: 100%;
}
————————————————


const app = getApp()
Page({
  data: {
    swiperCurrent: 0,
    indicatorDots: true,
    autoplay: true,
    interval: 3000,//自动切换时间间隔
    duration: 800,//滑动动画时长
    circular: true,//是否采用衔接滑动
    imgUrls: [
      '../../img/index/1.jpeg',
      '../../img/index/2.jpeg',
      '../../img/index/3.jpeg'
    ]
  },
  //轮播图的切换事件
  swiperChange: function (e) {
    this.setData({
      swiperCurrent: e.detail.current
    })
    //console.log(e.detail.current);
  },
  //点击指示点切换
  chuangEvent: function (e) {
    this.setData({
      swiperCurrent: e.currentTarget.id
    })
  },
  //点击图片触发事件
  swipclick: function (e) {
    console.log(this.data.swiperCurrent);
    wx.switchTab({
      url: this.data.links[this.data.swiperCurrent]
    })
  },
})
————————————————



真机预览本地页面方式-简单快捷(精简大法Node)

前端达人

前提:真机和PC端在同一个局域网内。

1、安装nodejs环境 (node -v 查看版本号)



2、在所在的项目下输入命令:npm install anywhere -g



3、直接输入命令:anywhere,这里浏览器自动打开所有项目的根目录,点击就可以看到,同一网段下,然后手机直接预览这个地址就可以

————————————————


小程序单张图片 和 九宫格图片上传、预览、删除示例

前端达人

<view class="gallery">

  <view class='tipTitle'>

    快去上传自己的照片吧

  </view>

  <view class='item-ot'>

    <view class="item">

      <!-- 添加按钮 -->

      <view class="addIcon" bindtap="chooseImage" wx:if="{{imgBoolean}}">

          <view class=''>+</view>

      </view>

      <!-- 上传的图 -->

      <view class='itemImg' >

        <image src="{{item}}" data-src="{{item}}" bindtap="previewImage"  mode="aspectFill" />

        <!-- 删除按钮 -->

        <view class="delete" bindtap="deleteImg" data-index="{{index}}">X</view>

      </view>

      <view class='boxStyle'></view>

    </view>

    <view class='itemTxt'>正面照</view>

  </view>

  <view class='uploadFinish'>

    <a class="uploadFinishBtn" href="javasctipt:;"  bindtap="submit">提  交</a>

  </view> 

</view>


/*画廊*/
.gallery {    
  width:100%;
  margin: 0 auto;
  display: flex;    
  justify-content: flex-start;    
  flex-wrap: wrap;
  background: #fffaf0;
}
/*每张图片所占容器*/
.item-ot{
  margin:0 auto;
  width: 100%;
  height: 100%;
}
.item {    
  position:relative;
  margin:0 auto;
  width:370rpx;
  height:490rpx;
  background:#eee;
  border:2rpx solid #f9c4c2;
  /* overflow:hidden; */
}
.itemImg{
  position: absolute;
  left: 0;
  top:0; 
  width: 100%;
  height: 100%;
  overflow: hidden;
  z-index:1;
}
.itemImg image{
  width: 100%;
  height: 100%;
}
/*add按钮*/
 .addIcon{
   position:absolute;
  left: 0;
  top: 0; 
  width: 100%;
  height: 100%;
  text-align:center;
  line-height:490rpx;
  font-size:80rpx;
  background: #fff;
  color: #999;
  z-index:2;
}
/*删除按钮*/
.delete {    
  position:absolute;
  right:0;
  top:0;
  /* background:#ccc; */
  opacity:1;
  height: 36rpx;
  font-size:22rpx;
  font-weight:700;
  padding:0 8rpx 0 10rpx;
  color: #999;
}
.itemTxt{
  text-align: center;
  font-size: 30rpx;
  color: #999;
  margin-top: 50rpx;
  margin-bottom:  70rpx;
  font-weight: 700;
}
.uploadFinish{
  width: 100%;
  height: 100%;
  padding: 0 30rpx;
  box-sizing: border-box;
}
.uploadFinishBtn{
  background: #ff6666;
  color: #fff;
  display: block;
  width: 100%;
  padding: 26rpx 0;
  text-align: center;
  font-size: 36rpx;
  border-radius: 10rpx;
  margin-bottom: 40rpx;
}
.tipTitle{
  text-align: center;
  font-size: 30rpx;
  color: #f6a29d;
  font-weight: 700;
  width: 100%;
  margin: 50rpx 0;
}
.boxStyle{
  width:300rpx;
  height:100rpx;
  position:absolute;
  bottom:-1rpx;
  border-radius:50%;
  box-shadow:0rpx 10rpx 100rpx #fddbd9;
  margin-left:35rpx;
}


Page({
  data: {
    uploadedImages: [],
    imgBoolean: true,
  },
  onLoad: function (options) {
    var that = this;
  },
  chooseImage: function () {
    var that = this;
    // 选择图片
    wx.chooseImage({
      count: 1, // 默认9
      sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
      sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
      success: function (res) {
        // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
        var tempFilePaths = res.tempFilePaths
        that.setData({
          item: tempFilePaths[0],
          imgBoolean: false
        });
      }
    })
  },
  // 图片预览
  previewImage: function (e) {
    var current = e.target.dataset.src
    wx.previewImage({
      current: current,
      urls: [current]
    })
    console.log("这是1" + current);
  },
  //删除图片
  deleteImg: function (e) {
    var that = this;
    var images = that.data.uploadedImages;
    that.setData({
      uploadedImages: images,
      imgBoolean: true
    });
  },
  // submit: function () {        

  // }, 
})


charts柱状图的X轴Y轴加单位的写法

前端达人

  •         {
  •             type : 'value',
  •             axisLabel:{formatter:'{value} %'}
  •         }
  •     ],

  • 如果想控制百分比最大到100% 可添加


  • yAxis : [
     
            {
                type : 'value',
                max:100,//Y轴最大值 不写的话自动调节
                axisLabel:{formatter:'{value} %'}
            }
     
        ],
    > max:100,//Y轴最大值 不写的话自动

  • table点击实现可编辑文本

    前端达人

    table点击实现可编辑文

    一个简单的例子,直接添加contentEditable=”true”标签属性即可

    <table>
        <tr>
            <td>姓名:</td>
            <td contentEditable="true"></td>
        </tr>
        <tr>
            <td>密码:</td>
            <td contentEditable="true"></td>
        </tr>
    </table>

    iPhone如何改变我们的交互方式

    雪涛

    当我们回顾近20年的手机发展历程,可以发现2007年iPhone的横空出世真正改变了手机这个行业。乔布斯在发布会上展示初代iPhone给行业带来的冲击力是前所未有的,对人机交互领域也带来了了深远的影响。



    从外观上来看,iPhone与那个时代手机最大的区别在于它舍弃了笨重的键盘,3.5英寸的全触控屏幕在当时来说可谓石破天惊。对于现在的手机来说,全触控屏幕可谓是标配。但是在当时来说面临着巨大的争议和风险。当时的微软CEO鲍尔默,也就是现在NBA快船队的老板就持反对意见,甚至苹果内部的高管都不看好全触控屏幕,因为他们觉得: “每个人都会对没有触摸感的东西感到不适”。

    这个理由现在看起来很无厘头,但是如果我们看待问题总是以现在的眼光和立场,那么就会产生“我上我也行”的错觉。这样的复盘,除了满足自己的YY欲,不会给我们的认知带来任何提升。


    我们来系统的分析一下,全触控屏幕究竟是怎么淘汰键盘的呢?首先最直观的一点就是,因为去掉了实体按键,那么手机的屏幕面积得到了提升。 此外,键盘交互的时代,条目的移动速度取决于手指点按键盘的速度。 而在触控交互的时代,移动条目只要手指滑动一下就可以了。 交互效率得到了指数级别的提升。



    信息限制


    而这里我想从可供性的角度来思考触控交互带来的体验提升。 可供性,通俗点说,就是功能隐喻。优秀的产品设计可以有效的利用功能隐喻让用户快速的明白如何操作。


    而隐喻不能太多,太多的隐喻等于没有隐喻。早期的战机有十几个姿态显示仪表和100多个操作按钮,这样的操作界面毫无隐喻而言,飞行员很难同时处理这么多信息。后来从三代机开始,战机舱普遍使用显示屏,化繁为简,限制了操作选项,降低了驾驶成本。

    在实体键盘时代,要限制操作选项是非常困难的。因为用户与手机进行交互是依赖键盘这个媒介,而键盘无法针对特定的场景提供定制化服务,例如我打电话拨号需要数字键,发短信需要26位字母键。那个时代音乐手机(诺基亚5300)甚至要将音乐按键放置在机身。


    一款产品可以给用户提供很多功能,但并不是每一个功能都是用户全程需要的。 只有判断在某个场景下,用户对特定功能的诉求很高,才展示相关的信息。 如果诉求很低,可以隐藏相关信息,避免给用户造成干扰。

    例如,在知乎中,你想搜索跟叶问相关的内容。在搜索结果页滑动了大概3屏左右,在界面底部会出现“向知友提问”的按钮。因为滑动了3屏,那么极有可能对当前的搜索结果不满意,这时引导用户去提问。如果从一开始就给用户展示去提问的按钮,那么对于不想提问的用户来说,其实是一种干扰,并且减少了阅读区域。


    在微博中停留3秒左右,就会提醒你去评论。在用户不断刷微博的状态下,一旦出现了停留,说明你被这条内容给吸引住了。与其每条微博下放一个评论框,还不如提醒你去评论感兴趣的内容。


    不同的场景,用户对功能的需求是不一样的,因此交互方案需要做出相应的调整。在有网的状态下,启动网易云音乐进入的是首页;无网情况下,启动网易云音乐进入的是我的音乐。因为用户在无网情况下进入网易云音乐,最大的可能性就是听之前下载好的歌曲。


    我们再来思考一个问题,为什么QQ的对讲功能是长按,而录音功能却是点击?录音与对讲最大的区别在于,录音完成后不会直接发送给对方。你可以听一下录音效果,感觉不错后再发送给对方。而对讲是说完之后直接就发送对方的。


    因此对讲功能更加看重效率,而且录音功能追求的是严谨。因为追求效率,用户对讲完成手指松开就可以直接发送了。如果使用点击,用户需要点击“发送”按钮才能发送,增加了操作步骤。


    目前很多电商平台支持语音搜索,用户可以直接说出商品名称进行搜索。京东采用长按的交互方式,长按说话,说完松开。而淘宝用的却是点击开始说话,说完自动发送。


    为什么淘宝这里做了差异化?这是因为,语音搜索商品,更多是短字符。用户在这里不太可能会说很长一段话,因此一旦用户的语音出现了中断,就可以判断已经完成了语音录入。交互流程就简化为点击开始录音,说完自动发送。

    操作与反馈


    我在前面提到了,全触控屏幕可以节省屏幕面积。这时可能会有人存在疑问,翻盖和滑盖手机不也能节省屏幕面积吗?

    所有的人机交互流程我们都可以简化为两个步骤: 操作与反馈。 按键手机,用户与手机进行交互都必须依赖键盘这个媒介,而反馈区在屏幕,你的视线需要不断的来回移动。全触控屏幕,用户可以跟屏幕中元素直接进行互动。视线可以集中在一点。


    即使在全触控屏幕,产品设计中操作区与反馈区的关系一样值得我们思考。以拍摄视频这个场景为例:

    目前抖音、快手和微博都支持用户分段拍摄视频,一个长视频可以由几段短视频拼接而成。这个就产生了一个新的场景,如果我对上一段视频不满意怎么办?


    我们先来看微博的处理方式,用户可以点击左边的关闭按钮,这时顶部的视频进度条开始闪烁。表明需要用户确定是否要删除这段视频?这种 通过闪烁和摇摆等不稳定状态来提醒用户进行决策的交互方式很常见,例如我们长按iPhone桌面图标,图标就会不断的抖动来询问是否要卸载该应用。

    这里存在一个问题, 触发区和反馈区距离太远,而且闪烁的样式不明显,首次使用的用户可能无法在短时间内快速的理解闪烁的进度条是在询问用户是否要删除该段视频。

    相比较而言,抖音的提醒方式更加直接,直接出现一个对话框。简单明了的询问用户是否要删除上一段视频,降低了用户的理解成本。当然抖音的交互方式也有缺点,对话框的出现增加了用户的操作成本。


    如果用户不想删除视频,抖音需要首先点击“取消”,关闭对话框,才可以进行后续流程。而微博用户取消删除,不需要任何操作,可以直接进行后续流程。


    如果用户“确定”要删除视频,抖音和微博用户的操作动作都是点击。但是微博用户手指不需要进行任何移动,等于是原地重复点击两次。所以我们无法判断双方孰好孰坏,只能说抖音的交互方式对新用户来说更加的友好。

    总结


    在做这期视频的时候,适逢微信新版本发布。其中一个改动点是,视频和图片查看界面的按钮都统一移到界面的底部。因为考虑到用户在单手握持手机的情况下,拇指很难直接够得着界面顶部。这样的改动可以方便用户操作。我看了一下反馈,发现持反对意见的较大,原因很简单:不习惯。


    做一款好产品,我们需要秉持着一颗尊重用户的态度。但是我不赞成把“用户当成上帝”的观点,大多数用户都是偏爱旧有模式的。即使你的改动从长期上来看,对他们来说是有益的,用户也会抗拒。因为他们看的永远都是当下的利益,因为你的改动我要离开我的舒适区,我要重新学习并适应新的交互模式了。人民创造了历史,但是人民本身也是创造历史的最大阻力。

    任何一个新事物的出现,人们总是倾向于从现有的知识体系中寻找类似的事物进行描述与概括,以寻求情感上的归属和理性上的辨识。但是过于超前的创新,往往是现有的知识体系无法解释的。无法解释,自然无法接受。


    文章来源:站酷

    日历

    链接

    blogger

    蓝蓝 http://www.lanlanwork.com

    存档