最近项目开发中遇到不少蛋疼的问题,每一个问题都可单独拿出来探讨,前端领域就是这样,浏览器对标准支持不一,国内IE市场仍有相当的占有率,无端的提高了开发和维护成本。

在本篇文章将来探讨placeholder这个属性,该属性是HTML5提出的一个属性,
占位符的属性值在用户录入数据时用来作为一个简短的提示。规范中明确指出占位符不应该用来代替<code>label</code>标签,如果有较长的描述,可以单独放置比较合适。W3C文档参考地址

占位符(placeholder),如果使用在M端,则不用考虑兼容问题,浏览器基本上都支持,但是PC端的支持情况却惨不忍睹,不用我提及都会想到万恶的IE吧。关于浏览器的支持情况看以参考placeholder浏览器支持,IE9及以下浏览器都不支持该属性。

从上述可以看出,像京东、QQ等大型互联网注册页面,没有使用placeholder,而是使用label或者label定位来添加描述的原因。

下面说说自己在PC端项目中采用placeholder遇到的问题以及处理方法(兼容IE8+及现代浏览器)。
问题一、placeholder设置文本颜色问题
解决方式:使用placeholder伪类或者伪元素,处理如下:

// Firefox 4-18
input:-moz-placeholder,
textarea:-moz-placeholder { 
  color: #f0f; 
} 
// Firefox 19+
//::-moz-placeholder 伪元素在Firefox 19+替代了之前的 :-moz-placeholder 伪类.
input::-moz-placeholder,
textarea::-moz-placeholder{
  color: #f0f; 
} 
// Internet Explorer 10+
// 经测试,现在这种写法在IE10+上设置没有反应,兼容性还有待探讨
:-ms-input-placeholder,
textarea:-ms-input-placeholder{
  color: #f0f; 
} 

// Safari and Chrome
// 必须加上元素标签,不然不生效
input::-webkit-input-placeholder,
textarea::-webkit-input-placeholder{ 
  color: #f0f; 
}

对于不支持设置placeholder文本颜色的浏览器,只能通过js脚本来控制了,将在问题二中一并处理。
问题二、placeholder多浏览器支持问题
解决方式:在不支持的浏览器中可以使用js脚本来统一处理,因IE不同版本支持情况各异,所以统一使用脚本处理,其它现代浏览器不用考虑。

// 判断当前是否是IE浏览器(IE6-11)
// 因IE6/7已做特殊处理,在此不再过滤。
if("ActiveXObject" in window){
  $('input[placeholder],textarea[placeholder]').each(function() {
    var $this = $(this),
        txt_placeholder = $this.attr('placeholder');

    if(this.type == 'hidden') return true;
    // 初始化值
    if($this.val() === '') {
      // 此处的txt-placeholder就是用来设置placeholder文本颜色的。
      $this.val(txt_placeholder).addClass('txt-placeholder');
    }

    $this.off('.placeholder');
    // 获得焦点事件
    $this.on('focus.placeholder', function() {
      if($this.val() === txt_placeholder) {
        $this.val('').removeClass('txt-placeholder');
      }
    })
    // 失去焦点事件
    .on('blur.placeholder', function() {
      if($this.val() === '') {
        $this.val(txt_placeholder).addClass('txt-placeholder');
      }
    });
  });
}

2015-07-20补充:

  1. 在IE中使用JS设置input[type=”password”]控件时,placeholder作为value值形式显示,默认为圆点!

  2. 在低版本IE浏览器中不建议使用placeholder,可以使用label定位来代替。下面是IE8/9中对password做的兼容及特殊处理:

        if("ActiveXObject" in window){
         $('input[placeholder],textarea[placeholder]').each(function() {
             var $this = $(this),
                     type = this.type,
                     isPassword = type == 'password'
                     ie89 = IE_Version == 8.0 || IE_Version == 9.0,
                     txt_placeholder = $this.attr('placeholder');
    
             if(type == 'hidden') return true;
    
             if($this.val() === '') {
                 if(isPassword) {
                     if(ie89) {
                         $this.prev('label').show();
                     }
                 }else {
                     $this.val(txt_placeholder).addClass('txt-placeholder');
                 }
             }
    
             $this.off('.placeholder');
             $this.on('focus.placeholder', function() {
                 var txt_placeholder = $this.attr('placeholder');
                 if(isPassword) {
                     if(ie89) {
                         $this.prev('label').hide();
                     }
                 }else {
                     if($this.val() === txt_placeholder) {
                         $this.val('').removeClass('txt-placeholder');
                     }
                 }
             }).on('blur.placeholder', function() {
                 var txt_placeholder = $this.attr('placeholder');
                 if($this.val() === '') {
                     if(isPassword) {
                         if(ie89) {
                             $this.prev('label').show();
                         }
                     }else {
                         $this.val(txt_placeholder).addClass('txt-placeholder');
                     }
                 }
             });
         });
     }

    问题三、placeholder兼容性方案和validate.js插件校验融合问题

解决方式:如果你的validate.js插件通过input/change/propertychange/foucus/blur等事件来处理的,在IE浏览器中需要增加针对解决问题二的特殊过滤,即:
如果该input控件为必填项,校验是需做如下处理:

// IE支持placholder 兼容
var isIE = "ActiveXObject" in window;
if(isIE && $zt.attr('placeholder')  === value) {
  value = '';
}

如果是绑定propertychange事件,因为在IE中JS赋值也会触发propertychange事件,所以需要增加如下过滤:

if(value === $zt.attr('placeholder')) return;

以免placeholder赋值给value时会进行校验。如果想链接propertychange事件相关情况可以查看文章:实时监听输入框值变化的兼容性方案

当然前端市场上,也有一些javascript ployfill,来解决部分浏览器无法支持的情况。例如:
1.Placeholders.js
Placeholders.js is a JavaScript polyfill for the HTML5 placeholder attribute. It’s lightweight, has zero dependencies and works in pretty much any browser you can imagine.
2.jquery.input-placeholder-polyfill.js
3.jquery-placeholder
看了下上述的源码,从技术层面看,与上述实现方式大同小异。仅供读者参考。

问题四、从产品层面上看,当用户输入文字时,placeholder文本描述就消失了,这个用户体验有点不妥
解决方式:Google了下,还有真有解决该问题的案例,国外技术发展就是快哈,不能不佩服哈~~。但是此种方案要想在国内实现,只能使用JS来写了,CSS写光浏览器支持问题就可以直接pass掉了。附上地址供大家观摩adaptive-placeholders

转载申请

本作品采用知识共享署名 4.0 国际许可协议进行许可,转载时请注明原文链接,文章内图片请保留全部内容。