使用 label 标签 解决 IE10 以下 input 的 placeholder 不显示问题
IE 是前端一生的夙敌
问题引出
没人不认识这个把:
<input name="username" placeholder="请输入用户名" />
就一个输入框,然后没输入值情况下显示 请输入用户名
偏偏 IE10 以下就不认识 placeholder 兼容性
我真是,惊呆了。。。
冷静分析
采用 <label></label>
标签
为何?
我们需要把文字,用定位的方式定在输入框上,可是又不能挡住 input 的聚焦,所以不论是普通的 div 还是伪元素
都不行
- 而 label 标签有一个
for
属性,点击的时候可以触发对应的组件 - input 不支持伪元素,所以就算用伪元素写,也是写在父级 div
撸码解决
html 结构
先确定下 html。既然要用定位,那我们还是给 input 多包裹一层 div。正常 input 也会有 div 包裹了~
由于我们要解决的只是 IE 的问题,所以 label
默认不写,通过 js 来动态添加
<div class="form-item user-name">
<input name="username" placeholder="请输入用户名" />
</div>
css 样式
label-placeholder
是将要动态添加的 label 的样式
还用到了 css 的兄弟选择器(+)
用于控制输入框获得焦点后,lable 隐藏
.form-item {
position: relative;
}
.label-placeholder {
position: absolute;
top: 0;
bottom: 0;
left: 28px;
font-size: 14px;
text-align: left;
z-index: 10;
color: #999;
}
/* input聚焦的时候,lable自动隐藏 */
.form-item input:focus + .label-placeholder {
display: none;
}
重头戏 JS
-
initPlaceholder
- 这里采用闭包,避免多次创建的时候还要重复判断 IE 版本
- 其次尽量减少全局变量的使用,避免造成污染
-
window.onload
- 所有的操作在 dom 节点挂载后才操作
-
只有 IE 6-9 的版本才使用
initPlaceholder
方法主要接收一个对象,其中对象包含 targetId
,placeholder
,blur
分别对应 input 的 id 属性,要显示的 placeholder
和 失去焦点的方法
这里必须要通过 ID 传递,因为 lable 的 for 标签只认 ID 属性
接下来,JS 封装好了,要用的时候就是调用 initPlaceholder
方法,然后自动判断版本,如果非 IE,或者非 IE6-9 版本的,直接用浏览器的功能,不过还是注册上了 blur
事件
var initPlaceholder = (function() {
var userAgent = navigator.userAgent //取得浏览器的userAgent字符串
var isIE = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1 //判断是否IE<11浏览器
var reIE = new RegExp('MSIE (\\d+\\.\\d+);')
var fIEVersion = parseFloat(RegExp['$1']) || -1 // 代表不是IE
return function(data) {
var _data = data || {}
var targetId = _data.targetId || null
var blurFn = _data.blur || null
if (!targetId) {
throw Error('targetId is cannot be null')
return false
}
var target = document.getElementById(targetId)
if (!target) {
throw Error(targetId + ' is does not exist')
return false
}
// IE 环境
if (fIEVersion >= 6 && fIEVersion <= 9) {
var parent = target.parentNode
var childLabel = document.createElement('label')
childLabel.setAttribute('class', 'label-placeholder')
childLabel.setAttribute('for', targetId)
childLabel.innerHTML = _data.placeholder || ''
parent.appendChild(childLabel)
target.onblur = function(event) {
blurFn && blurFn.call(this, event)
if (this.value != '') {
childLabel.style.display = 'none'
} else {
childLabel.style.display = ''
}
}
} else if (blurFn) {
// 非IE环境,不过有回调方法,直接注册回调方法
target.onblur = blurFn
}
}
})()
window.onload = function() {
initPlaceholder({
targetId: 'username',
placeholder: '请输入用户名',
blur: function(e) {
console.log(e)
console.log(this.value)
}
})
}
完整的 demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.form-item {
position: relative;
}
.label-placeholder {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
font-size: 14px;
text-align: left;
z-index: 10;
color: #999;
}
/* input聚焦的时候,lable自动隐藏 */
.form-item input:focus + .label-placeholder {
display: none;
}
</style>
</head>
<body>
<div class="form-item username">
<input name="username" placeholder="请输入用户名" id="username" />
</div>
<div class="form-item">
<input name="username" placeholder="请输入用户名" id="password" />
</div>
<script>
var initPlaceholder = (function() {
var userAgent = navigator.userAgent //取得浏览器的userAgent字符串
var isIE = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1 //判断是否IE<11浏览器
var reIE = new RegExp('MSIE (\\d+\\.\\d+);')
var fIEVersion = parseFloat(RegExp['$1']) || -1 // 代表不是IE
return function(data) {
var _data = data || {}
var targetId = _data.targetId || null
var blurFn = _data.blur || null
if (!targetId) {
throw Error('targetId is cannot be null')
return false
}
var target = document.getElementById(targetId)
if (!target) {
throw Error(targetId + ' is does not exist')
return false
}
// IE 环境
if (fIEVersion >= 7 && fIEVersion <= 10) {
var parent = target.parentNode
var childLabel = document.createElement('label')
childLabel.setAttribute('class', 'label-placeholder')
childLabel.setAttribute('for', targetId)
childLabel.innerHTML = _data.placeholder || ''
parent.appendChild(childLabel)
target.onblur = function(event) {
blurFn && blurFn.call(this, event)
if (this.value != '') {
childLabel.style.display = 'none'
} else {
childLabel.style.display = ''
}
}
} else if (blurFn) {
// 非IE环境,不过有回调方法,直接注册回调方法
target.onblur = blurFn
}
}
})()
window.onload = function() {
initPlaceholder({
targetId: 'username',
placeholder: '请输入用户名',
blur: function(e) {
console.log(e)
console.log(this.value)
}
})
initPlaceholder({
targetId: 'password',
placeholder: '请输入密码'
})
}
</script>
</body>
</html>
总结
对于 initPlaceholder 只是一个简单的封装,而且尽可能用 JS 原生语法,毕竟考虑到是 IE 浏览器
其次其实这个 demo 局限性还是很大的,比如 label
的文本并没有垂直居中,然而垂直居中最快的方式就是 line-height
。所以这个还是留给具体的业务场景,拿到高度,在设置line-height
.
其次这个方法必须依赖于 input 的父级 div,并且对应父级 div 还必须有相对定位
才可以
虽然局限性很大,不过对于能解决 IE 的问题,我觉得这已经是非常欣慰了~
上一篇: 蒋介石手下两大特务头子 为什么只有徐恩曾舒服的度过了一生
下一篇: PHP日期与时间戳