input file 的美化

input file 的美化原文链接:Styling&CustomizingFileInputstheSmartWay(作者:OsvaldasValutis)这份教程主要介绍如何将与配合、以保持语义化+可访问性为目标辅以少量Javascript来美化。实例网上流传过一些“自定义”元素的方法,试验过但都实现不了像Readerrr上那种上传文件即时显示到内容流里的效果。兴许最烂

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

原文链接:Styling & Customizing File Inputs the Smart Way(作者:Osvaldas Valutis)

这份教程主要介绍如何将<input type=”file” />与<label>配合、以保持语义化+可访问性为目标辅以少量Javascript来美化。

input file 的美化

实例

网上流传过一些“自定义”<input type="file" />元素的方法,试验过但都实现不了像Readerrr上那种上传文件即时显示到内容流里的效果。兴许最烂的做法是:把input直接放进模拟按钮的容器、100%大填满容器、点击容器的任意区域即等于点击input。听起来可行但实际又比较奇怪对吧?并且实际上这样做也会带来一些不可接受的缺失,比如可用性、比如对touch事件的支持等等。

后来我在StackOverflow网站上发现一条隐藏得很深的灵感,有些人顶它但是被淹没在该主题的回复里。这条回复的重点只有一个——<label>!好用在于,它可以跟input的click事件关联上,这就实现了语义化解决方案。

<input type="file" name="file" id="file" class="inputfile" /> <label for="file">Choose a file</label> 

因此点击这两个元素的任何一个都能得到相同的结果——弹出文件上传选择对话框。这意味着最难的部分解决了。没有JavaScript,不需要其他比如捕捉鼠标位置之类的麻烦方案,只需要两行代码。如图:

input file 的美化

上传效果

现在剩下的工作就是将它当成一个普通按钮来尽情美化。

隐藏<input>

首先,部分CSS属性对隐藏<input type="file" />无效

display: none;
visibility: hidden;

原因是:这样做之后input将不能提交数据,也会被tab顺序跳过(键盘可用性一下子就完蛋了)。为了完美实现视觉不可见但浏览器可辨认,我测试出了这样的CSS组合:

.inputfile { width: 0.1px; height: 0.1px; opacity: 0; overflow: hidden; position: absolute; z-index: -1; } 

你可能会好奇为什么宽和高会设成0.1px而不是0px,因为在某些浏览器下0宽高将会让<input>元素被tab键忽略。而position: absolute的目的是不干扰随后元素的位置。

美化<label>

对<label>的修饰就随意了,先来几行简单的效果:

.inputfile + label { font-size: 1.25em; font-weight: 700; color: white; background-color: black; display: inline-block; } .inputfile:focus + label, .inputfile + label:hover { background-color: red; } 
input file 的美化

效果

可用性

一个用户要如何知道网页上的某个元素是“可点”?首先它要传达出一种可摁或者可点的暗示;其次hover时光标应该直接体现。而<label>默认没有变小手的效果,那么加上:

input file 的美化

input file 的美化

键盘导航

如果用户不能使用键盘访问到这个按钮,设计就失败了。除了做到优雅隐藏外,还应该在focus状态时有所反馈:

.inputfile:focus + label { outline: 1px dotted #000; outline: -webkit-focus-ring-color auto 5px; } 

-webkit-focus-ring-color auto 5px是Chrome/Opera/Safari上的一个默认支持的小技巧。

input file 的美化

Touch事件上可能存在的问题

如果你正在使用FastClick(一个消除可触屏上的300毫秒反馈延迟的库)之类的东西,并且想对label增加一些额外属性,按钮有可能出现问题,这时候就需要加上:

pointer-events: none;

JavaScript辅助

最后还不能忘记一件事:判断文件是否已选中<input type="file" />既然已经被隐藏,你就看不到选上了的文件名。这个时候就只能再依赖一小段JavaScript,使<label>的文本显示为选中的文件名。如果有多个文件被选中,文本还应该显示出文件总数。
<input type="file" name="file" id="file" class="inputfile" data-multiple-caption="{count} files selected" multiple />

var inputs = document.querySelectorAll( '.inputfile' ); Array.prototype.forEach.call( inputs, function( input ) { var label = input.nextElementSibling, labelVal = label.innerHTML; input.addEventListener( 'change', function( e ) { var fileName = ''; if( this.files && this.files.length > 1 ) fileName = ( this.getAttribute( 'data-multiple-caption' ) || '' ).replace( '{count}', this.files.length ); else fileName = e.target.value.split( '\\' ).pop(); if( fileName ) label.querySelector( 'span' ).innerHTML = fileName; else label.innerHTML = labelVal; }); }); 

jQuery的话:

$( '.inputfile' ).each( function() { var $input = $( this ), $label = $input.next( 'label' ), labelVal = $label.html(); $input.on( 'change', function( e ) { var fileName = ''; if( this.files && this.files.length > 1 ) fileName = ( this.getAttribute( 'data-multiple-caption' ) || '' ).replace( '{count}', this.files.length ); else if( e.target.value ) fileName = e.target.value.split( '\\' ).pop(); if( fileName ) $label.find( 'span' ).html( fileName ); else $label.html( labelVal ); }); }); 

部分解释:

  • 保留原生[multiple]特性允许一次上传多个文件,而[data-multiple-caption]是自定义特性,用于显示被选中的文件数,同时也可以设置自定义文本。{count}则是可选项,文件数将显示在内部。没有使用JS变量而是直接增加HTML特性的目的是,后者在同一页内多次使用时比较便利。
  • [multiple]在IE9及以下不被支持,也不属于JavaScript的原生files属性。对于后者,我们可以简单地使用value(值),比如c:\path\filename.jpg这样的路径,split( '\\' ).pop()就能一步到位获取到文件名。
  • 有个有趣的细节:在弹出文件选择对话框后你可以摁ESC键重设/清空input的值,虽然有可能限于Chrome/Opera。因此设计出labelVal这个变量来装这个值,并且随时回头利用。

效果如图:

input file 的美化

如果不支持JavaScript怎么办?

鉴于没有JavaScript以外的方式能获取文件是否选中的状态,最好的办法就是依赖<input type="file" />的原生外观。只需要对<html>增加一个.no-js的class名,再用JS去改变为.js——以辨识出JS是否得到支持。

<html class="no-js">
    <head>
        <!-- remove this if you use Modernizr -->
        <script> (function(e,t,n) { var r=e.querySelectorAll("html")[0]; r.className=r.className.replace(/(^|\s)no-js(\s|$)/,"$1js$2") })(document,window,0); </script>
    </head>
</html>

CSS相应为:

.js .inputfile { width: 0.1px; height: 0.1px; opacity: 0; overflow: hidden; position: absolute; z-index: -1; } .no-js .inputfile + label { display: none; } 
input file 的美化

Firefox bug

可能大家都没想到,Firefox完全忽略input[type="file"]:focus这样的定义,却完美支持:hover:active!更意外的是,Firefox竟然支持在JavaScript里获取焦点,因此解决方法就是多加两行:

input.addEventListener( 'focus', function() { input.classList.add( 'has-focus' ); }); input.addEventListener( 'blur', function() { input.classList.remove( 'has-focus' ); }); 
.inputfile:focus + label, .inputfile.has-focus + label { outline: 1px dotted #000; outline: -webkit-focus-ring-color auto 5px; } 

DEMO:http://tympanus.net/Tutorials/CustomFileInputs/
打包下载:http://tympanus.net/Tutorials/CustomFileInputs/CustomFileInputs.zip

题外话

有用户指出这样实现的上传按钮无法通过拖拽的方式来上传——毕竟这是<input type=”file” />的原生功能。有人建议可以辅用Plupload或者Dropzone.js之类的插件,但此人反驳道本来就支持的功能现在失去了,再找其他东西来修补是一种脱裤放屁的行为。楼主回复认为,上传按钮的拖拽支持本来就非常隐蔽,并不是明面上可见的功能,除了一些习惯泡在网上的技术男,绝大部分普通用户看到一个形象的上传按钮时肯定是点击它而不是往上面拖文件。


除了设宽高为0,有人给出隐藏input但不让它失效的其他方法:

input { position: absolute; opacity: 0.01; } 

也就是把透明度设为一个极小的值。目前未测试不确定适用范围(该人声称已在其公司的项目里广泛应用)。


还有一些人提出一个比较常见的理解:

input { position: absolute; width: 容器宽; height: 容器高; opacity: 0; user-select: none; } 

透明度为0,同时不允许被选中,绝对定位覆盖填满容器,然后点击的时候就肯定点击在input上。看似很好理解并且实现简单,但作者指出在IE10及以下这种做法可能导致双击才能生效:在线测试


进而有人提出需求:如果还能清除选中的文件名就好了。作者链接到另一个StackOverflow上的帖子,那边有人问如何用jQuery清空<input type="file" />的值,因为这样做无效:

$('#control').attr({ value: '' }); 

那边帖子有一个顶得最高的解决方法,颇为巧妙:

function resetFormElement(e) { e.wrap('<form>').closest('form').get(0).reset(); e.unwrap(); // Prevent form submission e.stopPropagation(); e.preventDefault(); } 

具体做法就是产生一个外包<form>,然后原生reset掉其内的<input>,再去掉这个外壳。最后添加preventDefault的目的是,假如表单里存在一个触发reset的button,这样做可以避免上面的JS触发它。


也有人提出把<input>放在<label>里,显得更天然更合理:

<label class="upload"> Choose a file... <input type="file" /> </label> 

但作者指出如果需要捕捉<input>是否有:focus就只能依赖JS了,因此在楼例里作者把<label>放在<input>后面,利用CSSinput + label去选择到它。


最后有人提出如果动态添加多个<input type="file" />,以上的方法就不够全面,希望作者能给出一个思路,到目前为止作者没有回复。

作者:QIQIBIBI

链接:https://www.jianshu.com/p/07c27e576b26

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/160955.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 工作量证明(PoW)的内部攻击模型「建议收藏」

    工作量证明(PoW)的内部攻击模型「建议收藏」虽然,POW算法其实并没有协调选择博弈论中的安全性,因为多数联盟可以形成和有益的审查和回复块。但是当我们考虑PoW的攻击时,通常不会考虑到矿工联合攻击,而是想到购买矿工设备或者对更重链进行挖矿。这篇文章主要是谈论PoW对抗控制半数哈希力攻击的能力,不允许租用,或贿赂矿工,或与矿工进行任何其他形式的合作。外部攻击外部攻击者购买足够的GPU或者ASIC直到完成对可信网络的“51%攻击”,或者至少…

  • gis可视化的方法_gis可视化分析

    gis可视化的方法_gis可视化分析前言从去年开始无脑接触Cesium三维GIS可视化,入坑之后一直到到现在,其实已经写了多个项目了,中间也遇到了很多坑点,很早就想分享其中所获了,只是觉得不太专业而且没有太多时间,…

  • R、RStudio下载与安装方法

    R、RStudio下载与安装方法现如今,R语言是统计领域广泛使用的工具,是属于GNU系统的一个自由、免费、源代码开放的软件,是用于统计计算和统计绘图的优秀工具。而RStudio是R的集成开发环境,用它进行R编程的学习和实践会更加轻松和方便。下面就教大家如何下载并安装R和RStudio,比较简单。R的维护工作由一个国际化的开发者团队负责。R软件的官方下载页面叫作TheComprehensiveRArchiveNetwor…

  • mybatishelperpro激活码_在线激活

    (mybatishelperpro激活码)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html2K…

  • snmptrap报文_snmp指定发送IP

    snmptrap报文_snmp指定发送IP#/bin/shOidWarnHead=1.3.6.1.4.1.53151.2.15.4.1targetIp=172.16.101.34targetPort=162trapOid=1.3.6.1.4.1.53151.3.1warnIdOid=${OidWarnHead}.1.0warnIdVal=1500000200warnSnOid=${OidWarnHead}.2.0…

  • 有关软件设计师的报名问题及答案_软件设计师软考

    有关软件设计师的报名问题及答案_软件设计师软考下面是青岛人才市场的联系地址和电话 青岛市中高级人才市场海尔路178号889166728891667088916679 中国青岛人才大市场山东路171号856329738564389885636580 贵州路人才市场贵州路69号一楼咨询:82685619 城阳人才市场(人才交流中心)城阳正阳路222号87868756 胶南市人才交流服务中心新华路8

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号