【4Large-Style】前端框架设计——Button 的设计思路

Button 的设计


 

Button 作为基本的 Web 元素,看似简单,却需要非常用心的设计,因为 Button 作为按钮,是具有多个不同的状态,每种状态都基本上需要进行一些特殊的优化设计,以让组件更生动美观。

注:所有的长度单位均采用 rem 而非 px,需要在 html 标签下设定 font-size 的 CSS 样式,一般我都是设置:font-size:12px,1440 x 900 的分辨率,如果分辨率更高的话,可以自己调整。当然你改写成 px 作为度量衡也是 OK 的。

 Example: 

Default Inverse Primary Success Info Warning Danger

 Button的几种状态:

  我们设计 Button 的样式,基本按照以下几个状态来设计:

  1.   :focus - 当按钮获取焦点(可以是 JS 控制获取焦点,也可以是用 Tab 键一个一个切换从而获得焦点)
  2.   :hover - 当鼠标处于悬停状态时
  3.   :active - 当按钮处于点击状态时(按下但还没有放手的情况下)
  4.   :active:hover - 当按钮处于点击,且鼠标依然悬停的情况下(比如你按下去,但是鼠标还不放手,然后把鼠标拖拽着挪开按钮,此时就会出现这个状态的反例)
  5.   :active:focus - 当按钮处于点击且获取焦点的情况(这个情况的反例我也不知道反例应该怎么举)
  6.   正常状态,这我就不用解释了。
  7.   .focus - 通过 class 设置的获取焦点状态
  8.   .active - 通过 class 设置的点击状态

 

 Button 的状态变化

  我们先来梳理一下,Button 对应不同的动作,所产生的相应的变化。

  正常状态

    ┣ A:鼠标悬停 -> S:hover -> A:鼠标按下 -> S:active:hover/:active:focus(*) -> A:鼠标移开 -> S:active/:active:focus(*) ->A:鼠标松开 -> S:focus

    ┗ A:Tab 选中 -> S:focus -> A:空格按下 -> S:active:focus -> A:Tab 移开焦点 -> S:active -> A:空格松开 -> S:focus

  : A = Action , S = Status

  这边值得注意的是我打星号的位置:  A:鼠标按下 -> S:active:hover/:active:focus(*) -> A:鼠标移开 -> S:active/:active:focus(*) ,这个位置有点特别,不同的浏览器有不同的实现效果:

    •   Chrome:在 CSS 文件中,active:hover 跟 active:focus 定义的顺序会影响到上面这个步骤的实现,定义在后的会优先显示给用户(距离用户越近),比如给按钮定义了如下的 CSS 效果:
    •  1 .btn-default:active:focus {
       2     color: #000;
       3     background-color: #eeeeee;
       4     border-color: #000000;
       5 }
       6 
       7 .btn-default:active:hover,
       8 .btn-default.active:hover{
       9     color: #000;
      10     background-color: #e6e6e6;
      11     border-color: #000000;
      12 }

       那当我们按下鼠标的时候,看到的是 hover 的 CSS 效果,但是如果定义的顺序相反,鼠标按下以后,显示的是 active:focus 的 CSS 样式,如果是用空格键按下,也是这个规律,所以在 chrome 当中,鼠标按下(若键盘按下但是鼠标同时也悬停在上的话,情况也是一样),其实是有三个状态叠加而成,分别是 :active:hover+:active:focus+:active,当通过操作比如移除鼠标悬停再tab 键移除焦点(这些操作前提都是在鼠标按下或空格按下没松手的情况),那就会显示 active的样式,这一点弄明白了很重要。

    •   Safari:不存在上述优先顺序,空格键按下就是 active:focus,鼠标按下就是 active:hover,而且这两个状态是独立的,不会层叠覆盖,也就是说,在 safari 当中,只会有两个样式叠加,通过鼠标按下的就是 :active:hover+:active,通过键盘空格按下的,就是:active:focus+:active。
    •   其他浏览器我暂时还么有测试。

 

Button 基础样式


  我们首先要来设计一个基础的 Button 样式,我们可以这样子来做:

 1 .btn {
 2     display: inline-block; /*允许横排布局且支持设置宽高*/
 3     padding: 0.5rem 1rem; /*设置内边距,避免文字直接贴在边框上*/
 4     margin-bottom: 0; /*默认按钮是紧贴外部容器的底部*/
 5     font-size: 1.2rem; /*文字大小*/
 6     font-weight: normal; /*正常字体*/
 7     line-height: 1.42857143; /*设置行高*/
 8     text-align: center; /*文字居中*/
 9     white-space: nowrap; /*强制文本在一行显示,不允许换行*/
10     vertical-align: middle; /*垂直居中*/
11     cursor: pointer; /*设置鼠标悬停时的光标样式*/
12     background-image: none; /*不设置背景图*/
13     border: 0.1rem solid transparent; /*设置边框样式,但不设置颜色,颜色交由后续其他类来配合设置*/
14     border-radius: 0.5rem; /*圆角*/
15

  做了这些设置以后呢,我们的默认样式按钮就是这样子了: 

  然后我们再对 focus、hover 做一些设置: 

1 /*鼠标悬停*/
2 .btn:hover,
3 .btn.focus{
4     text-decoration: none;
5     -webkit-box-shadow: 0 0.2rem 0.2rem rgba(0, 0, 0, .525); /*下阴影(兼容)*/
6     box-shadow: 0 0.2rem 0.2rem rgba(0, 0, 0, .525); /*下阴影*/
7 }

  这样的效果是,当鼠标悬停增加一个下阴影,让按钮感觉是浮起来,等待你按下意思,本来我是不打算把.focus 放入的,希望跟:focus 保持一致,但是后来想一想,如果我们都主动的设置了 focus 这个类的话,肯定是希望它凸显的,而不加入:focus 是因为,当两个按钮并排的时候,点选一个按钮结束后会进入 :focus状态,此时按钮凸起,但是我如果想点击另一个按钮,鼠标移动到第二个按钮,第二个按钮也会凸起,这时候就有两个按钮同时凸起,然后当按下第二个按钮时由于第一个按钮会回到正常状态,正常状态下是不会有凸起而是平滑的,那两个按钮同时变化就会有两个按钮同时被按下的错觉,这种感觉就很不对了,而对于:focus 的状态而言,我们可以通过等会儿要讲的风格变化,通过颜色的变化凸显来解决:  

  接着还要对 :active(.active)、:active:focus、:active:hover 三个状态来做设置,设置一个内阴影,

/*鼠标按下且悬停、键盘空格按下且未松手*/
/*当空格按下没有松手,直接用tab键切换焦点后,被按下的组件将一直保持按下即:active状态*/
.btn:active:hover,
.btn:active:focus,
.btn:active,
.btn.active {
    background-image: none;
    -webkit-box-shadow: inset 0 0.2rem 0.2rem rgba(0, 0, 0, .525); /*内阴影(兼容)*/
    box-shadow: inset 0 0.2rem 0.2rem rgba(0, 0, 0, .525); /*内阴影*/
}

  能够给人一种“按钮被按下去”的感觉:

  我觉得这最需要做一个说明了,为啥 active:focus 要设置内阴影,而 focus 不用呢?因为前者代表的意思是通过点击后获取焦点,后者则并没有这条限制,所以当你用 Tab 键来让按钮获取焦点的时候,自然不能代表按钮被按下。所以要做一个区分。另外还有一点要做一个说明,那就是 active 也要做同样的设置,因为我们设置了 active:hover,会有一个问题,就是当我们按下并且鼠标悬停在按钮上的时候,才会有内阴影,但是如果此刻你鼠标不悬停,而是“拖拽”着让光标离开了这个按钮,为了要让按钮依旧保持被按下(因为你的鼠标此刻依旧处于按下的状态没松手),那 active 就要做相同的设置,否则按钮会回到最初的状态,那这样就没有被按下的那种直观感觉了。

  最后我们还要做一个基本设置:

1 /*去除键盘Tab选中、鼠标点击时的边框*/
2 .btn:focus,
3 .btn:active {
4     outline: 0;
5 }

  因为一些浏览器,会默认的加上这个属性,在你点击按钮时,会自动生成一个外边框,这个外边框我个人不喜,因为当我的组件是圆角矩形的时候,边框依旧还是直角矩形,这非常不好,超级难看,比如:

  outline 不能设置为圆角(除了火狐独有这个属性,但兼容性不好,所以不打算采用这个样式),网上我看到其他替代方案,是用 box-shadow 来模仿的,效果还可以,但是一个 box 只能有一个 shadow,这样就等于让我放弃使用 box-shadow 所以最后我还是不打算采用这种样式,感觉也不是很重要,就算没有 outline 也可以将按钮通过添加一些颜色来使其很醒目。

  同时我们增加了.focus 和.active 两个类样式,这样我们就可以通过设置 class 属性,来让我们的按钮主动的显示聚焦或点击的样式了。

  OK 了,这是最基本的样式设计,兼容性稳稳的,不论哪个浏览器,效果都是一样的。当你看到“基础”两个字的时候,就应该知道,咱们的文章,不可能就这么完了,那多没意思呀。

  现在 CSS 都流行使用嵌套或覆盖等手法,做一些多样性的扩展,我们当然也要追逐潮流啦。

 

 Button 的多样化:

  我们设计 Button 的基础模型,但是基础模型依旧还是很单调的,而且有很多状态其实是共用样式,如何让我们的按钮显得更加生动呢?这就是我们接下来要干的活了。

  我们设计出以下7种风格以供选择:

  1.   btn-default:
  2.   btn-inverse:
  3.   btn-primary:
  4.   btn-success:
  5.   btn-info:
  6.   btn-warning:
  7.   btn-danger:

  看着是不是很眼熟呀?没错,3-7的风格取名字是参照 Bootstrap 的,毕竟 Bootstrap 已经是非常流行的框架了,树立了一种标准,我们在设计样式表的时候,如果能保持一致,那使用者使用的时候,就会降低很多重复学习的门槛,用起来也比较方便,而我自己最后加了1个风格:btn-inverse,因为我个人是黑白党,很喜欢黑白风,而且有的场景使用这种比较严肃的配色也挺好。

Default Default


 

  我们已经定义了 Button 的基础样式,现在我们要定义的是风格状态,定义风格状态基本上只需要修改三个属性: 

    • color
    • background-color
    • border-color

  然后我们要根据之前说的,button 的不同状态,来进行编写,首先书写正常状态:

1 .btn-default {
2     color: #000;
3     background-color: #ffffff;
4     border-color: #000000;
5 }

  然后在设计当鼠标悬停或者 tab 选中时的效果,同时还要加入,当我们手动将按钮设置为 focus 状态或设置了 active 状态下的 focus 状态,来保持状态的一致性:

1 .btn-default:hover,
2 .btn-default:focus,
3 .btn-default.focus,
4 .btn-default.active:focus{
5     color: #000;
6     background-color: #ebebeb;
7     border-color: #000000;
8 }

  接下来就是比较需要细心的部分了,这部分 hover 和 focus 是有定义先后顺序的,我们来设置当按钮被按下后的样式:

 1 .btn-default:active:focus {
 2     color: #000;
 3     background-color: #eeeeee;
 4     border-color: #000000;
 5 }
 6 
 7 .btn-default:active:hover,
 8 .btn-default.active:hover{
 9     color: #000;
10     background-color: #e6e6e6;
11     border-color: #000000;
12 }
13 
14 .btn-default:active,
15 .btn-default.active {
16     color: #000;
17     background-color: #ffffff;
18     border-color: #000000;
19 }

  OK,最后效果就像这组按钮一样了,第二个是设置了active 状态,第三个是设置了 focus 状态。

Default Default Default

  好了,我们基本上是按照这个范式来设计不同的风格即可,只需要简单地调节一下颜色,基本上可以理解为按下的颜色为最“深”,鼠标有悬停比没悬停颜色更“深”,有焦点比没焦点颜色更“深”,正常状态下颜色最“浅”,这样的一个思维,再对比 Button 的不同状态来设计就行了,然后细节上再做一些调整,搭配出一个你最喜欢的。

  我们最后再来设计一个,比较特殊的,就是黑色的按钮(深色系按钮也可以参照这个逻辑):

Inverse  Inverse


  深色系跟浅色系设计师不同的,为什么呢?其实是因为我们设计的基础样式的原因,简单的说,我们基础样式里,阴影是黑色的,如果我们的按钮背景是黑色,那内阴影就看不到了,自然是没办法识别出按钮被按下的状态,这个想像一下就应该可以理解,所以我们要做一些调整。

.btn-inverse {
    color: #ffffff;
    background-color: #000000;
    border-color: #404040;
}

.btn-inverse:hover,
.btn-inverse:focus,
.btn-inverse.focus,
.btn-inverse.active:focus {
    color: #ffffff;
    background-color: #282828;
    border-color: #404040;
}

.btn-inverse:active:focus {
    color: #ffffff;
    background-color: #383838;
    border-color: #000000;
}

.btn-inverse:active:hover,
.btn-inverse.active:hover {
    color: #ffffff;
    background-color: #4d4d4d;
    border-color: #000000;
}

/*调整内阴影为白色,并且 Y 轴的位移改为"-"的,就是自下而上,内阴影的状态也添加了几种,大家可以自己去调试看看效果,就知道为什么要加了*/
.btn-inverse:active:hover,
.btn-inverse.active:hover,
.btn-inverse:active:focus,
.btn-inverse:active,
.btn-inverse.active {
    -webkit-box-shadow: inset 0 -0.2rem 0.2rem rgba(255, 255, 255, 0.52); /*内阴影(兼容)*/
    box-shadow: inset 0 -0.2rem 0.2rem rgba(255, 255, 255, 0.52); /*内阴影*/
}

.btn-inverse:active,
.btn-inverse.active {
    color: #ffffff;
    background-color: #232323;
    border-color: #000000;
}

  深色系的按钮组件基本可以参考这个模板来对色彩进行调配。值得关注的就是内阴影的状态多了几种,并且内阴影自身的属性有一些变化,具体如下:

Inverse Inverse Inverse

 

   其实这没有什么很厉害的东西,前端设计,关键在于一个思路,如何把复杂繁多的样式,通过一些抽象、分类的思想,逐渐的形成一个思路,再根据思路进行统一的,有条理的设计,这样就能够保持整体风格一致的情况下,灵活创建一些很棒的样式,CSS还有很多内容,一篇文章说不完,有心得朋友应该可以发现,我写的样式已经应用到了我的博客当中,我希望通过一点一点的努力,最终能够形成一套,属于自己的框架。

你可能感兴趣的:(【4Large-Style】前端框架设计——Button 的设计思路)