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 效果:
    •  .btn-default:active:focus {
           color: #000;
           background-color: #eeeeee;
           border-color: #000000;
       }
      
       .btn-default:active:hover,
       .btn-default.active:hover{
           color: #000;
           background-color: #e6e6e6;
           border-color: #000000;
       }

      那当我们按下鼠标的时候,看到的是 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 样式,我们可以这样子来做:

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

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

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

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

  这样的效果是,当鼠标悬停增加一个下阴影,让按钮感觉是浮起来,等待你按下意思,本来我是不打算把.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 就要做相同的设置,否则按钮会回到最初的状态,那这样就没有被按下的那种直观感觉了。

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

 /*去除键盘Tab选中、鼠标点击时的边框*/
 .btn:focus,
 .btn:active {
 ;
 }

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

  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 已经是非常流行的框架了,树立了一种标准,我们在设计样式表的时候,如果能保持一致,那使用者使用的时候,就会降低很多重复学习的门槛,用起来也比较方便,而我自己最后加了2个风格:btn-white&btn-black,因为我个人是黑白党,很喜欢黑白风,而且有的场景使用这种比较严肃的配色也挺好。

Default Default


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

    • color
    • background-color
    • border-color

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

 .btn-default {
     color: #000;
     background-color: #ffffff;
     border-color: #000000;
 }

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

 .btn-default:hover,
 .btn-default:focus,
 .btn-default.focus,
 .btn-default.active:focus{
     color: #000;
     background-color: #ebebeb;
     border-color: #000000;
 }

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

 .btn-default:active:focus {
     color: #000;
     background-color: #eeeeee;
     border-color: #000000;
 }

 .btn-default:active:hover,
 .btn-default.active:hover{
     color: #000;
     background-color: #e6e6e6;
     border-color: #000000;
 }

 .btn-default:active,
 .btn-default.active {
     color: #000;
     background-color: #ffffff;
     border-color: #000000;
 }

  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 的设计思路的更多相关文章

  1. Semantic UI 语义化设计的前端框架

    UI是Web的灵魂!Semantic UI是一款语义化设计的前端框架,为攻城师而制作的可复用的开源前端框架. 特性 弃用有歧义的表述 Semantic是围绕自然交流语言而架构的,这使得开发更加直观(易 ...

  2. 合理使用CSS框架,加速UI设计进程

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://dzone.com/articles/how-to-speed-up-your-d ...

  3. AI框架精要:设计思想

    AI框架精要:设计思想 本文主要介绍飞桨paddle平台的底层设计思想,可以帮助用户理解飞桨paddle框架的运作过程,以便于在实际业务需求中,更好的完成模型代码编写与调试及飞桨paddle框架的二次 ...

  4. 游戏UI框架设计(一) : 架构设计理论篇

    游戏UI框架设计(一) ---架构设计理论篇 前几天(2017年2月)看到一篇文章,国内王健林.马云等大咖们看好的未来十大最有"钱途"产业中,排名第一的就是"泛娱乐&qu ...

  5. Robot Framework测试框架用例脚本设计方法

    Robot Framework介绍 Robot Framework是一个通用的关键字驱动自动化测试框架.测试用例以HTML,纯文本或TSV(制表符分隔的一系列值)文件存储.通过测试库中实现的关键字驱动 ...

  6. .net core +codefirst(.net core 基础入门,适合这方面的小白阅读) 【我们一起写框架】领域驱动设计的CodeFirst框架(一)—序篇

    .net core +codefirst(.net core 基础入门,适合这方面的小白阅读)   前言 .net core mvc和 .net mvc开发很相似,比如 视图-模型-控制器结构.所以. ...

  7. atitit.atiOrmStoreService 框架的原理与设计 part1  概述与新特性

    atitit.atiOrmStoreService 框架的原理与设计 part1  概述与新特性 1. 新特性如下 支持生成sql在无数据库连接的情况下 2. Orm设计 主要的俩个以来service ...

  8. 前端项目课程7 banner设计注意事项

    前端项目课程7 banner设计注意事项 一.总结 一句话总结: 1.每个部分的里面的部分可以用相同的名字么,如何修改样式呢? 可以, 用模块名 + 比如上中下(top middle bottom) ...

  9. App自动化测试框架学习探索--从零开始设计

    App自动化测试框架学习探索--从零开始设计---持续更新中,敬请关注 1 批量执行app自动化测试使用多线程设计思路: 1)并发级别选择用methods 2)采用@Test多线程,数据提供类dp单线 ...

随机推荐

  1. express4.x中路由中间件和挂载路径的关系

    express4.x 中一个路由中间件可以挂载到多个路由上,一个路由也可以绑定多个路由中间件,如: //多个路由匹配一个路由中间件 app.use(['/gre+t', '/hel{2}o'], gr ...

  2. [FTP]xferlog日志解析

    [root@teacher ~]# cat /var/log/xferlogMon Jan 25 20:41:39 2016 1 10.0.222.156 913268 /sys/sys64/Pack ...

  3. PHP运行方式

    原文链接:http://www.cnblogs.com/xia520pi/p/3914964.html 1.运行模式 关于PHP目前比较常见的五大运行模式: 1)CGI(通用网关接口 / Common ...

  4. Spark 的combineByKey函数

    在Spark中有许多聚类操作是基于combineByKey的,例如group那个家族的操作等.所以combineByKey这个函数也是比较重要,所以下午花了点时间看来下这个函数.也参考了http:// ...

  5. PC端 H5实现拍照并上传

    <!DOCTYPE HTML><html><head> <meta charset="UTF-8"> <meta name=& ...

  6. MQ-2烟雾传感器启动

    MQ-2气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2).当传感器所处环境中 存在可燃气体时,传感器的电导率随空气中可燃气体浓度的增加而增大.使用简单的电路即可将电导率的 变化 ...

  7. MVC 5学习总结笔记1

    01.使用MVC自带的DataAnnotations实现数据验证 public class ExternalLoginConfirmationViewModel { [Required] [Displ ...

  8. java线程 — 创建和启动线程

    创建和启动线程,传统有两种方式: 方式1:继承Thread类: 方式2:实现Runnable接口: 线程类(java.lang.Thread):Thread类和Thread的子类才能称之为线程类.阅读 ...

  9. IOS开发-UI学习-NSBundle和NSURL的区别(读取文件以及写入文件)

    NSBundle和NSURL的区别: 在项目的工程中添加一个文件,本例程添加的是aa.txt,文件的内容为百度: www.baidu.com,现在要使用NSBundle和NSURL分别去获取内容,代码 ...

  10. PowerShell学习小结

    1. 获取所有别名信息Get-Alias 2. 获取指定别名信息Get-Alias xx 3. 通过command name获得指定别名信息Get-Alias -Definition xx-xxx 4 ...