CSS

css的艺术

用户体验篇

Posted by XX on August 30, 2019

web前端优化有很多技术层面,本文主要总结在web开发过程中,如何在css层面优化用户体验,需要注意的是,css的优化效果往往是立竿见影的.

1.选用合适的鼠标光标

难题

鼠标指针的用途不仅在于显示鼠标在屏幕上的位置,还可以告诉用户当前可以执行什么动作。这在桌面应用程序中是十分普遍的用户体验实践,但在网页应用中却往往被忽视。

用户体验0.png

解决方案

  1. 提示禁用状态

    这种情况虽然用的很多,但是大多数表单组件已经被封装好了禁用状态,所以我们并不需要特别关心禁用状态

    :disabled{
      cursor: not-allowed;
    }
    
  2. 提示可点击状态

    有时候我们不免要自己写一些按钮或者区域是可点击的.

    cursor: pointer;
    
  3. 禁用文字选中

    很多情况下,一些现成的框架组件都忽视了这一情况,比如按钮里的文字,树形结构里的文字,tab页面标签的文字,menu菜单里的文字,并没有禁用文字选中,实际上会严重影响用户的体验和视觉效果

    user-select: none;
    
  4. 恢复默认鼠标样式

    有些情况一些特殊组件(带有特定鼠标手势的组件),我们并不需要他提供特殊的鼠标样式,这时候我们可以重置鼠标样式

    cursor:default
    
  5. 提示可移动组件

    如果一些组件是可以拖拽移动的,一定要给鼠标加上移动提示

    cursor:move
    

2. 扩大可点击区域

用户体验2.png

难题

对于那些较小的、难以瞄准的控件来说,如果不能把它的视觉尺寸直接放大,将其可点击区域(热区)向外扩张往往也可以带来可用性的提升。随着触屏的不断普及,这一点变得愈发重要。没有人愿意对一个狭小的按钮尝试点按很多次,但实际上这样的无奈之举仍然每天都在发生。

还有一些时候,我们想让某个元素在鼠标接近窗口某侧时自动滑入。举个例子,一个自动隐藏的页头会在鼠标接近时自动从顶部滑入并完整展现,这也涉及(只在单一方向上)放大热区的问题。只借助纯 CSS 可以做到这一点?

解决方案

  1. 利用元素边框

    扩张热区最简单的办法是为它设置一圈透明边框,因为鼠标对元素边框的交互也会触发鼠标事件,这一点是描边和投影所不及的。

    border: 10px solid transparent;
    background-clip: padding-box;
    
  2. 边框会影响布局,而且在某些场景下我们可能根本无法利用边框。那该怎么改进呢?我们放弃边框,然后改

    用另外一个特性来实现:伪元素同样可以代表其宿主元素来响应鼠标交互。

    button {
    	position: relative;
     /* [其余样式] */
    }
    button::before {
    	content: '';
      position: absolute;
      top: -10px; right: -10px;
      bottom: -10px; left: -10px;
    }
    

3. 遮罩层的体验优化

难题

通过半透明遮罩层调暗并弱化页面背景的方法,如果背景页面中包含很多内容的话,只有将其调到很暗的程度,才能为背景之上的文本提供足够的对比度,才能把用户 的注意力引导到弹出层上。还有另外一种更加优雅的方法,就是把关键元素之外的一切都模糊掉,用来配合(或取代)阴影效果,这效果的真实感更强,因为它营造出了“景深效果”:当我们的视线聚焦在距离较近的物体上时,远处的背景就是虚化的。

用户体验3.png

解决方案

把页面中的主要内容标记出来(对话框通常都不是主要内容),同时还给了我们添加样式的钩子。结构代码基本上如下所示

<main>Bacon Ipsum dolor sit amet...</main>
<dialog>
  O HAI, I'm a dialog. Click on me to dismiss.
</dialog>
<!-- 其他对话框都写在这里 -->

它并没有配备遮罩层。接下来,每当弹出一个对话框,都需要给 <main> 元素增加一个类,以便对它应用模糊滤镜:

main.de-emphasized {
 filter: blur(5px);
}

这已经是一个巨大的进步了。不过,现在这个模糊效果是突然出现的,看起来不是那么自然,反而给人一种突兀的感觉,由于 CSS 滤镜是可以设置动画的,我们可以让页面背景的模糊过程以过渡动画的形式来呈现。

main {
  transition: .6s filter;
}

4. 弹性过渡

用户体验4.png

假设有一个文本输入框,每当它被聚焦时,都需要展示一个提示框。这个提示框用来向用户提供帮助信息,比如字段值的正确格式等。结构代码可能是这样的:

<label>
  Your username: <input id="username" />
<span class="callout">Only letters, numbers,
  underscores (_) and hyphens (-) allowed!</span>
</label>

触发这个提示框(.callout)所需要的 CSS 代码如下所示(我们在里略去了具体的外观和布局样式):

input:not(:focus) + .callout {
transform: scale(0);
}.callout {
transition: .5s transform;
transform-origin: 1.4em -.4em; }

当用户聚焦到这个文本输入框时,会有一个半秒钟的过渡。这个过渡没有什么问题,但如果它在结尾时能再夸张一点的 话,会显得更加自然和生动(比如说,先扩大到 110% 的尺寸,然后再缩回100%)。

动画实现

@keyframes elastic-grow {
  from { transform: scale(0);
  }
  70% {
  transform: scale(1.1);
  animation-timing-function:
    cubic-bezier(.1,.25,1,.25); /* 反向的ease */
	}
}
input:not(:focus) + .callout { transform: scale(0); }
input:focus + .callout { animation: elastic-grow .5s; }
.callout { transform-origin: 1.4em -.4em; }

更简单的过渡实现

input:not(:focus) + .callout { transform: scale(0); }
.callout {
transform-origin: 1.4em -.4em;
transition: .5s cubic-bezier(.25,.1,.3,1.5);
}

当弹框关闭时

调整cubic-bezier函数和动画时间

input:not(:focus) + .callout {
  transform: scale(0);
  transition: .25s;
}
.callout {
  transform-origin: 1.4em -.4em;
  transition: .5s cubic-bezier(.25,.1,.3,1.5);
}