使用css及js自定义文件上传按钮 | 前端记录
前端记录 记录分享前端知识

使用css及js自定义文件上传按钮

CustomFileInputs1

目录

前言

本文主要是利用 <label> 跟js做一些按钮样式功能跟样式上的自定义。并考虑了兼容性、js禁用、浏览器bug。主要思路如下:

  • 隐藏 <input>
  • <label>定义样式充当上传按钮
  • 用 js 获得选定的文件名与数量

我们先来看一个单纯的 input :

smart-custom-file-input-1

接下来开始一步步优化这个文件选择按钮。

隐藏 Input

首先我们先把难看的输入框隐藏起来。注意这时是不能用 display: nonevisibility: hidden 的。理由是:这样做的话input 的值就无法通过 submit 发送到服务器,input 按钮也无法被 tab 键被选中。我们可以使用一些 css 属性隐藏 input 同时让它对浏览器是可见的:

这里解释下为什么把 widthheight 设置为 0.1px 而不是 0px,把宽高设成0的话在一些浏览器中会被排除在 tab 键选择之外。另外 position: absolute; 可以保证它不会影响周围元素。

给 Label 定义样式

主要就是让 <label> 看起来像个按钮,简单的写一下:

网页无障碍 Web Accessibility

为了让效果更友好,我们需要让按钮被选中时产生变化,以便让用户知道按钮被选中了。

我们先让鼠标覆盖到按钮上时变成小手:

smart-custom-file-input-2
smart-custom-file-input-3

键盘导航

某些用户只能使用键盘来操作页面,我们得让按钮被聚焦到时产生点变化表示被选中,以便这些用户操作。可以使用css选择器:

提示:-webkit-focus-ring-color auto 5px 可以在 Chrome, Opera 和 Safari 显示的像一个默认的外框线。在非 webkit 浏览器下则使用第一条 outline 规则。

smart-custom-file-input-4

可能出现的点击问题

如果你使用FastClick(一个用来处理移动端 click 事件300毫秒延迟的库)并且打算在 lable 里加一些标签,按钮可能就无法工作了。可以使用 pointer-events: none 来解决这个问题:

提示:pointer-events: none在解决点击穿透问题时还是很好用的,具体的相关介绍可以查看张鑫旭大神的这篇文章:CSS3 pointer-events:none应用举例及扩展

通过 JavaScript 改善

我们还需要能够显示选择了多少文件,input是能够做到这个的,但是我们已经把它给隐藏了。我们可以使用一点点 js 让 lable 的内容变成选择的文件名或数量。

再来个jQuery版的吧,现在也是很少有人用原生js了:

解释下 js 的几个点:

  • 添加 [multiple] 属性可以允许用户上传多个文件。
  • HTML 的 [multiple] 跟 JS 的 file 属性都是只支持现代浏览器,ie6、7、8都是不支持的。对于后一种情况,可以简单的使用 input 的值来改善。例如获得 input 的值是 C:\fakepath\filename.jpg ,可以使用 split( '\\' ).pop() 来提取文件名。
  • 在一些浏览器里可以使用 ESC 按键取消选择,这样input的值就会被重置。所以我们先定义了个变量 labelVallable 的默认值保存起来,以便使用。

smart-custom-file-input-5

如果 JavaScript 被禁用了怎么办?

我们在 css 里把 input 给隐藏掉了。所以在 js 被禁用时要更改下css样式。先给页面添加个 no-js 类名,如果 js 可用,就替换为 js 类名。以此来控制 input 的样式:

smart-custom-file-input-6

Firefox 浏览器的 bug

很出乎意料的是火狐浏览器会完全的忽略 input[type="file"]:focus 选择器,但是 :hover:active 却能正常选择。不过火狐浏览器允许在js里获取 focus 事件,所以在火狐浏览器里可以给 input 元素添加类名控制 focus 样式:

翻译完了,这里是原文地址,有兴趣的可以去看下。

文中的方法也可以用在单选框、复选框样式自定义上。关于兼容性、js禁用下、火狐浏览器bug都是平时没注意到的地方,以后可以注意下。

欢迎留言