手機開發webapp的同學一定遇到過這樣問題,如何為丑極了的手機元素應用自定義的樣式。首先,要弄清楚為什么要定義手機原生控件的樣式,就需要看看手機的那些原生框樣式的丑陋摸樣:
android:

ios:

無奈的選擇
看完了這些丑陋的界面元素,我們就可以理解當我們把他們暴露在產品同學的眼中時,那種層層的殺氣了。可以看到,界面元素十分丑陋,產品兄弟是肯定不會接受的。但是,不得不說這些控件在觸發后的效果比pc機上的要炫酷。這其中以apple機的滾筒選擇最為出色.以下是它們觸發后調用原生控件的效果:
android:



ios:



不得不說這些樣式原生彈出樣式是符合我們設計的原則的,因為它即體現了UI界面的友好和體驗度,又不損耗任何web性能,關鍵是我們什么都不需要做。產品BZJ君看到了,指明要在apple機下要滾筒的效果用來選擇日期或者下來單。如果我們不能解決掉界面文本框的樣式問題,那么無論后面的效果多炫酷,始終使無法讓人接受的。也許你會想花時間寫類似的效果?我不否認你可以寫出來,但是需要多少時間的工作量呢?也很多人選擇了插件的方式。通過jq插件(如果你的項目中沒在使用jq,為了這個效果無奈下載jq和其插件)來實現,其實是非常吃力不討好的事情。一個是插件這種東西出了問題或者變換了需求后它會變得異常的不好擴展,第二個當然是考慮到資源加載,在手機端尤其需要考慮。因此,選擇插件是下下策!
解決方法
問題來了,既想要彈出層的炫酷效果,又想自定義控件在界面顯示的樣式。怎么辦呢?露珠曾經嘗試過最簡單的方法去重寫css去改變它們的樣式,但是即使在google若干小時,也沒有找到滿意的結果。露珠也嘗試過-webkit-appearance屬性,但它也顯得不盡如人意。況且我們還需要兼容多機型(安卓,蘋果,wp?)。無論如何,走改變原始樣式的路是行不通的。露珠經過一番思考,找到了自認為非常好的解決方法,也是這篇博文的主題:既然控件在頁面的樣式不可以改變,那就隱藏它,但是!不是用display:none隱藏,也不是把width和height設置為0,我們希望的是看不到它們的原始樣式,而希望保留對它們的tap和focus事件。但是除了以上的方法,還有什么能使它們看不見呢?聰明的你一定想到了,對,就是opacit:0, 通過將控件的不透明度設置為0,我們可以讓元素繼續讓它留在界面上,並且保持隨時響應focus事件的狀態。我們要做的,是為該控件設置為絕對定位,覆蓋在我們自定義樣式的一個element上。這樣,用戶看到的是底下的element,但當他的手去觸碰此element時,他實際觸碰的是完全透明確留在界面上的原生控件!如下圖所示:

這還是第一步,接下來我們需要為控件綁定響應事件,大多數情況下我們需要綁定的事件都是onchange,一旦選擇完成,就把值復制到自定義的element上去。這樣大功告成了!不管你是通過表單或者post提交,你取到的值依然是控件的值,自定義的element只負責顯示,不負責業務!

代碼實現
<html>
<head>
<style>
body{
position: relative;
}
.front {
position: absolute;
opacity: 0;
height: 30px;
width: 180px;
}
.back {
height: 30px;
width: 386px;
border: 1px dashed #19a39e;
line-height: 30px;
text-align: center;
font-size: 11px;
}
</style>
</head>
<body>
<input type="date" class="front" onchange="document.getElementsByClassName('back')[0].innerHTML = this.value;">
<div class="back">我是自定義element,我上面覆蓋着一層看不見的input</div>
</body>
</html>
結束語
產品B君看到了丑陋的東西消失了,ios下的滾筒又炫酷滾起來了,肯定會拍拍你的肩膀說兄弟干得不錯。這篇博文也不僅僅是關於解決控件樣式的問題,在其他類似的情況下,用遮罩層的方法掩蓋你無能為力的地方是值得借鑒的。其實在開發中類似的的小花招很多,只要找到了訣竅和方法,一行代碼抵得上一萬行代碼(借用劉震雲的小說名)。雖然是個很小的小花招,大篇幅的用一篇博客來講解是過於誇張和繁瑣,不過前端開發事無巨細,希望對遇到類似問題或者將來需要解決的同學有幫助。
