對HTML-input的一些思考和理解

原文連接:https://yunxiaomeng.blog.csdn.net/article/details/107575226css

背景html

前兩天在寫原生上傳文件時用到了input的 type="file" 按鈕,寫完之後就感受彆扭的一批:這玩意本身的樣式實在難看,可是它又不支持自定義樣式。最後「靈光一現」,想到:能夠設置其透明度爲 opacity: 0; 而後拿其餘的標籤覆蓋上去:好比 input type="text" 、好比 div、好比 label 。。。前端

項目地址:http://htmlpreview.github.io/?https://github.com/1314mxc/compress/blob/master/index.htmlgit

(這個工具中的全部「上傳框」皆是input) 最近正好在搞這個「圖片上傳」、「壓縮」的事情:H5之後,input就支持了accept —— 選擇文件類型,還有一些值好比:「multiple」 可設置「只選擇文件夾」。github

這兩個問題也造就了這篇文章:web

先說下input中的一些問題:瀏覽器

不是全部的 input 都支持「placeholder」,好比:type="date" 。嘗試了一下,雖然H5原生的date功能強大,但對placeholder還真沒有什麼解決方案。不過,參照本文開篇的思路,咱們一樣能夠先寫一個 type="text" ,而後用0級DOM事件 onfocus (在觸焦時)將其變爲date:onfocus="(this.type='date')" 。
這種方法在PC端簡直完美,但在一些手機上須要【點擊兩次】纔有效 —— 猜想可能仍是移動端響應click的問題。因此還有一種方案:在input上覆蓋一個div,當點擊時去操控 input 的事件和響應!微信

咱們都知道,在input中,當輸入過一次時,下一次輸入會有提示 —— autocomplete 。但這也會帶來一些效果:input 將背景「自動」變爲黃色。哦,這可不是什麼bug。是 input 對 paste 的響應樣式罷了。咱們能夠用「autocomplate='off'」 / 僞類:app

input:-webkit-autofill{
 -webkit-box-shadow: 0 0 0px 1000px white inset;
}

來去除效果。ide

上面這段CSS代碼意思爲:將邊框陰影設爲白色,而後向內擴展,覆蓋原來應該顯示的「黃色」。」
HTML5約束驗證
HTML5對於input增長了不少標籤屬性,和事件。其中最著名的莫過於「表單驗證validate」了:當你獲取到validitestate對象(經過DOM.validity)後,這裏面有幾個很重要的屬性:

  • willValidate:元素約束是否「被符合」,無則返回false
  • validity:當前元素驗證狀態
  • validationMessage:描述相關約束失敗 / 錯誤信息
  • checkValidity():有沒有知足任一約束(常被用在submit事件中)
  • setCustomValidity():設置自定義驗證提示信息
    裏面還有許多屬性都是和input中的屬性(字段)一一對應的:

對HTML-input的一些思考和理解
input還有一個比較「特別」的:search。這種類型的input,在輸入時右側會有一個「帶圓圈的×」,那麼確定會有人以爲不想要 or 很差看了,咱們也能夠用僞元素來將其去掉:

input[type="search"]::-webkit-search-cancel-button{
 -webkit-appearence: none;
 //下面可自定義樣式
}

一樣的還有input的button、普通input的邊框陰影均可以用相似代碼去除!」
看好了,上面是 -webkit前綴!幾乎不用想,在手機上必定會出現一些「彷佛莫名其妙的問題」:比較推薦的是,用div+absolute來從新寫一個「小叉號」,用JS控制對應事件。

這裏「比較推薦」是「在解決問題的辦法」中比較而得。事實上,仍是推薦用原生的「取消按鈕」。」
哦對了,既然有了maxlength,爲何W3C還保留了max?由於在 type="number" 中,maxlength是沒啥用的。。。(就很尷尬) 更尷尬的是:max只能控制「上限值」 —— 好比只能輸入5位,則寫爲:max="99999" ,並且他的效果仍是體現到「獲取到的值」上。這也就是說:你在沒有任何提示下,在你眼睛所能看到的input裏,你能夠輸入無限長度。

input的高度能夠用height或者padding來改變 —— 事實上,幾乎全部的行內(非替換)元素都是用padding改變高度的(行內替換元素能夠設置height)」
其實說了這麼多,HTML+CSS就能夠完成簡單的「表單校驗」:僞類「:valid」、「:invalid」直接做用到對應input上便可 —— 基於pattern + required的基礎功能驗證。

//HTML部分
<input id="mail" type="email" required placeholder="請輸入郵箱" />
<span class="title">郵箱</span>
<label for="mail"></label>
//css部分
input:focus,input:hover{text-indent: 2px;}
input:focus +span.title,input:hover +span.title{transform: translateX(-120%);}
input:valid ~label::after{content: '你輸入郵箱正確!';}
input:invalid ~label::after{content: '你輸入郵箱錯誤';}
input:valid{border: 1px solid green;}
input:invalid{border: 1px solid red;}

對HTML-input的一些思考和理解
甚至是用僞類 optional 、required 設置「選填」和「必填」的簡單樣式:

input:required +label::after{content:'(必填)';}
input:optional +label::after{content:'(選填)';}
input:required:focus{box-shadow: 0 0 3px 1px #aa0088;}
input:optional:focus{box-shadow: 0 0 3px 1px #999;}

你甚至能夠在input中加入0級DOM事件oninvalid,在其中直接調用 this.setCustomValidity("...") 來做爲填錯時提示。這很方便。

作完這些,你很滿意。可是你的UI設計師可能要發火了 —— 不一樣的提示框UI實在是太... 咱們須要自定義提示氣泡!

  1. 阻止自帶默認氣泡:
function stopBubble(form){
 form.addEventListener("invalid",function(e){
  e.preventDefault()
 },true)
 //submit事件中監聽:若是提交時驗證不經過
 form.addEventListener("submit",function(e){
  if(!this.checkValidity()){
   e.preventDefault()
  }
 },true)
}
  1. 自定義氣泡、JS生成DOM、插入(appendChild)與input同級、並觸發focus(xxx.focus())

    擴展Tip:

    • 如何設置了驗證(required/pattern/...)但不讓瀏覽器去驗證?
    • 兩個HTML屬性:novalidate(放在input上) / formnovalidate(放在提交按鈕上)

最後

  • 歡迎加我微信(winty230),拉你進技術羣,長期交流學習...
  • 歡迎關注「前端Q」,認真學前端,作個專業的技術人...
    對HTML-input的一些思考和理解
相關文章
相關標籤/搜索